Kodlama Stili

Aşağıdaki kod stili Cotonti CMF çekirdeği ve resmi uzantıların geliştirilmesi için kullanılır. Çekirdeğe talep kodu çekmek istiyorsanız, bunu kullanmayı düşünün. Cotonti'ye dayalı uygulamanız için sizi bu kod stilini kullanmaya zorlamıyoruz. Size daha uygun olanı seçmekte özgürsünüz.

#1. Genel kurallar

Bu genel kurallar, başka bir kural tanımlanmamışsa, projedeki tüm kaynak kodu dosyalarını (HTML, PHP, CSS, JS, vb.) dikkate alır.

  • Kod dosyaları BOM olmadan yalnızca UTF-8 kodlamasını KULLANMALIDIR.
  • Yeni satır LF olmalıdır. 
  • Girinti için sekme değil 4 boşluk kullanılmalıdır.
  • Satırların sonunda fazladan boşluk olmamalıdır (metin düzenleyicinizi kaydederken fazladan boşlukları kaldıracak şekilde ayarlayın).

Satır uzunluğu konusunda kesin bir sınır yoktur. Kodunuzdaki her metin satırı en fazla 120 karakter uzunluğunda olmalıdır.  
Satır sonunu, 120 karaktere en yakın kırılma noktası olmak zorunda değil, en estetik anlam ifade eden yere koyun.

 

#2. PHP Kılavuzları

#2.1. Kısa Bir Bakış

…genel kurallara ek olarak

PHP kodu, PSR-12, PSR-1 kodlama standartlarını ve PSR-4 otomatik yükleme standardını takip etmelidir.

Eğer PhpStorm kullanıyorsanız, gerekli kod stilini korumanıza yardımcı olabilir. Bunu açmak için AyarlarEditörKod StiliPHPŞuradan AyarlaPSR12 yolunu izleyebilirsiniz.

  • PHP kodu <?php veya <?= açılış etiketlerini kullanmalı ve <? gibi diğer etiket varyasyonlarını kullanmamalıdır.
  • Eğer dosya yalnızca PHP içeriyorsa, sonunda ?> etiketi olmamalıdır.
  • Artırma/azaltma operatörleri hariç, tüm operatörlerin etrafında bir boşluk kullanılmalıdır. Örneğin: $a + $b, $string = $foo . 'bar', $i++, ancak $a+$b gibi değil.
  • Virgülden sonra bir boşluk bırakılmalıdır: $one, $two, ancak $one,$two şeklinde değil.
  • Kesin eşitlik === (ve eşitsizlik !==) kullanılmalıdır.
  • Yeni dosyalarda declare(strict_types=1); yönergesi ile sıkı tür belirlemenin etkinleştirilmesi önerilir.
  • Tek satırlık yorumlar // ile başlamalıdır, # ile değil.
  • Global değişkenler kullanmaktan kaçının. Tanımsız değişkenler kullanmayın.

#2.2. Dokümantasyon

  • Dokümantasyon söz dizimi için PHPDoc kaynağına bakın.
  • Dokümantasyonsuz kodlara izin verilmez.
  • Tüm sınıf dosyalarının her dosyanın en üstünde "dosya seviyesinde" bir docblock ve her sınıfın hemen üzerinde "sınıf seviyesinde" bir docblock içermesi gerekir.

Dosya Başlığı

Tüm PHP dosyaları, PHPDoc biçiminde bazı dokümantasyon bilgileri içermelidir.

Başlığın, bu dosyada kullanılan ancak başka bir yerde tanımlanan değişkenleri açıklaması çok iyidir.

Yeni dosyalar için standart başlık (bu başlık şablonu tüm Cotonti dosyalarının başlangıcına eklenmelidir):

PHP
1
2
3
4
5
6
7
8
9
/**
 * @package {PACKAGENAME}
 * @version {VERSION}
 * @copyright (c) 2008-2023 Cotonti Team
 * @license BSD License
 *
 * @var array<string, mixed> $user
 * @var XTemplate $t
 */

@version etiketi isteğe bağlıdır. Örneğin, bir eklenti geliştiriyorsanız, sürüm bilgisi zaten eklenti kurulum dosyasında tanımlandığı için @version etiketini belirtmenize gerek yoktur ve bu diğer geliştiricileri yanıltabilir.

Sınıflar

Sınıfı yorumlamayı unutmayın. Sınıfların ayrı bir @package tanımı olması gerekir, bu, başlık paket adıyla aynıdır.

PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
/**
 * Cotonti MySQL Veritabanı adaptör sınıfı.
 * Standart PHP PDO sınıfına, Cotonti'ye özgü bazı ihtiyaçları karşılayan
 * küçük bir eklenti, kullanışlı fonksiyonlar ve sorgu oluşturucu içerir.
 *
 * @package cotonti
 *
 * @property-read int $affectedRows Son sorgudan etkilenen satır sayısı
 * @property-read int $count Toplam sorgu sayısı
 * @property-read int $timeCount Toplam sorgu yürütme süresi
 */
class MySQL extends Adapter

Metotlar ve Fonksiyonlar

Fonksiyonları yorumlamayı unutmayın. Her fonksiyonun en azından ne yaptığına dair bir açıklaması olmalıdır. Ayrıca parametreleri de belgelemek önerilir. @param, @return, @throws sırasıyla kullanın.

PHP
1
2
3
4
5
6
7
/**
 * Bir tabloda bulunan toplam kayıt sayısını döndürür.
 * @param string $tableName Tablo adı
 * @return int
 * @throws Exception Eğer tablo adı mevcutsa
 */
public function countRows($tableName)

Yerel türlerin kullanımı nedeniyle @param veya @return etiketleri gereksiz olduğunda, bunlar atlanabilir:

PHP
1
2
3
4
5
6
7
/**
 * Görevi yürütür.
 */
public function handle(AudioProcessor $processor): void
{
    //
}

Ancak, yerel tür jenerik olduğunda, jenerik türü @param veya @return etiketleri ile belirtin:

PHP
1
2
3
4
5
6
7
8
/**
 * Gönderiye ait ekleri alır.
 * @return array<int, Attachment>
 */
public function attachments(int $postId): array
{
    // ...
}

#2.3. Sınıf, Fonksiyon ve Değişken Adlandırma

Tüm adlar açıklayıcı ancak öz olmalıdır. Bir sınıfın veya değişkenin adını gördüğünüzde, ne için kullanıldıkları açık olmalıdır. Örneğin: $CurrentUser, getUserData($id).

Sınıf adları PascalCase formatında olmalıdır. Örneğin: Controller, Model.

Sabitler tamamen büyük harflerle ve alt çizgi ayracı kullanılarak tanımlanmalıdır. Örneğin: STATUS_PUBLISHED.

Dizin/namespace adları küçük harflerle yazılmalıdır.

Sınıfın özel (private) özelliklerini ve metotlarını belirtmek için alt çizgi kullanılmaz.

Değişken Adlandırma

Değişken adları camelCase biçiminde olmalıdır. İlk kelime küçük harfle başlamalı ve sonraki her kelime büyük harfle başlamalıdır. Örneğin: $currentUser doğrudur, ancak $current_user ve $currentuser yanlıştır.

Tek karakterli değişken adlarının kullanılabileceği durumlar: dil dizgeleri: $L, dizge kaynakları: $R ve bir döngü yapısının indeks değişkeni olarak kullanıldığında.

Döngü İndeksleri:
Dış döngünün indeksi her zaman $i olmalıdır. Eğer içinde bir döngü daha varsa, onun indeksi $j, ardından $k ve böyle devam eder. Eğer döngü zaten anlamlı bir isimle tanımlanmış bir değişken tarafından indeksleniyorsa, bu kural uygulanmaz. Örnek:

PHP
1
2
3
4
5
for ($i = 0; $i < $outerSize; $i++) {
  for ($j = 0; $j < $innerSize; $j++) {
    foo($i, $j);
  }
}

Fonksiyon ve Metot Adları

Fonksiyon ve metot adları camelCase formatında olmalıdır. İstisna olarak, Cotonti çekirdek fonksiyonları farklı olabilir. İyi fonksiyon adları şunlardır: printLoginStatus(), getUserData() vb.

Cotonti içinde, isim çakışmalarını önlemek için tüm fonksiyonlarda standart cot_ öneki kullanılır. Çekirdek API’nin yeniden kullanılabilir olması için bu bir standarttır: cot_mailPrepareAddress($address).

Ancak, eğer fonksiyonlarınızı yalnızca kendi eklentiniz içinde kullanacaksanız, cot_ önekini kullanmanız zorunlu değildir. Eklenti API’niz içinde kendi önekinizi kullanabilirsiniz.

Fonksiyon Argümanları değişken adlarıyla aynı kurallara tabidir.

Özet

Buradaki temel felsefe, tembellik uğruna kodun açıklığını bozmamaktır. Ancak, bu biraz sağduyu ile dengelenmelidir: Örneğin, printLoginStatusForAGivenUser() çok uzun bir isim olur, bunun yerine printUserLoginStatus() veya sadece printLoginStatus() daha iyi bir seçimdir.

#2.4. Türler

Tüm PHP türleri ve değerleri küçük harflerle kullanılmalıdır. Buna true, false, null dahildir.

Tür dönüşümü için fonksiyonlar yerine operatörleri kullanıyoruz. Sadece kısa formlarını kullanıyoruz ve operatörden sonra bir boşluk bırakıyoruz.

PHP
1
2
3
4
5
$value1 = (int) $argument1;     // doğru
$value2 = (bool) $argument2;    // doğru
 
$value3 = (integer) $argument3// yanlış
$value4 = intval($argument2, 8); // sadece gerçekten gerekli ise

Var olan bir değişkenin türünü değiştirmek kötü bir uygulama olarak kabul edilir. Gerçekten gerekmedikçe bu tür kod yazmaktan kaçının.

PHP
1
2
3
4
5
public function save(Transaction $transaction, int $argument2 = 100)
{
  $transaction = new Connection; // kötü
  $argument2 = 200; // iyi
}

#2.5. Stringler

Eğer string içinde değişkenler veya tek tırnak bulunmuyorsa, tek tırnak kullanın.

PHP
1
$str = 'Böyle olmalı.';

Eğer string içinde tek tırnak varsa, fazladan kaçış karakteri kullanmamak için çift tırnak kullanabilirsiniz.

Değişken yerleştirme:

PHP
1
2
$str1 = "Merhaba $username!";
$str2 = "Merhaba {$username}!";

Aşağıdaki kullanım izin verilmez:

1
$str3 = "Merhaba ${username}!";

Bitişik ekleme (Concatenation)

Stringleri birleştirirken nokta operatörünün etrafına boşluk bırakın:

PHP
1
$name = 'Cotonti' . ' CMF';

Eğer string uzun ise şu format kullanılmalıdır:

PHP
1
2
3
$sql = 'SELECT * '
. 'FROM post '
. 'WHERE id = 121 ';

#2.6. Diziler

Diziler için kısa dizi sözdizimini kullanıyoruz.

PHP
1
$arr = [3, 14, 15, 'Cotonti', 'CMF'];

Eğer bir satıra sığmayacak kadar çok eleman varsa, her eleman ayrı bir satıra yerleştirilir. Son elemenden sonra bir virgül konulur.

PHP
1
2
3
4
5
$mail = [
  'to'  => 'user@domain.com',
  'from' => ['admin@site.com', 'SiteTitle'],
  'cc' => [['user2@example.com', 'User2'], 'user3@example.com', 'User4 '],
];

#2.7. Kontrol Yapıları

  • Kontrol ifadelerinin parantezlerinden önce ve sonra bir boşluk olmalıdır.
  • Parantez içindeki operatörler bir boşluk ile ayrılmalıdır.
  • Açılış süslü parantezi aynı satırda olmalıdır.
  • Kapanış süslü parantezi, gövdenin bulunduğu satırdan sonraki satıra yerleştirilmelidir.
  • Tek satırlık ifadeler için her zaman süslü parantez kullanılmalıdır.

if, elseif, else

PHP
1
2
3
4
5
6
7
8
9
10
if ($expr1) {
  // if gövdesi
} elseif ($expr2) {
  // elseif gövdesi
} else {
  // else gövdesi;
}
 
// Aşağıdaki kullanım YASAKTIR:
if (!$model && null === $event) throw new Exception('test');

elseif anahtar kelimesi, tüm kontrol yapısı anahtar kelimelerinin tek kelime gibi görünmesini sağlamak için else if yerine kullanılmalıdır.

Parantez içindeki ifadeler, her bir sonraki satır en az bir kez girintilenerek birden fazla satıra bölünebilir. Bunu yaparken, ilk koşul bir sonraki satırda olmalıdır. Kapanış parantezi ve açılış süslü parantez, kendi satırlarında bir boşluk ile yerleştirilmelidir. Koşullar arasındaki mantıksal operatörler (&&, ||) satır başında olmalıdır.

PHP
1
2
3
4
5
6
if (
  $expr1
  && $expr2
) {
  // if gövdesi
}

return kullanıldıktan sonra mümkünse else kullanımından kaçınılmalıdır:

PHP
1
2
3
4
5
6
$result = $this->getResult();
if (empty($result)) {
  return false;
} else {
  // sonucu işle
}

Bunun yerine şu şekilde yazılmalıdır:

PHP
1
2
3
4
5
6
$result = $this->getResult();
if (empty($result)) {
  return false;
}
 
// sonucu işle

switch, case

switch yapısı aşağıdaki gibi olmalıdır. Parantezlerin, boşlukların ve süslü parantezlerin yerleşimine dikkat edin.

PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
switch ($expr) {
  case 0:
    echo 'Birinci durum, break ile sonlandırılıyor';
    break;
  case 1:
    echo 'İkinci durum, break içermiyor ve devam ediyor';
    // break yok
  case 2:
  case 3:
  case 4:
    echo 'Üçüncü durum, break yerine return kullanıyor';
    return;
  default:
    echo 'Varsayılan durum';
}

Üçlü Operatör (Ternary Operator)

Üçlü operatörler yalnızca çok basit işlemler için kullanılmalıdır. Tercihen sadece atama işlemlerinde kullanılmalı, fonksiyon çağrıları veya karmaşık işlemler için tercih edilmemelidir. Yanlış kullanıldığında okunabilirliğe zarar verebilir, bu yüzden yazım tasarrufu yapmak uğruna yanlış kullanımdan kaçının. Örnekler:

PHP
1
2
3
4
5
// Kullanım için kötü bir örnek
($i < $size && $j > $size) ? do_stuff($foo) : do_stuff($bar);
 
// Kullanım için uygun bir örnek
$min = ($i < $j) ? $i : $j;

#2.8. Sınıflar

"Sınıf" terimi, tüm sınıfları, arayüzleri ve trait'leri kapsar.

  • Sınıfın açılış süslü parantezi kendi satırında olmalıdır; kapanış süslü parantezi, gövdenin yer aldığı satırdan sonraki satırda olmalıdır.
  • Sınıf adları PascalCase formatında olmalıdır.
  • Her sınıf, PHPDoc standartlarına uygun bir dokümantasyon bloğuna sahip olmalıdır.
  • Tek bir PHP dosyasında yalnızca bir sınıf olmalıdır.
  • Tüm sınıflar bir namespace içerisinde tanımlanmalıdır.
  • Tüm özellikler (property) ve metotlar için erişim belirleyicisi (visibility) tanımlanmalıdır.
  • extends ve implements anahtar kelimeleri, sınıf adıyla aynı satırda olmalıdır. implements listesindeki her öğe ayrı bir satıra yerleştirilebilir ve her satır bir kez girintilenmelidir. Böyle yapıldığında, listedeki ilk öğe yeni bir satırda olmalı ve her satırda yalnızca bir arayüz bulunmalıdır.

Özellikler (Properties)

Public ve protected değişkenler, herhangi bir metodun tanımlanmasından önce sınıfın en üstünde tanımlanmalıdır. Private değişkenler de sınıfın en üstünde tanımlanmalıdır, ancak yalnızca belirli birkaç metoda özgü olduklarında, ilgili metotların hemen önüne de eklenebilir.

Metotlar ve Fonksiyonlar

Bir fonksiyonun açılış süslü parantezi, fonksiyon tanımının yer aldığı satırdan sonraki satırda olmalı ve kapanış süslü parantezi fonksiyon gövdesinden sonra yeni bir satıra yerleştirilmelidir.

Parametre listesindeki her virgülden sonra bir boşluk bırakılmalıdır.

PHP
1
2
3
4
function foo(int $arg1, string &$arg2, array $arg3 = [])
{
  // fonksiyon gövdesi
}

Argüman listeleri, sonraki her satırın bir kez girintilendiği birden fazla satıra bölünebilir. Bunu yaparken, listedeki ilk öğe bir sonraki satırda OLMALIDIR ve satır başına yalnızca bir argüman OLMALIDIR.

PHP
1
2
3
4
5
6
7
public function aVeryLongMethodName(
  ClassTypeHint $arg1,
  string &$arg2,
  array $arg3 = []
) {
  // metot gövdesi
}

Metotlar/fonksiyonlar tanımlanırken, her zaman parametrelerin ve dönüş değerlerinin yerel türlerini belirtin:

PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// Doğru
/**
 * Görevi yürütür.
 */
public function handle(AudioProcessor $processor): void
{
    //
}
 
 
// Yanlış
/**
 * Görevi yürütür.
 * @param AudioProcessor processor
 * @return void
 */
public function handle($processor)
{
    //
}
 
// Kötü
/**
 * Görevi yürütür.
 */
public function handle($processor)
{
    //
}

Bir metot veya fonksiyon çağrılırken, metot veya fonksiyon adı ile açılış parantezi arasında boşluk OLMAMALIDIR, açılış parantezinden sonra boşluk OLMAMALIDIR ve kapanış parantezinden önce boşluk OLMAMALIDIR. Parametre listesindeki her virgülden önce boşluk OLMAMALI, ancak virgülden sonra bir boşluk bulunmalıdır.

#3. SQL Kuralları

SQL ifadeleri genellikle okunaklı olması için biçimlendirme gerektirir, çünkü bazen oldukça uzun olabilirler. SQL ifadelerinin okunaklılığını artırmak için şu şekilde biçimlendirilmelidir:

PHP
1
2
3
4
5
$sql = 'SELECT p.*, u.* '
    . 'FROM ' . Cot::$db->pages . ' AS p '
    . 'LEFT JOIN ' . Cot::$db->pages . ' AS u ON u.user_id = p.page_ownerid '
    . "WHERE p.page_ownerid = 1 AND p.page_cat = 'news' "
    . 'LIMIT 10';

Kullanıcı girdilerini güvenli bir şekilde sorguya eklemek için parametreler kullanın (değişkeninizin tek tırnak içeremeyeceğinden emin olsanız bile, girdiye asla güvenmeyin):

PHP
1
2
3
4
$result = Cot::$db->query(
  'SELECT * FROM ' . Cot::$db->forum_topics . ' WHERE ft_cat = :cat  AND ft_id = :topicId',
  ['cat' => $section, 'topicId' => $param]
);

Veritabanına Özgü SQL Kullanımından Kaçının

  • Eşit olmayan (!=) operatörü SQL-92 standardına göre <> olarak tanımlanmıştır. Çoğu veritabanı != operatörünü destekler ancak <> kullanımı önerilir.
  • INSERT ... ON DUPLICATE KEY UPDATE sadece MySQL'e özgü bir eklentidir.
  • Tablo ve sütun adları için geri tırnak işareti (`) kullanımı MySQL'e özgüdür. Bunun yerine CotDB::quoteTableName() ve CotDB::quoteColumnName() veya bunların kısa versiyonları CotDB::quoteT(), CotDB::quoteC() kullanın.

#4. Javascript Kuralları

  • Sınıflar, üye değişkenleri ve metotlar için JSDoc kullanın.
  • Dokümantasyon, yorumlama ve adlandırma kuralları PHP için belirtilen kurallarla aynıdır.
  • jQuery'yi gereksiz yere kullanmayın.
  • Değişkenleri tanımlamak için let, sabitleri tanımlamak için const kullanın.
  • Program boyunca sabit kalan değerler tamamen büyük harfle ve kelimeler arasında alt çizgi olacak şekilde tanımlanmalıdır. Örneğin: const COLOR_ORANGE = "#ffa500". Sabitler gibi değişmeyen ancak farklı fonksiyon çağrılarında farklı değerler alabilecek değişkenler için const kullanmalı ve camelCase formatında adlandırılmalıdır.
  • Noktalı virgüller her zaman satır sonunda yer almalıdır.
  • Her zaman kesin eşitlik operatörü === (eşitsizlik için !==) kullanılmalıdır.

#4.1. Stringler

  • Tek tırnak kullanın: let single = 'single-quoted';.
  • Eğer string içinde tek tırnak varsa, çift tırnak kullanarak fazladan kaçış karakteri kullanmaktan kaçının.
  • İfade yerleştirmek için backtick (``) kullanın: alert(`1 + 2 = ${sum(1, 2)}.`); // 1 + 2 = 3..

#5. Faydalı Bağlantılar ve Araçlar

 

Önceki kodlama stili sürümü



1. Kabak  2023-06-01 05:25

Насчёт стиля по закрывающим фигурным скобкам - очень спорный вопрос.  Мне удобнее когда скобки находятся друг над или под другом - сразу видно какая скобка к чему относится и компиляторы подсвечивают блоки кода и таким образом расположенные скобки. У вас почему-то приняли за ствндарт когда открывающая скобка в конце строки открывающей блок кода , а закрываюзщая где-то там под блоком.  По-моему это плохой стиль для таких блоков.

2. Dayver  2023-06-01 20:52

Касательно расположения скобок я того же мнения + привык за всю историю существования кота именно к такому положению. Но принятый за основу psr-12 гласит именно о таком "кривом" расположении ... типа этот стандарт международно признаный ... 

3. Kort  2023-06-12 11:16

Предлагаемый вариант с фигурными скобками хорош тем, что экономит место на экране. Занимать целую строку открывающей скобкой так себе дело. Плюс практически в любом редакторе есть индикация закрывающей/открывающей скобки. Так что здесь рациональнее именно так.

По замене табуляторов на 4 пробела не совсем интересно. Хотя табуляторы в разных редакторах имеют разную длину, так что пробелами нерационально, зато гарантировано ровно будет. ((

Yalnızca kayıtlı kullanıcılar yorum yapabilir