PHP ve TDD
Test yazmak hayat kurtarır. Nasıl mı? Büyük bir yazılım yazdığınızı düşünün. Ülke çapında onbinlerce kullanıcınız var. Herkes sistemi aktif olarak kullanıyor ve sistemin saniyede 200-300 requeste gecikmeden cevap vermesi gerekiyor. Arkaplanda birsürü sistem çalışıyor. Mysql, Mongodb, Memcache, API’ler vs. Her saniye onlarca megabyte veri ekleniyor sisteme. Veritabanı gigabytelarla ölçülüyor. Böyle bir sistemi nasıl yazarsınız? Eğer cevabınız “yaz-çalıştır” ise hemen bilgisayarı kapatın ve kendinize yeni bir meslek edinin. Çünkü böylesine büyük bir sistemi bu yöntemle çalıştırmayı bile başaramazsınız. Başarsanız bile büyük sistemlerin mutlaka düşmanı olur ve çok kolay hackleneceği için hemen darmadağın olur ve sisteminiz kapanır. O yüzden boşuna uğraşmış olursunuz. Tabiki böyle büyük bir sistem için sağlam bir yatırım gerekir ve eğer siz programcılar olarak bu işin üstesinden gelemezseniz yatırımcılar size çok kızarlar. Eğer agresif bir yatırımcınız varsa iş büyür ve en iyi ihtimalle sizden davacı olur. İşte bu yüzden test yazmak hayat kurtarır.
Fakat şöyle bir problem var. PHP kökeni fonksiyonel programlamaya dayanır. Tüm işlerinizi fonksiyonlarla yapabilirsiniz aslında. Teoride böyledir ama pratikte büyük projeler bu şekilde yapılmaz. Mutlaka TDD yapılmalı ve bunun için de mutlaka sistemi Object Oriented yazmanız gerekir. Büyük projeler için bunlar şart. Peki aslı fonksiyonel olan bir dil için bunları nasıl yapacağız?
PHP son versiyonlarında Object Oriented konusunda gelişmeler yaptı. Eksiklerini gün geçtikçe kapattı ve çok gelişmiş bir class yapısına sahip oldu. Namespacelerden Reflectionlara kadar çok iyi bir gelişme yaptı. Hala bazı yerlerde standart fonksiyonları kullanmaya mecbur olsak da bizi ilgilendiren kısım OOP konusundaki gelişmeler. Tamam herşey nesne değil, herşeyi sadece standart classlar ile yapamıyoruz ama birsürü framework çıktı ve hatta becerebiliyorsanız kendi OOP frameworkünüzü bile yazabilirsiniz.
Gönül isterki sizinle burada ufak bir örnek proje yapalım ama bu makale daha çok PHP ile kodlama yaparken neden TDD kullanmak gerektiği hakkında olacaktır. Örnek projeyi de başka bir makaleye sakladım. TDD hakkında birçok kez yazıldı çizildi. Java ile TDD, C# ile TDD, Python ile TDD, falan ile TDD, filan ile TDD. Herkes tecrübelerini paylaştı, örnek projeler yaptı, farklı dillerin karşılaştırmaları yapıldı, imkanlardan ve imkansızlıklardan bahsedildi. Ben bunlara girmeyeceğim. Konumuz “Neden PHP ile TDD yapılmalı?” olacaktır.
Ülkemizde PHP denince çoğu kişinin aklına basit siteler, beceriksiz freelancerlar, hazır sistemler, Open Source mu yoksa closed source mu tartışmaları, webmaster siteleri vs gelir. Ama aslında bu dilde birçok dilde olmayan özellikler var. Bunlardan en önemlisi çalışma hızı. Ondan sonra heryerde çok rahat şekilde kullanılabilir olması. Öğrenilmesi ve çalıştırılması kolay. Bir problem çıktığı zaman çözüm bulmanız kolay. Tüm dünyada çok büyük bir kitle tarafından aktif olarak kullanılmaktadır çünkü. Sizin karşılaştığınız problemle mutlaka daha önceden biri karşılaşmış, çözmüş ve çözümü paylaşmıştır. Ayrıca bilinen birçok büyük siteler ve yazılımlar PHP ile yazılmıştır. Sitelerin reklamını yapmayacağım ama bilinen yazılımları söyleyeceğim. VBullettin, phpBB, SMF, WordPress bunlardan en bilinenleri. Bu sistemler çok kullanıcılı ve büyük verileri işleyebilen ve ağır yük altında bile kasmadan çalışabilen sistemlerdir. Ayrıca plugin desteği, kullanıcı yetkilendirmesi falan gibi önemli özelliklere de sahiptirler. Sizce bu yazılımlar nasıl yazılıyor? Cevabı ben vereyim. Uzman mühendisler tarafından TDD kullanılarak yazılıyor. Ayrıca OOP özellikleri geliştiği için Design Pattern’lar da rahatlıkla kullanılabilir.
Dediğim gibi PHP OOP konusunda büyük ilerlemeler katetti. Bu sayede test yazmak çok kolaylaştı. Herşeyin kütüphanesini çok kolay şekilde bulabilirsiniz ve bunları kullanırken yazdığınız kodları PHPUnit ile rahatlıkla test edebilirsiniz. Ayrıca birçok mock kütüphanesi de geliştirilmiş. Phake, mockery, PHPUnit mock objects bunlardan bazıları. Yine bu kütüphaneler de uzman mühendisler tarafından geliştirilmekte ve gönül rahatlığıyla kullanabilirsiniz.
Benim test yazarken en çok takıldığım nokta eğer bir yerde fonksiyon kullanmışsanız o zaman test yazmak zorlaşıyor. Örneğin Mysql’e fonksiyonel yöntemle bağlanırsanız o bağlantı metodunun testlerini yazamazsınız. Evet yazamazsınız. Çünkü o metodu çağırdığınız an Mysql’e bağlantı yapmaya çalışacak ve ya hata verecek ya da yanlış sonuç dönderecektir. Dolayısıyla da metod test esnasında hiçbir zaman beklendiği gibi çalışmayacaktır. Fonksiyonun sahtesiyle değiştirmek mümkün ama neden daha basit yöntemler varken kendinizi zora sokuyorsunuz ki? Sağ kulağınızı sol elinizle tutmayın. O yüzden her zaman bir işin OOP muadilini kullanın.
Her zaman bu mümkün olmaya da bilir. Fonksiyonların her zaman OOP karşılıkları olmayabilir. Bu durumda yapmanız gereken en iyi şey o fonksiyonları sarmalayan bir class wrapper yazarsınız ve test esnasında o class’ın mock objesini oluşturup o şekilde kullanırsınız. Bu şekilde yaparsanız yine herşey sizin kontrolünüzde olur. Çağırılmaması gereken bir fonksiyon çağırılmamış olur. Test etmek istediğiniz metod yine PHPUnit sınırları içerisinde kalır ve gerçek hayata taşıdığınız zaman arkanıza bakmanıza gerek kalmaz.
Hepinize bol testli az problemli günler dilerim.