Dokümantasyon Standartları (Doc Block'lar)
Drupal'da dokümantasyon, sonradan eklenen bir ayrıntı değil, kodun kendisinin bir parçası olarak görülür. api.drupal.org'daki API dokümantasyonu doğrudan kod tabanındaki doc block'lardan üretiliyor — kodlama standartlarının bu block'ların tam olarak nasıl yazılacağı konusunda bu kadar titiz olmasının nedeni de bu. Bu bölümde dosyalar, fonksiyonlar, sınıflar ve hook'lar için doc block'ları, satır içi yorumları ve kullanımdan kaldırma (deprecation) sürecinin nasıl işlediğini ele alıyoruz.
1. Genel Doc Block Kuralları
Doc block, /** ile açılan ve belgelediği şeyin hemen üzerinde, aralarında boş satır olmadan duran bir yorumdur.
- İçindeki her satır 80 karakterde kırılır.
- İlk satır her zaman nokta ile biten, tek satıra sığan bir özet cümlesidir ve asla satır sarmaz. Bu satır neyin ne yaptığını söyler, nasıl yaptığını değil.
- Özellikle fonksiyon ve method'larda bu özet üçüncü tekil şahısla, bir fiille başlar — "Builds…", "Returns…", "Checks…" gibi — "Build the form" ya da "This function builds…" şeklinde değil.
- Özetten sonra boş bir yorum satırı gelir, ardından varsa daha uzun açıklama, sonra bir boş satır daha ve etiket bölümü.
2. Dosya Doc Block'ları
Bir'den fazla önemsiz olmayan fonksiyon içeren her .php ya da .module dosyası, namespace tanımının üzerinde — ya da prosedürel bir dosyada ilk kod satırının üzerinde — bir dosya doc block'uyla açılır. Bu block'un görevi dosyanın ne içerdiğini anlatmaktır, tek tek fonksiyonların ne yaptığını değil.
/**
* Product Import modülü için hook implementasyonlarını içerir.
*/Bir dosya sadece tek bir sınıf tanımlıyorsa, ayrıca bir dosya doc block'una ihtiyaç duymaz — sınıfın kendi doc block'u bu işi zaten görür.
3. Fonksiyon ve Method Doc Block'ları
Tek satırlık özetin ardından boş bir yorum satırı, gerekiyorsa daha uzun bir açıklama, bir boş satır daha ve ardından her zaman @param, @return, @throws sırasıyla etiketler gelir.
/**
* Uzak API'den bir grup ürün kaydını içe aktarır.
*
* Var olan kayıtlar yerinde güncellenir; feed'de artık görünmeyen
* kayıtlar silinmez, olduğu gibi bırakılır.
*
* @param array $items
* Harici ID'ye göre anahtarlanmış ham ürün kayıtları.
* @param bool $overwrite
* Lokalde düzenlenmiş alanların üzerine yazılıp yazılmayacağı.
*
* @return int
* Oluşturulan veya güncellenen ürün sayısı.
*
* @throws \Drupal\product_import\Exception\ImportException
* Feed ayrıştırılamadığında fırlatılır.
*/
public function importProducts(array $items, bool $overwrite = FALSE): int {
}Her @param satırı parametrenin tipiyle açılır, ardından aynı satırda değişken adı gelir; açıklama ise altına iki boşluk girintili şekilde yazılır. Hiçbir şey döndürmeyen bir method ise @return'ü tamamen atlar — asla @return void olarak yazılmaz.
Bir method sadece üst sınıfın ya da arayüzün sözleşmesini yerine getiriyorsa ve kendi başına belgelenmeye değer bir şey eklemiyorsa, tek satırlık bir {@inheritdoc} block'u yeterlidir:
/**
* {@inheritdoc}
*/
public function label(): string {
}4. Sınıf ve Arayüz Doc Block'ları
Sınıf doc block'u, sınıfın adının başka kelimelerle tekrarı değil, sınıfın neyden sorumlu olduğunun açıklamasıdır. Arayüzler için de aynısı geçerlidir; arayüzdeki her public method kendi tam doc block'unu taşır, çünkü onu implemente eden sınıflar genelde açıklamayı tekrar etmek yerine {@inheritdoc} ile ona işaret eder.
/**
* Harici katalog API'sinden ürün kayıtlarını içe aktarır.
*/
class ProductImporter implements ProductImporterInterface {
}5. Hook Implementasyonu Doc Block'ları
Hook implementasyonları, hook sisteminin zaten başka bir yerde belgelediği şeyi yeniden anlatmak yerine, sadece hook'un adını veren kısa ve sabit formatlı bir özet alır:
// ❌ Yanlış: hook_cron()'un zaten belgelediği şeyi yeniden anlatıyor.
/**
* Her cron çalışmasında uzak feed'i yeni ürünler için kontrol eder
* ve bulduklarını teker teker içe aktarır.
*/
function product_import_cron() {
}
// ✅ Doğru: sadece hook'un adını veren kısa, sabit formatlı özet.
/**
* Implements hook_cron().
*/
function product_import_cron() {
}
/**
* Implements hook_form_FORM_ID_alter() for the node edit form.
*/
function product_import_form_node_form_alter(&$form, FormStateInterface $form_state) {
}Asıl davranış zaten core'daki hook'un kendi dokümantasyonunda yer alır — her implementasyonda tekrar etmeye gerek yok.
6. Satır İçi Yorumlar
Satır içi yorumlar neyin değil, neden yapıldığının açıklamasıdır — kod zaten ne yaptığını gösterir. // ile, tek bir boşlukla ve büyük harfle başlar, nokta ile biter. Kısa bir yorum bahsettiği satırın hemen üzerine yerleştirilebilir; daha uzun bir açıklama ise kendi paragraf tarzı block'unu hak eder.
// ❌ Yanlış: kodun zaten gösterdiğini tekrar ediyor.
// Dizideki tekrarlanan değerleri kaldırır.
$product_ids = array_unique($raw_ids);
// ✅ Doğru: kodun tek başına göstermediği "neden"i açıklıyor.
// API, birden fazla kategoride listelenen ürünler için
// tekrarlanan satırlar döndürüyor, bu yüzden kaydetmeden önce
// tekilleştiriyoruz.
$product_ids = array_unique($raw_ids);7. Kodu Kullanımdan Kaldırma
Bir şey değiştirilip de hemen kod tabanından sökülemiyorsa, @deprecated etiketiyle sabit bir formatta işaretlenir — kullanımdan kaldırıldığı sürüm, kaldırılacağı sürüm ve yerine ne kullanılması gerektiği.
/**
* Ürünün dahili adını döndürür.
*
* @deprecated in product_import:2.3.0 and is removed from
* product_import:3.0.0. Use
* \Drupal\product_import\Entity\Product::getDisplayName() instead.
*
* @see https://www.drupal.org/node/1234567
*/
public function getName(): string {
@trigger_error('getName() is deprecated in product_import:2.3.0 and is removed from product_import:3.0.0. Use getDisplayName() instead. See https://www.drupal.org/node/1234567', E_USER_DEPRECATED);
return $this->getDisplayName();
}Değişiklik kaydına (change record) işaret eden o @see satırı, insanların gerçekten geçiş yapmasını sağlayan şeydir — tek satırlık özet tek başına bunu anlatmaz.