Ne kadar abstraction?

Tarik Guney
Kodcular
Published in
3 min readJan 29, 2018

--

Hatırlatma: YouTube Kanalıma abone olarak, her hafta eklenen yazılımcılar için programlama ve kariyer video eğitimlerime ulaşabilirsiniz.

Mutlu bir şekilde programınızın çalışmasına bakarken bir anda aldığınız exception ile moraliniz bozuldu ve hatanın nerede olduğunu öğrenmek ve çözümü kodlamak için başladınız debug etmeye. İlk breakpointe vurdu debugger ve gördünüz ki çağrılan methodun adı getAccountDetails(). Gayet anlaşılır bir method ismi. Demek ki account detaylarını getirmede sorun var dediniz ve step-in yapmak suretiyle debugger ile methodun içine girdiniz. Orada validateAccount(), checkLDAPAuthentication(), recordLastAccessDate() methodlarının çağrıldığını gördünüz. Stack trace size checkLDAPAuthentication()methodunda bir sorun olduğunu söyledi. Bu methodun içine girdiniz ve orada da isLDAPActive() methodunun yanı sıra başka method çağrımlarının olduğunu gördünüz. Derken isLDAPActive() methodunun getLDAPConfiguration() methodunu çağırdığını, onun da getConfiguration() methodunu, onun da getConfigurationFromServer() methodunu derken işlerin çığrında çıktığını ve artık aklınızla bu kadar indirectionu takip edemeceğiniz bir hale geldiğini gördüğünüz. Pişman mısınız? Pişman olmak isteyebilirsiniz!

Soyutlama Katmanı

Yukarıda devamlı aşağılarına indiğiniz katmanların hepsi birer soyutlama katmanı. Her güzel şeyin kötüye kullanılması ve abartılması sonucunda iğrenç bir şeye dönüşmesine benzer olarak soyutlama da yanlış kullanıldığında kolaylık sunmak yerine bilakis işleri zorlaştıran ve kaliteli kod yazmanın en önemli kriterlerinden birisi olan okunabilirlik ilkesini ihlal etmesinden dolayı bilinçli kullanılması gereken bir durum. Kaliteli yazılımcılar körü körüne abartarak birşeyi kullanmazlar. Onlar doğru çözümü doğru yerde doğru miktarda kullanırlar.

Peki Single Responsibility Principle?

Tecrübeli yazılımcıların bu kadar fazla abstraction kötüdür denildiğinde aklına ilk gelecek sorulardan bir tanesi: Peki birden fazla iş yapmak SRP’ye ters değil mi? Mantıklı bir soru belki ama cevaben hayır. Çünkü birden fazla işe yapmıyorsunuz. Ya da daha doğrusu bir unite işin meydana gelmesi için birbirlerini tamamlayan işleri grupluyorsunuz. Yukarıda ki örneğe baktığımızda, farklı katmanlarda tanımlanmak yerine bazı methodlar belki aynı sınıfta birer private method olarak tanımlanabilirdi. SRP, sorumlulukları gruplamak için ve hangi katmandan baktığınıza göre değişen bir kavram. Örneğin, getLDAPConfiguration() sınıfını içeren LDAPConfigurationProvider sınıfının dışarıdan bakıldığında tek sorumluluğunun LDAP ayarlarını döndermek olduğunu görüyoruz. Ama bunu kendi iç dünyasında nasıl yaptığı ise ona kalmış bir durum. Implementation detaylarında isterse bunu ayrı bir katmanda bulunan bir methodu çağırmak sureti ile yapar, isterse de direk redirection yapmadan kendi içinde daha detaylı bir implementasyona sahip olmak yardımıyla. Ama değişim amacı yine bir nedenden dolayı olacaktır ve o da LDAP ayarlarını alırken yapmak isteyeceğiniz bir nedenden dolayı.

Dikkat edilmesi gereken mesele katmanlamayı nerede bırakmamız gerektiği. İleride kullanılır belki umudu ile herşeyi bir abstraction arkasına saklamak ve daha granular hale getirmek suretiyle daldan dala atlayan bir kod yazmak zamanla okunmaz ve debug edilmesi ciddi zorlaşmış bir proje ile karşı karşıya kalmamız ile sonuçlanacaktır.

Kod Yazmanın Zevki

Kod yazarken çoğumuzun zevk aldığını söylemek malumun ilanı sadece. Özellikle iyi bir şekilde anladığımız bir requirementi kodlarken aklımızda ki taze bilgiler ile kodumuzu katmanlayıp durabiliyoruz. Çünkü o anda hem abstraction gibi önemli yazılım konseptlerini kullanmış olmanın verdiği tatmin, hemde herşeyin kafamızda hala taze olması, yazdığımız kodun gayet anlaşılır olduğu illüzyonunu uyandırabiliyor çoğumuz için. Ama ne zaman ki 4–5 ay sonra yeniden bu koda döndüğümüz de, veya kaynak kodun bu kısmında daha önce hiç çalışmamış insanlar sizin kodunuzu incelemeye başladıklarında meselenin hiçte bu kadar kolay anlaşılır olmadığı ortaya çıkmaya başlıyor. Hele bir de bu insanlar sizin kodunuzu debug etmek zorunda kalmasınlar. Arkanızdan çok rahmet okunmayacağından emin olabilirsiniz.

Peki Nerede Durmak Lazım?

Bunun cevabı genelde içinde bulunan projeye ve domain’e göre değişecektir. Onun için yazılım mimarı olmak kolay iş değildir ve zaman gerektirir. Ama, kendimize bazı sorular sormak sureti ile en azından duracağımız noktayı görmemiz mümkün:

  1. Bir kod parçasını abstract etmek ile şu anda veya çok yakın zamanda code reusability sağlamış olacak mıyım? Yoksa karşımda yapmayı düşündüğüm soyutlama sadece bir YAGNI durumu mu? (YAGNI: You ain’t gonna need it! demek.)
  2. Bunu ileride rahatlıkla refactor etmek sureti ile abstract edebilir miyim? Evetse, o zaman inline edin gitsin.
  3. Yukarıdan aşağıya doğru farklı soyutlama katmanlarını geçerek kodunuzu okumayı deneyin ve adımları aklınızdan hatırlamaya çalışın. Eğer yarısına bile gelmeden ne nereden geldi, kim kimi çağırdı unutmaya ve kafanız karışmaya başlamışsa, çok fazla katmanlaşmış olabilirsiniz.

Unutulmaması gereken şey, çoğu zaman yukarıdan aşağıya kod okumak, devamlı soyutlama katmanları arasında dolaşarak kod okumaktan çok daha kolay olduğu gerçeği. Onun için doğru zamanda doğru şekilde soyutlama yapmak hem kod okunurluğu arttırabilecek, hemde kod yazmayı kimimiz için daha zevkli hale sokacaktır.

Şu an için aklıma gelenler bunlar. Sorularınız varsa, buyrun burada paylaşın.

Bir daha ki yazımda görüşmek üzere…

--

--