Java By Comparison — Karşılaştırmalı Java — 2

İkinci yazımızla kaldığımızdan yerden devam edelim.

Birinci bölümü okumak için…

5. Koşullarda NullPointerException Hatasına Dikkat Edin

Hataya neden olabilecek örneğimize bakalım.

Java’da en sık karşılaştığımız hatalardan biri NullPointerException hatasıdır. null olan bir referans üzerinden bir metoda veya değişkene erişmek istediğimiz zaman bu hatayı alırız. Bu tür hataları almamak için metodun argümanlarını kontrol etmek gerekir ama doğru sırada!

Bu kod parçasında argüman olarak geçilen mesajların dosya sistemine yazılmasını istiyoruz. Bunun içinde dosyanın konumunu ve argümanın kontrol edilmesi gerekiyor.

Metodun şimdiki hali de bazı kontroller yapıyor ama iki yanlışı bulunuyor. İlk önce location değişkeni için null kontrolü yapılmıyor. İkincisi ise message için null kontrolünün yeri yanlış seçilmiş.

Argüman olarak bir metoda null geçmek gerçekten kötü bir stildir. Bu metodun, parametresiz de çalışacağı anlamına gelir. Bu durumda metodu 2 ayrı metoda yeniden düzenlemek daha anlamlı olabilir: parametreli bir tane ile parametresiz bir tane.

Şimdi metodun daha düzgün kontrol edilmiş haline bakalım.

Metodumuzun yeni halinde ilk önce null değer kontrolü yaptık daha sonra ise alana-yönelik kısıtlamaları kontrol ettik.

Kendi kendinize şunu sorabilirsiniz: Bu seviye parametre kontrolü her zaman gerekli midir? Hayır diyebiliriz.

Genel kural olarak, public, protected veya default metodların parametlerini kontrol etmeye ihtiyacınız var. Diğer türlü, private metodlarınız var ise, hiçbir zaman null pas edilmeyeceğini garanti edebilirsiniz. Onun için kontrole gerek kalmaz.

İ.K. Notu: Daha önce Junior olmayan bir arkadaşın şöyle koduna rastlamıştık.

if (str.length > 0 && str != null) {
//…
}

Uzunca bir süre kodun bu şekilde olmayacağını anlatmaya çalışmıştık ama arkadaş çalışacağında ısrar etmişti :) İtiraf ediyorum, o arkadaş ben değildim :)

6. Switch’in Akışına Dikkat Edin

Switch ifadesi barındıran kodumuza bakalım.

Bazı dillerin adı kötüye çıkmış hatalar yıllardır devam etmektedir. Bunlardan bir tanesi ise switch’tir ve onu kullanırken dikkatli olmak gerekir.

authorize(User) metodu kullanıcının null olup olmadığını kontrol ettikten sonra switch akışı içine girmektedir. Buradaki hata ilk switch ifadesindedir, break sözcüğü unutulmuştur. Yani bu durum, ilk ifadeye girdikten sonra ikinci ifadeye de gireceği anlamına gelir. Kod, break sözcüğünü görünceye kadar tüm case ifadelerine girmeye devam eder.

Bu kullanım şekline C-stil dillerde rastlarsınız ve Java’da bu özelliği C dilinden almıştır.

İlk başlarda belki iyi niyetle böyle bir case-break tasarımına gidilmiş ama yıllarca bu durum, faydadan çok zarar getirmiştir. Unutulan break ifadesi yüzünden, yazılım geliştiriciler nice uykusuz gecelere gark olmuşlardır. Nadir durumlarda, kasıtlı olarak break kullanılmayabilir. Bu durumda da yorum yazılmalıdır.

İ.K. Notu: En iyisi hiç eksik break kullanmamaktır. Yeni dillerde(Kotlin mesela) derleyici otomatik olarak break ifadesini kendiliğinden ekliyor. Ayrıca, bizim eklememize gerek kalmıyor. Bu da hataları azaltıyor.

Kodumuzun hatasız versiyonuna bakacak olursak,

Her case ifadesi sonuna break ekleyerek hatamızı giderebiliriz.

Şimdi kodumuz hatasız ama gerçekten burada switch doğru bir çözüm müdür? Hayır tabi ki.

Switch ifadesi, iki farklı ilgiyi, yetkili ve yetkisiz erişimi, tek bir blok içinde birleştirmiş. Genel kural olarak, farklı alakalı şeyleri, farklı bloklara veya metodlara ayırmak gerekir.

İ.K. Notu: “Her switch ifadesinin arkasında bir kalıtım(inheritance) yatmaktadır” diye bir söz hatırlıyorum. Refactoring kitabından idi herhalde.

7. Her zaman Parantez Kullan

Hataya meyilli örneğimize göz atalım.

Bir önceki örneğimizde, switch ifadesinin if koşullu ifadesine çevrilmiş haline bakalım. Buradaki hata, hizalamanın kodda yanlış anlaşılmaya yol açması. if koşullu ifadesinden sonra, süslü/kıvırcık parantez bulunmuyor. Bu da, sadece if’den sonraki ilk ifadenin çalıştırılacağı anlamına geliyor. Yani cruiseControl.grantAdminAccess(user) kod satırının, her zaman çalıştırılacağı anlamına geliyor.

Buradaki asıl problem, hizalama değil, koddaki parantezlerin unutulması. Hizalamaya hiçbir zaman güvenmemeliyiz(Phyton yazmıyorsak tabi ki) ve parantezleri her zaman eklemeliyiz.

İ.K. Notu: R.C.Martin, Clean Code kitabında if, for, while gibi ifadeleri tek satıra indirdikten sonra süslü parantezlerin silinmesini tavsiye ediyor. Bana göre ise ilerde o tek satırın yanına başka ifadelerin de gelme olasılığı yüksek olduğu için, tek satır bile olsa her zaman süslü parantez kullanmak daha doğru gibi geliyor. Karar sizin…

Koda derleyici gözüyle bakacak olursak, derleyici kodu şöyle görür.

Hatayı hemen farketmişsinizdir. Parantezler sayesinde kod artık daha okunulabilir. Hata da hemen farkediliyor.

Hatalı hizalama kodumuzda hataya yol açıyordu. Bu da gösteriyor ki, her zaman daha az kod, daha iyi demek değildir. Amacımız daha okunaklı koddur.

Bu hatanın pek gerçekçi olmadığını ve pratikte kimsenin yapmayacağını düşünebilirsiniz. 2014 yılında, Apple mühendisleri iOS için geliştirdikleri SSL/TLS protokollerinde benzer bir hata yaptı ve bu açıktan dolayı, şirket saldırılara maruz kaldı.

Şimdi de kodun düzeltilmiş haline bakalım.

O yüzden her zaman parantez kullanmayı unutmayalım.

8. Kod Simetrisini Sağlayın

Bir önceki örneğimizden devam edelim.

Daha önce defalarca vurguladığımız gibi, kodun anlaşılabilirliği kritik bir görevdir. Parantezlerin simetrikliği oluşturacak şekilde kullanılması da, kodun anlaşılmasını ve okunulabilirliği kolaylaştırır.

Bu kodda, açık bir hata yok. Burada ki asıl problem, bütün koşullar ardı ardına birbirini takip etmiş. Bu da, hepsini tek seferde okuyup anlamanıza zorluyor sizi. Böyle küçük bir örnekte çok sorun değil ama kod tabanımız büyüdüğü takdirde, ki her zaman büyüyecektir, sorun olmaya başlayacaktır.

Aslında, eksiklik kodun simetriğinin olmamasıdır. Bu konuda Kent Beck şöyle der ki, “Neredeyse benzer olan şeyler, aynı ve farklı kısımlar olarak parçalara bölünebilir”.

Bunun hakkında düşünelim. Bütün dallanmalar gerçekten benzer bir ilgiyi mi paylaşıyor? Gerçekten simetrik midir? Cevap, aslında değil. İlk ifade, yetkisiz durumu gösteriyor. İkinci ve üçüncü ifadeler ise yetkili halini gösteriyor. Bu simetrik değildir.

Kodun simetrik haline bir bakalım.

Kodu farklı bloklara ayırarak, kod simetrisini sağladık.

Yetkisiz erişimi başta kontrol ederek ve metoddan geri döndürerek ilk kısımda kontrol etmiş olduk. Sonrada, diğer iki durumu hallettik.

İkinci kısımda simetrikliği sağlamış olduk.

Hala yapılacak iyileştirme bulunuyor. grantAccess(user) iki yerde de çağrılıyor. Ayrıca, iki ifadeyi iki ayrı private metoda bölebiliriz. Yönetmesi daha kolay olur.


Bir yazımızın daha sonuna geldik. Bir sonraki yazımızda görüşmek dileğiyle. Sağlıcakla kalın.