Optional Kullanmaya Başlamak

Java 8’i uzun zamandır kullanıyorum desem yalan olur. Yaklaşık bir sene önce kullanmaya başladım. Kullanmaya başladığımdan beri de genel olarak Stream yapıları ve Lambda’ları kullandım. Optional ve diğer özelliklerine de baktım ama açıkcası çok ilgimi çekmedi. Bu yazıda kısaca neden başlarda ilgimi çekmediğini ve sonrasında ise neden her fırsatta kullanmak istediğimi anlatacağım.

Neden Başlarda İlgimi Çekmedi?

Bunun aslında çok karmaşık bir açıklaması yok. Yanlış anlatılan blog yazılarından tutunda, benim detaylı test etmememe kadar bir çok sebebi var. Özetle kendi hatam. Şöyle anlatayım. Eğer optional kullanmıyorsanız, aşağıdakine benzer bir null kontrolü illaki yapmışsınızdır.

Şimdi bunu alıp, benzerini optional ile yapmaya çalıştığınız da aşağıdaki sonucu alıyorsunuz.

Kabul edelim, hemen hemen aynısı. Tabi ikinci örnekte birde optional’ın null olma ihtimali var onunda ayrıca kontrol edilmesi gerekiyor. Fakat DAO katmanını yazan kişinin düzgün yazdığını varsayalım. Böyle yaklaşınca tabi insanın ilgisini çekmiyor. Ama şunu söyleyeyim eğer optional kullanıyorsanız, yukarıda yaptığınız şey tamamen yanlış. Evet yazılımsal olarak yapabilirsiniz, ama yapmamalısınız.

Sonradan Neden İlgimi Çekmeye Başladı?

Geçenlerde kod okurken, bir projede kullanımına rast geldim. O zaman anladım ki çok yanlış bir açıdan bakıyorum. Basit bir örnek üzerinden, yukarıdaki yaklaşımın neden yanlış olduğundan ve optional’ın neler sağladığından bahsedeceğim.

Basit örneğimizin, sağ tarafta gördüğünüz gibi, basitte bir model yapısı var.  Özellikle iç içe nesneleri olan bir model yapısı seçmeye çalıştım ki anlatmak istediklerimi daha iyi vurgulayabileyim.

Kod Okunabilirliğini Arttırıyor

Kod okurken rast geldiğimi söylemiştim. İlk dikkatimi çeken kısmı bu oldu. Şöyle düşünün User modelimiz için bir DAO tasarladığımızı düşünün aşağıdaki methodlardan hangisi daha net?

Benim için findUser metodu daha net. Biliyorum ki findUser methodu, user nesnesini bulamayabilir. Diğerinde ise bilmiyorum, null olabilir mi olamaz mı, bana var sayılan bir User mı dönecek, hiç bir fikrim yok.

Farkındayım ufak bir örnek üzerinde çok anlamlı olmuyor ama inanın büyük bir projede kodunuzun okunurluğunu çok arttırıyor. Design By Contract gibi düşünün.

Null Kontrollerinden Kurtulma

Genelde farklı blog yazılarından NullPointerException’lardan kurtulma olarak söyleniyor ama bence daha çok Null kontrollerinden kurtulmamıza yarıyor. Örneğin yukarıdaki DAO’yu kullanan bir servis katmanı geliştirdiğimizi düşünelim.

Gördüğünüz gibi basit bir katman. Yapması gereken iki şey var.

  1. getUser: Alttaki DAO katmanını çağırım kullanıcıyı bulmaya çalışacak. Bulamazsa UserNotFoundException fırlatacak.
  2. getUserCountryCode: Alttaki katmanı çağırıp User’ı bulacak. Eğer user’ın tanımlı adresinde, tanımlı ülke bilgisi varsa, tanımlı ülkenin kodunu, yoksa varsayılan ülke kodunu dönecek. (Yukarıdaki model UML’inden bakabilirsiniz) (Normalde veritabanından, doğruca ülke kodunu çekebilirsiniz tabi ama o zaman benim başka bir örnek bulmam gerekir. Zaten DAO katmanımızda izin vermiyor.)

Eğer optional kullanmıyorsanız, aşağıdakine benzer bir implementasyon yazmanız gerekecek.

Gerçekten çirkin bir kod. Sizi bilmem ama ben buna benzeyen if yapılarını falan defalarca yazdım. İstediğiniz tür Utility’i kullanın, inanın bana, bundan ancak bir yere kadar kaçabiliyorsunuz. Üstelik nesne yapınız ne kadar derinse işler o kadar çirkinleşiyor.

Şimdi bir de bunu optional kullanarak nasıl yapabileceğimize bakalım.

Biliyorum, satır sayısıyla kıyaslamak biraz yanlış, ama ikinci versiyon benim için çok daha okunabilir. Eğer java 8’e ve lambda operasyonlarına alışık değilseniz ilk başta biraz karışık gelebiliyor ama alıştığınızda çok daha net ve kolay olduğunu göreceksiniz. İkinci örnekte userDao.findUser(…), Optional.empty() dönse bile hiç bir şekilde NullPointerException almayacaksınız. Bu sebepten hiç bir şekilde null kontrolü yapmanıza da gerek kalmayacak.

Son

Optional’ın tüm marifeti bunlarla sınırlı değil. Farklı işlemler için kullanabileceğiniz daha bir çok özelliği daha var. Ama benim için önemli olanları şimdilik bunlar. Umarım az da olsa işinize yaramıştır. Ek olarak, şu yanlış bloglar konusunda şunu söylemek istiyorum. Oracle’ın blog tarzını (tema olarak, görünüş olarak) oldum olası beğenmemişimdir, hiç okuyasım gelmez. Bunu neden söylüyor diyecek olursanız, eğer ikinci elden yani başka blog yazıları yerine oracle’dan okumuş olsaydım büyük ihtimal bu detayları çoktan öğrenmiş olacaktım. Siz siz olun oracle’ın bloglarını es geçmeyin.