BÖLÜM 2 PHP KODLAMA STANDARTLARI İSİMLER: Konuya uyan isimler seçin. İsimler programcılığın kalbidir. Eğer bir şey için doğru ismin ne olması gerektiğini biliyorsanız, kendinize ve sizden sonra gelecek programcılara kod üzerinde kullanabilecekleri büyük bir güç veriyorsunuz demektir. Bir isim, içinde bulunduğu çevre hakkında uzun ve derin bir düşünme sürecinin ürünüdür. Sadece bir sistemin bütün olarak çalışma prensibini tam olarak anlayan bir programcı sisteme tam anlamıyla uyan isimler bulabilir. Eğer isim uygunsa geri kalan her şey doğal bir şekilde uyacaktır. Bu sayede ilişkiler açık, anlamlar ulaşılabilir, ve insancıl beklentilerden yola çıkarak ulaşılan sonuçlar anlamlı olacaktır. Eğer kodunuza baktığınızda isimleri 'sey', 'birsey', 'bunu_yap','suraya_git', 'onu_calistir' gibi isimlerle değiştirdiğinizde bir şey fark etmeyecek gibi geliyorsa, o kodun dizaynına bir daha göz atsanız iyi olur. Sınıf İsimleri * Sınıfın ismini, sınıfın ne olduğuna bakarak verin. Eğer isim bulmak konusunda çok uğraşıyorsanız bu sisteminizin dizaynına yeteri kadar zaman harcamadığınızın bir belirtisidir. * Üç kelimeden fazla birleşik isimler sistem dizaynınızın bazı şeyleri bir birine karıştırıyor olabileceğinin bir habercisidir. Dizaynınızı tekrar gözden geçirin. Bir CRC kartı oturumuyla objelerinizin gereğinden fazla sorumluluklarla yüklenmiş olup olmadığını kontrol edin. * Bir sınıftan kalıtım/miras yoluyla (inheritance) başka bir sınıf oluşturduğunuzda ana sınıfın ismini alt sınıfın ismi içinde kullanmaktan kaçının. Eğer bir sınıfınız varsa o sınıf kendi ayakları üzerinde durabilmelidir. Hangi başka sınıftan oluşturulmuş olduğu önemli olmamalıdır. * Eğer sınıflarınız bir ortak başlık altında toplanabilir nitelikte ise, yani benzer bir amaca hizmet ediyorlarsa bu sınıfları belli bir başlık altında toplamak da mümkündür. Örneğin birkaç 'motor' sınıfınız olduğunu düşünürsek, SorguMotoru, AramaMotoru gibi sınıf isimleri kullanılabilir. Metot ve Fonksiyon İsimleri: * Genellikle bütün metot ve fonksiyonlar bir aktivite gerçekleştirirler, bu yüzden isimleri de gerçekleştirdikleri aktiviteyi belirtir nitelikte olmalıdır. Örneğin, HataKontrol() yerine HataKontroluYap(), VeriDosyasi() yerine 5
VeriDosyasinaCıktıYap() kullanılmalıdır. Bu kullanım şekli değişken objelerinin ve fonksiyonların birbirine karışmasını da engelleyecektir. * Bazen sona eklenen kısaltmalardan yararlanılabilir. - MAX : Bir değişkenin alabileceği Maksimum değerden bahsederken. - Cnt : Bir sayaç değişkeninin o anki değerinizden bahsederken ( Sayaç = Counter ) - Key : Bir anahtar değer ( Anahtar = Key ) Örneğin: TekrarMax - Maksimum tekrar sayısı, TekrarCnt - Şu anki tekrar sayısı gibi kullanılabilir. * Bazen başa eklenen kısaltmalardan da yararlanılabilir. Tamamı Büyük Harf Olan Kısaltmalar Kullanmayın: * Normalde tamamı büyük harften oluşan kısaltmaları bir isimde kullanmanız gerektiğinde bu kısaltmanın sadece ilk harfini büyük yapıp gerisini küçük harfler devam edin. Örneğin: 'YeniHTMLSayfasi' yerine 'YeniHtmlSayfasi' kullanın. : * Tamamı büyük harflerden oluşan kısaltmaları isim olarak kullanırken herkes farklı bir tarz izlemektedir. İsimlerin ne anlama geldiğini tahmin edebilmek açısından sadece bir tarzı kullanmak gereklidir. Örneğin NetworkABCKey isminde ABC'den gelen C ile Key'den gelen K karışmış durumdadır. Bazı programcıları rahatsız etmeyen bu durum diğerlerini rahatsız edebilmektedir. Bu yüzden değişik kişiler tarafından yazılmış kod örneklerinde bu konuya değişik yaklaşımlar görebilirsiniz. ler: class FluidOz // FluidOZ değil class GetHtmlStatistics // GetHTMLStatistics değil Sınıf İsimleri Kelime ayracı olarak büyük harf kullanıp kelimelerin devamını küçük harflerle getiriniz. Bir ismin ilk karakteri büyük harf olmalıdır. Alt çizgi kullanmayınız (' _ ') 6
Değişik isimlendirme şekilleri arasından yukarıda belirtilen şekil büyük bir çoğunluk tarafından verilen tavizler ve kullanışlılık dengesi açısından en iyi olarak benimsenmiştir. class IsimBirIki class Isim Sınıf Kitaplığı (class library) İsimleri * İsim boşluğu/uzayı/alanı (Name Space) kavramının kullanımı iyice gelişmekte olduğu için farklı üretici ve guruplar tarafından hazırlanmış kitaplıklar arasında sınıf isimleri çakışmasını önlemek için bu isim boşluğu/uzayı/alanı kavramından yararlanmak gerekmektedir. * İsim boşluğu/uzayı/alanı kullanılmadığı zaman genelde sınıf isimleri özel bir string ile başlatılarak çakışmalar önlenir. Genelde başa gelen bu string için iki karakter yeterli olsa da daha uzun bir string de kullanılabilir. Metot İsimleri * Yukarıdaki sınıf isimleri ile aynı kurallar geçerlidir. class IsimBirIki function DoIt() ; function HataKontrolEt() ; Sınıf Değişkeni İsimleri (class attribute) Sınıfa ait (member) değişken isimleri 'm' karakteri ile başlamalıdır. 'm' karakterinden sonraki kısım sınıf isimleri ile aynı kurallara uymalıdır. 'm' diğer bütün isim başlangıçlarından önce gelir. Örneğin referans için kullanılacak olan 'r' harfinden önce gelmelidir. * İsme 'm' ile başlamak metot isimleri ile meydana gelebilecek olası bir çakışmayı önler. Çoğu zaman kullandığınız metot ve değişken isimleriniz benzer olacaktır. 7
class IsimBirIki function VarAbc() ; function ErrorNumber() ; var $mvarabc; var $merrornumber; var $mrname; Metot Arguman İsimleri (method argument) İlk karakter küçük harf olmalıdır. İlk harften sonraki her yeni kelime başlangıcı sınıf isimlerinde olduğu gibi büyük harfle başlamalıdır. Bu sayede hangi değişkenlerin fonksiyon çağrısı içinden geldiği anlaşılır. class IsimBirIki function StartYourEngines(&$someEngine, &$anotherengine) $this->msomeengine = $someengine; $this->manotherengine = $anotherengine; var $msomeengine; var $manotherengine; Değişken İsimleri * Sadece küçük harflerden oluşan isimler kullanınız. * '_' karakterini kelime ayracı olarak kullanınız. * Bu yaklaşımda değişkenin yaşam/erişilebilme alanı (scope) açık olarak görülebilir. * Bütün değişken çeşitleri farklı olarak kullanıldığı için bunları ayırdetmek kolaylaşır. 8
function HandleError($errorNumber) $error = OsErr(); $time_of_error = OsErr->getTimeOfError(); $error_processor = OsErr->getErrorProcessor(); Referans Değişkenleri ve Sonuç Olarak Referans Veren Fonksiyonlar * Referanslar 'r' karakteri ile başlamalıdır. * Referans tipleri arasındaki farklar belirginleşir. * Sonuç olarak manipüle edilebilir bir obje veren bir fonksiyon ile sonuç olarak kodifiye edilemez bir obje veren aynı fonksiyonun ayırt edilmesi sağlanır. class Test var $mrstatus; function DoSomething(&$rStatus) ; function &rstatus() ; Global Değişkenler * Global değişkenler 'g' karakteri ile başlamalıdır. * Bir değişkenin erişim/yaşam alanının bilinmesi önemlidir. global $glog; global $grlog; // bu örnekte bir de referans için 'r' karakteri var. Tanımlanan İsimler ve Global Sabitler * Global sabit isimlerinin tamamı büyük harf ve '_' kelime ayracı kullanılarak yazılmalıdır. 9
Global sabitlerin bu şekilde isimlendirilmeleri geleneksel bir yöntemdir. Bunu kullanırken diğer tanımlanmış global isimleri ve ENUM etiketleri ile karışmamasına dikkat ediniz. define("a_global_sabit", "Merhaba Türkiye!"); Durağan (Static) Değişkenler * Durağan (Static) değişken isimleri 's' karakteri ile başlamalıdır. * Değişkenlerin yasam/erişim alanlarını bilmek önemlidir. function test() static $msstatus = 0; Fonksiyon İsimleri * PHP fonksiyonları için C GNU tarzı tamamı küçük harf olan '_' karakterinin kelime ayracı olarak kullanıldığı isimler kullanın. * Bu kullanış şekli fonksiyon isimlerini diğer bütün sınıf ile alakalı isimlerden ayırır. function her_hangi_bir_fonksiyon() Fonksiyonlardan Alınan Hataları Kontrol İşlemi: Hataları dikkate almamak istediğinizden emin olduğunuz durumlar dışında bütün sistem ve fonksiyon çağrılarını hatalar için kontrol ediniz. 10
Bütün sistem hataları için sistem hata mesajı metnini de alınız. Bağlama İşareti İşlemi Sıkça kullanılan 3 çeşit bağlama işareti kullanım tarzından ilk ikisi geçerli olmasına rağmen mümkün oldukça ilk tarz kullanılmalıdır. Bağlama işaretini ifadenin altına ve ifade ile aynı hizaya getiriniz. if($kosul)... while($kosul)... Geleneksel Unix tarzı olan açılış bağlama işaretinin ifade ile aynı satırda kullanılması. (K&R stili de denir) if($kosul)... while($kosul)... Hangi bağlama işareti tarzının kullanılacağı ancak taviz verilerek çözülebilecek bir sorun. Her iki tarz da kabul edilebilir olsa da çoğu kişi ilk kullanış şeklini daha uygun bulmaktadır. İlk tarz bağlama işaretinin nerede açılıp nerede kapandığını kolayca görebilmek için çok kullanışlıdır. İkinci tarzı kullananlar genelde bir ekrana daha fazla kod sığdırma avantajından yararlanmak isteyenlerdir. 11
Satır Başı, TAB ve Boşluk İşlemi Satır başını her seviyede 3,4 boşluk olarak kullanın. TAB yerine boşluk kullanın. Bir çok editör TAB ı boşluk karakterlerinden oluşan bir duruma getirebilmektedir. Gerektiği kadar satır başı bırakın. Üst üste tekrarlanan satır başları konusunda bir üst sınır olmasa da eğer 4,5 seviyeden fazla satır başı bıraktıysanız kodunuzu tekrar gözden geçirin. Herkes TAB için farklı değerler kullandığı için TAB kullanılmış bir kodu başka bir ortamda okumak veya yazıcıyla basmak çok zorlaşmaktadır. Bu yüzden farklı ortamlarda değişiklik göstermeyecek olan boşluk karakteri kullanılmalıdır. Boşluk sayısı hakkında herkesin kabul ettiği bir standart yoktur. Tutarlı ve sürekli aynı sayıda boşluk kullanılması yeterlidir. Bununla birlikte genelde 3,4 boşluk uygun görülmektedir. Her ne kadar satır başı seviyesi sayısını sınırlamak isteseniz de pratikte bu içinden çıkılamayacak bir sınırlamadır. Bu yüzden ne kadar iç içe yerleştirilmiş kod blokları yazacakları konusunda programcıların kendi düşüncelerine güvenmek gerekmektedir. function fonksiyon() if (ilk kosul) if (baska bir kosul) while (daha da fazla kosullar) not: (Konu sistemindeki sınırlamadan dolayı yukarıdaki kod istendiği gibi gösterilememektedir. Normalde her kod bloğu kendisini kapsayan bloğa göre 3,4 boşluk kadar içeriden başlamaktadır) Parantezlerin () Anahtar Kelime ve Fonksiyonlarla Kullanım İşlemi Parantezi Anahtar Kelimenin hemen yanına koymayıp arada bir boşluk bırakınız. Parantezi Fonksiyon İsimlerinin hemen yanına koyunuz. Fonksiyonların RETURN ifadelerinde gereksiz yere parantez kullanmayınız. 12
Anahtar Kelimeler fonksiyon değildir. Bunların hemen yanına parantez koymak fonksiyonlarla karıştırılmasına sebep olmaktadır. if (kosul) # bosluk var while (kosul) strcmp($s, $s1); # bosluk yok return 1; # parantez yok Soyutlama (Abstraction) Soyutlama (Abstraction) özellikle Object Oriented (obje temelli) programlamada vazgeçilmez bir programlama prensibidir. Basitçe soyutlama kavramını her zaman ve her şartta kullanılmaya uygun, mümkün olan bütün koşullar ve hata senaryoları göz önünde bulundurularak yazılmış ve spesifik olmayıp genel (jenerik) olarak kullanılabilen fonksiyonlar kullanımı olarak tanımlayabiliriz. Bir çoğumuz MySQL ile çalışacak programlar yazarken her seferinde, mysql_connect, mysql_select_db, mysql_query fonksiyonlarını ara arda yazarak çağıracağımıza bunları 'wrapper' (kapsayıcı,örtücü) denen fonksiyonlar içinde koyarak basit bir veritabanı_sorgula() fonksiyonuna indirgeyebiliriz. Bu sayede hem kodumuz çok daha kısa bir hale gelecektir hem de daha önemlisi iki ay sonra PostgreSQL ile çalışmaya karar verdiğimizde kodumuzu bu yeni veritabanına uyarlamak çok daha kolay olacaktır. Tek yapmamız gereken veritabani_sorgula fonksiyonuna geri dönüp onu PostgreSQL ile çalışacak şekilde uyarlamaktır. Peki kodumuzu başka bir veritabanına uyarlamak bu kadar kolaysa PHP'nin en son sürümüyle gelen DBX Soyutlama fonksiyonlarına neden ihtiyaç duyulur. Bunun birkaç sebebini sıralarsak, 1) Yeni başlayan PHP programcıları soyutlama veya wrapper kullanımı konusunda bilgisiz olduklarından her veritabanının kendi fonksiyonlarını kullanmaya alışmaktadır. Bu çok verimsiz bir kodlama şeklidir. 13
2) Soyutlama ve Wrapper fonksiyonlardan faydalanan programcıların hemen hemen hepsi bu fonksiyonların kendi versiyonlarını yazmaktadırlar. Bu yüzden ne belli bir standart oluşmakta ne de her zaman ve her ortamda kullanılabilecek bir beceri kazanılmaktadır. Ayrıca bu kitaplıklar yalnızca bir programcının ürünü olduğu için yeterli optimizasyon sağlanamamaktadır. Ayrıca programcının hiç tecrübesi olmadığı bir veritabanında bu kitaplıklar kullanılamaz. 3) İlave modüller ve kitaplıklar halinde bir çok veritabanı soyutlama kitaplığı olmasına rağmen bunların kullanımı standart bir boyuta ulaşmamıştır. 2. basamakta rastlanılan sorunların çoğuna daha az bir seviyede de olsa burada da rastlanmaktadır. Ayrıca bu modüller büyük çoğunlukla PHP'de yazıldıkları için PHP'nin kendisinin yazıldığı dil gibi daha aşağı seviyede çalışan dillerde yazılan fonksiyonlara nazaran daha verimsiz olmaya mahkumdurlar. 4) Bu kitaplıklar standart bir PHP kurulumunda olmayacağından kodunuz bir makinede çalışırken diğerinde çalışmayacaktır. Özellikle tümüyle kendinize ait olmayan ortamlarda bu büyük bir sorun yaratacaktır. Peki DBX bize ne kazandıracak? DBX ile birlikte bir veritabanına bağlanıp, sorgulama ve sonuçları alma işi tam anlamıyla bir standart haline gelmiştir. Hangi veritabanını kullandığınıza bağlı olmaksızın aynı ODBC ve JDBC teknolojilerinde olduğu gibi aynı fonksiyonları kullanarak desteklenen her türlü veritabanı ile çalışma imkanınız olacaktır. Eğer kodunuzu başka bir veritabanına uyarlamanız gerekirse tek yapmanız gereken en baştaki hangi tür bir veritabanına bağlanıldığını belirleyen seçeneği yeni veritabanına değiştirmektir. Bunu yaptıktan sonra teoride kodunuz yeni veritabanı ile hiç bir kod değişikliğine gereksinim kalmadan çalışacaktır. Bu aşamada aklımızda tutmamız gereken 4. 0. 6 ve DBX'in çok yeni teknolojiler olduğu ve henüz bütün veritabanlarını desteklemediği. Tabi ki açık kod felsefesi sayesinde az veya çok kullanılan veritabanlarının hepsinin en kısa zamanda desteklenmeye başlayacağından hiç şüphemiz yok. Örneğimize geçmeden önce şu anda desteklenen veritabanlarına göz atalım. MySQL,PostgreSQL, Microsoft SQL Server, ve ODBC destekleniyor. Bu arada Oracle, Sybase, DB2 gibi diğer bazı veritabanları desteklenmemesine rağmen ODBC desteği sayesinde bunların da DBX ile kullanılması mümkün. Unutmadan, DBX'i kullanabilmek için kurulum aşamasında. /configure 'e --enable-dbx i de eklemek gerekiyor. 1. Bu örneğimizde tek yaptığımız MySQL veritabanına bir bağlantı kurup, bağlantının kurulduğunu onayladıktan sonra bağlantıyı kapatıp çıkmak. 14
<?php $link = dbx_connect ("mysql", "localhost", "veritabani_adi", "kullanici_adi", "sifre") or die ("Veritabanına Bağlanılamadı"); print ("Veritabanına bağlantı sağlandı"); dbx_close ($link);?> İkinci örneğimizde ise veritabanımızdaki isciler_tablosu tablosundan isçilerin ad ve soyadlarını ekranda listeleyen küçük bir program yazacağız. 2. <? // İlk basamak veritabanına bağlantıyı sağlamak $db = dbx_connect ("mysql", "localhost", "veritabani_adi", "kullanici_adi", "sifre"); // İkinci olarak veritabanı sunucusuna bir sorgu yolluyoruz. $sonuc = dbx_query ($db, "SELECT ad, soyad FROM isciler_tablosu"); // dbx_query() fonksiyonu hata halinde '0' gönderiyor. // Başarılı bir sorgu sonucunda ya '1' ya da varsa sorgu sonuçları gönderiliyor. if ($sonuc == 0) echo 'Sorgu Çalışmadı<br />'; else // Sorgumuzun sonucu olarak kaç sonuç satırı gönderildiğini $sonuc // objesinin 'rows' (satırlar) değişkeninden öğreniyoruz. // Bu bir sonraki döngü için gerekli. $sonuc_satırlari = $sonuc->rows; // Veritabanının gönderdiği satırları bir bir geziyoruz. for ($satır = 0; $satır <= $sonuc_satırlari; $row++) // Sonuçları sonuç objesinin 'data' değişkenini kullanarak tablodaki alan // isimlerini denk gelen değişkenleri çağırarak alıyoruz. echo 'İsçi Adı: '. $sonuc->data[$satır]["ad"]. '<br />'; echo 'İsçi Soyadı: '. $sonuc->data[$satır]["soyad"]. '<br />'; // En son olarak da veritabanına açtığımız bağlantıyı kapatıyoruz. dbx_close($db);?> 15
DBX konusunda dikkat etmeniz gereken bir özellik sonuç satırlarını veritabanından istemek için bir fonksiyon bulunmayışı. Yani mysql_fetch_array, mysql_fetch_row tarzı fonksiyonlar kullanılmıyor. Bütün sorgular çalıştırıldıkları anda otomatikman sonuçları da bir array'e atıyorlar. Yani dbx_query hem sorgu hem de sonuçları alma işlemini yerine getiriyor. Diyelim ki bu örneği PostgreSQL ile çalıştırmak istiyoruz.. Tek yapmamız gereken ilk satırdaki dbx_connect() fonksiyonundaki ilk parametre olan 'mysql' i, 'pgsql' ile değiştirmekten ibaret. 16