CLEAN CODE
Clean code nedir? Clean code için yapılmış birçok tanımı var. Bunlardan bazıları aşağıdaki gibidir.
– Bjarne Stroustrup (C++’ı geliştiren ve “The C++ Programming” kitabının yazarı) : Temiz kod birşeyi en iyi şekilde yapmalıdır. Hata yönetimi ve mimarisi etkili, kolay geliştirilebilir ve performansı yüksek olmalıdır.
– Grady Booch, “Object Oriented Analysis and Design with Applications” kitabının yazarı : Temiz kod basit ve ne yaptığını direkt göstermelidir. İyi yazılmış bir yazı gibi okunabilmelidir.
– “Big” Dave Thomas, OTI’nin yaratıcısı ve Eclipse stratejisinin babası: Temiz kodu okunabilir ve orijinal kodcusundan başka bir kodcu tarafından geliştirilebilir olmalıdır. Bir şeyi yapmak için birden fazla yol yerine tek bir çözüm yolunu sunmalıdır.
Söylemlerden de görüldüğü gibi temiz kod; basit, okunabilen ve tek iş yapandır. Kod yazarken şu soruyu sorabilirsiniz kendinize “Yazılımla ilgisi olmayan biri bu kodu okuduğunda ne yaptığını anlayabilir mi?”. Eğer hayır ise demek ki karmaşık ve okunamayan kod yazıyorsunuz demektir.
İSİMLENDİRME
Bir şeyleri doğru şekilde adlandırmak, yazılım geliştirmede en önemli şeylerden biridir. Yazılımın her yerinde isimler vardır. Yöntemleri, sınıfları, dosyaları vb. adlandırıyoruz.
İsimlendirmede kodun hemen ne yaptığını bilmemize izin verecek kadar anlamlı ve açık olmalıdır ve bizden sonraki yazılımcıya mümkün olan en doğru mesajı verecek şekilde ustaca kullanılmalıdır.
İsimlendirme önerileri:
Telaffuz Edilebilir İsimler Kullanın: Telaffuz edilemeyen tarzda isimlendirmeler kullanmak kodu tartışmak isteyen kişileri zorlar. Örnek olarak generationTimestamp yerine genymdhms gibi nasıl okunacağı belli olmayan bir isim kullanmak.
Aranabilir İsimler Kullanın: Tek harfli isimler ya da sayı sabitleri arama dostu değildir. Örneğin sum çok kullanışlı bir isim değil ancak en azından aranabilir. Benzer şekilde
WORK_DAYS_PER_WEEK sabitinin kullanımlarını bulmak, 5 sayısını bulmaktan kat be kat daha kolaydır.
Amaca Uygun İsim Kullanın: Kullandığınız isim için bir yorum satırına ihtiyaç duyuyorsanız bu amaca uygun bir isim vermediğiniz anlamına gelir. Örneğin bir sayaç tutmak için yazdığınız şu kod okunabilirlik açısından da pek uygun gözükmüyor.
Yanlış Bilgi Vermekten Kaçının : Kodda kullanım yöntemine ve amacına aykırı olan bir isim vermekten kaçının. Örneğin liste veri yapısına sahip olmayan bir değer için accountList gibi bir isim vermek, kodu okuyan kişiye ilk bakışta o değer hakkında yanlış bir bilgi verilmesine neden olabilir.
Anlamlı Ayrımlar Yapın : Aynı scope içerisinde aynı ismi birden fazla kullanamayacağımızdan ,ismin sonuna sayılar vererek birbirinden ayırabiliriz. Compiler açısından da bir sıkıntı olmayacaktır.Ancak şöyle bir gerçek var ki ortada farklı bir isim vermemizi gerektiren bir durum varsa,aslında buna sebep olan şey yeni değişkenin farklı bir iş yapacak olmasıdır. O nedenle yine burada hizmete uygun ve anlamlı isimlendirmeler tercih edilmelidir. Aşağıdaki örneğe baktığımızda adlandırmanın net bir şekilde anlaşılmadığını görüyoruz.
Mental Haritalamadan Kaçının : Kodu okuyan kişilerden okudukları isimleri kendi zihinlerindeki haritadan eşleştirmelerini istemek yerine, isimleri amaçlarına ve bulundukları domainle uyumlu olarak net bir şekilde belirleyin.
Sınıf ve Metot İsimleri : Sınıf isimlerini isim veya isim gruplarından seçerken, metotları ise fiillerden seçin.
Sevimli Olmaya Çalışmayın : İsimlendirmede net ifadeler kullanmak varken onun yerine eğlenceli veya argo kelimeler kullanmaktan kaçının.
Her Bir Kavram İçin Bir Kelime Seçin: Her bir kavram için bir kelime seçin ve ona sadık kalın.Buna bağlı olarak belirlediğiniz kelimeyi farklı farklı işlerde kullanmayın. Örneğin ekleme işlemleri için sadece add kelimesini kullanın.
Çözüm Alan Adlarını Kullanın: Kodu okuyan kişilerin de birer yazılımcı olduğunu unutmayın ve bilgisayar bilimi terimlerini uygun durumlarda kullanın. Örneğin: JobQueue
Problem Alan Adlarını Kullanın: Problem alan adlarını kullanarak kodun bakımını yapan yazılımcının çalıştığı domain özelinde doğru kişilere doğru sorular sormasını sağlayın.
KOŞUL KULLANIMI
Koddaki koşullar, dallanmalar kodu karmaşık hale getirebilir. Koşulları, döngüleri mümkün olduğunca doğal yapmalıyız ki okuyucu durup tekrar tekrar okuma gereği duymasın.
Örnekle inceleyelim:
Kötü kod görüldüğü gibi gereksiz uzatılmış ve okunması zorlaştırılmış. Yani anlaşılması zor bir hal almış .Fakat iyi kodda gereksiz if tekrarlarından kaçınılmış ve daha basit anlaşılır bir hale gelmiş.
Koşul cümlelerinde ters koşul kullanmak da kodu okuyanlar için kafa karışıklığı yaratmaktadır. Elimizden geldiğince pozitif anlamlı koşullar üzerinden ilerlemeliyiz.
Koşul içerisinde tekrar true ya da false’a eşitlemek gereksiz bir kalabalık yaratacaktır onun yerine yukarıdaki gibi yazarak kısa öz yazmayı tercih etmeliyiz.
Bir grup seçenek arasından seçim yapacaksak bunu static olarak vermektense enumlara bağlayıp kullanmak daha yerinde olacaktır.
Kodun içerisinde hiç bir anlam ifade etmeyen sayı, string gibi staticleri de direkt olarak kullanmamamız gerekir. Yukarıda age > 21 koşulu bize yaşın 21’den büyük olması durumunu net bir şekilde anlatıyor ancak 21’in ne ifade ettiği ve neden orada olduğu konusunda bir fikrimiz yok. Değişken çok yerde kullanılıp belli aralıklarla değiştirilmeyecek ise database’de tutmak yerine yukarıdaki şekilde bir tanımlama koda anlam katacaktır.
İç içe if kullanarak yapmak çoğu yazılımcının düştüğü bir yazım yanlışıdır. Bu şekilde bir kod zincirinin okunması ve aynı zamanda hangi if’in hangi else denk geldiğinin anlaşılması zordur. Bunun yerine ifleri alt alta sıralayıp ilk yakalanan validasyondan itibaren kodu return etmek daha doğrudur.
DÖNGÜ
Kodlama yaparken mümkün olduğunca do/while döngüsü kullanmaktan kaçınılmalıdır. Birçok dilde, do {ifadeler} while(koşul) döngüsü vardır. Do/while döngüsünde tuhaf olan şey, kod bloğu koşula göre çalıştırılabilir de çalıştırılmayabilir de. Bu da kafa karışıklığına yok açabilir. Tüm do/while döngüleri while döngüsü olarak yazarak daha temiz bir kod yazabiliriz.
Örnekte de görüldüğü üzere do/while yerine sadece while döngüsünü kullanarak daha temiz bir kod yazmış olduk.
YORUM SATIRLARI
Yorumları kodda kendimizi iyi ifade edemediğimiz noktaları telafi etmek amacıyla kullanırız. Yorumlar her zaman koddaki kusurlarımızdır, çünkü kendimizi onlarsız nasıl ifade edebileceğimizi bilmiyoruz. Bu yüzden eğer kendimizi yorum yazarken buluyorsak, durup tekrar düşünelim. Kendimizi açıklayabileceğimiz başka yollar olup olmadığına bakalım.
Birkaç yorumu olan temiz ve açıklayıcı kod, bir sürü yorumu olan karmaşık ve darmadağın bir koddan daha iyidir. Yarattığın karmaşayı açıklamak için yazacağın yoruma harcadığın enerjiyi, bu karmaşayı temizlemek için harcamalısın.
“Kötü koda yorum yazmayın, onu yeniden yazın.”
Kötü Yorumlar
Gereksiz Yorumlar: Gereksiz yorumlar yapmaktan kaçının. Aşağıdaki örnekte kodun kendisini okumak, yorumu okumaktan daha kısa sürecektir:
Zorunlu Yorumlar : Her fonksiyonun bir Javadoc’u ya da her değişkenin bir yorumu olması gerektiğini söyleyen kurallar saçmadır.
Günlük Gibi Yazılan Yorumlar : Bazı kişiler bir modülü her düzenlemeye başladıklarında, başladıkları tarihi yorum olarak eklerler. Bu yorumlar bir günlük gibi birikir.
Kapama Parantezlerine Koyduğumuz Yorumlar: Bazen yazılımcılar kapama parantezlerine özel yorumlar eklerler. Uzun fonksiyonlarda bir anlam ifade etse de, küçük fonksiyonlarda sadece kalabalık sağlar. Bu nedenle, eğer bir kapama parantezine yorum ekliyorsanız, bunun yerine fonksiyonunuzu kısaltmayı denemelisiniz:
Kapatılmış Kodlar: Kodları kapatmanın önemli olduğu zamanlar vardı, 60'lar. Ancak şimdi versiyon kontrol sistemlerimiz (SVN, Git vb.) var ve bu sistemler kodu bizim için akıllarında tutuyorlar.
Yersiz Bilgi: Eğer bir yorum yazmanız gerekiyorsa, onun yakınında olduğu kodu tanımladığından emin olun. Kısmi bir yorum içerisinde, tüm sisteme ait bir bilgi vermeyin.
Yukarıdaki örneğe baktığımızda yorum kesinlikle fonksiyonu tanımlamıyor. Gereksiz bir bilgiyi, varsayılan port ayarını bize söylüyor. Ve elbette ayar değiştiğinde, bu yorumun da değişeceğinin hiçbir garantisi yok.
İyi Yorumlar
Yorum yazmak her zaman kötü olmayabilir. Bazı yorumlar zorunludur ve faydalıdır.
Yasal Yorumlar: Bazen kurumsal kodlama standartlarımız yasal sebelerden ötürü bizi kesin yorumlar yazmaya zorlar. Örneğin telif hakkı ve yazarlık durumları gereklidir ve her kaynak dosyanın başına böyle bir yorum koymak mantıklıdır.
Bilgilendirici Yorumlar: Bazen diğer programcıları kesin sonuçlar hakkında uyarmak iyi olabilir.Aşağıdaki yoruma bakalım; abstract bir metodun dönüş değerini açıklıyor. Fonksiyon ismini responderBeingTested şeklinde değiştirerek yorumu gereksiz hale getirebilirdik:
TODO Yorumları: Kodda yapmak istediklerimizi //TODO şeklinde yorum olarak yazabiliriz. TODO’lar programcıların yapmaları gereken ancak o anda bazı sebeplerden ötürü yapmadıkları işler içindir. Kullanımdan kaldırılan (deprecated) bir özelliği silmek için hatırlatıcı olabilir, birilerinin daha iyi bir isim düşünmesini isteyebiliriz ya da başka birilerinin probleme göz atması için bir rica olabilir. TODO ne olursa olsun, sistemde kötü kod bırakmak için bahane değildir.
Şimdi de clean code konusu ile ilgili aşağıdaki kodu inceleliyelim:
İlk satırımızı incelediğimizde “//sayı okuyoruz” satırının yersiz bir yorum olduğunu görüyoruz. 2.satırdaki digerSayı değişkenimizin adlandırılması açık ve anlaşılabilir değil, değişkenin ne için kullanıldığını net bir şekilde belirtmemektedir. 5. Satırdaki else komutu yazılmayabilir. 6. satırdaki j değişkenin yerine sayaç gibi bir isimlendirme kodu daha anlaşılır kılıcaktır ve buradaki yorum satırımız da gereksizdir. 8. satırdaki j değişkenini zaten j++ yapmak arttırmak anlamına gelir. Bunu yorum satırına yazmak gereksizdir. While döngü yerine for kullanarak kodu kısaltabiliriz.