Sözde Lean!

yazar:

kategori:

Super lean Grails Micro-Services diye bize sattıkları koda bir bakın:

[source language=”java”]
@Grab("com.h2database:h2:1.3.173")
import grails.persistence.*

@Entity
@Resource(uri=’/books’)
class Book {
String title
}
[/source]

Bu lean değil, patlamak üzere olan saatli bir bomba. Tek bir sınıf bünyesinde nasıl başardılarsa, sınıfın hem veri tabanı için gerekli JDBC sürücüsü konfigürasyonunu, buradan bir java.sql.Connection nesnesi edinme işlemini, JPA anotasyonları ile bu sınıftan olan nesneyi bir veri tabanında kalıcı hale getirmeyi ve @Resource anotasyonu ile bu sınıfı /books adresi altında bir REST kaynağı olarak dış dünyaya açmayı başarmışlar. Sınıf hangi veri tabanı sisteminin kullanıldığını bile bilyor. Böyle bir şeyin çok serin (cool) olduğunu düşünenler olabilir. Ben aynı fikirde değilim! Neden mi?

  • Bu sınıf tek sorumluluk prensibine çok aykırı bir yapıda. Bu sınıfın en az dört değişik sorumluluğu bulunuyor. Bu sınıf dört değişik sebepten dolayı kırılabilir. Yazılım sistemlerinin zamanla bakılamaz ve geliştirilemez hale gelmelerinin ana sebeplerinin başında tek sorumluluk prensibine uyumlu yapıların oluşturulmaması gelmektedir.
  • Gerçek iş mantığına sahip kodla, bu koda olan erişim örneğin cephe ya da business delegate tasarım şablonu ile birbirinden ayrılmalıdır. İş mantığı kendisine nasıl erişildiğini bilmemelidir. Aksi halde yukarıda yer alan kod örneğinde olduğu gibi erişim teknolojisini kendisi yönetmek zorundadır ki bu da sınıfa ikinci bir sorumluluk yükler. Erişim teknolojisi değiştiğinde sınıfın buna göre adapte edilerek, yeniden derlenmesi gerekir.
  • Uygulama bünyesinde yer alan alan nesneleri (domain objects) birebir dış dünyaya açılmamalıdır. Yukarıda yer alan örnekte bir alan sınıfı olan Book bir REST kaynağı olarak dış dünyanın kullanımına sunulmuştur. Bu yazılım sistemini kullananların yazılım bünyesinde olup, bitenler hakkında çok fazla detay bilgiye sahip olmalarına sebep verebilir. Bunun yani sıra uygulama bünyesindeki alan nesnelerinde meydana gelen değişikler dış dünyadaki kullanıcıları doğrudan etkiler. Bunun yerine gerekli verileri taşımak amacıyla request, response veri sınıfları tanımlanmalıdır. Bu sınıflar kullanıcılar ile uygulama arasında oluşturulan kullanım kontratının (contract) bir parçasıdır.
  • Uygulama hangi veri tabanı sistemini kullandığını bilmemelidir. Bu tür bilgiler uygulamanın değişik ortamlara göre ihtiyaç duyduğu konfigürasyonun bir parçasıdır. Kod değişikliği yapmadan konfigürasyon değiştirilebilir yapıda olmalıdır. Örnegin Spring ve Dependency Injection kullanılarak uygulama değişik ortamlara göre konfigüre edilebilir.
  • Sadece iş mantığını ihtiva eden bir servis ya da sınıfı test etmek çok daha kolaydır. Yukarıda yer alan sınıfı test edebilmek için veri tabanı bağlantısının oluşturulması, sınıfın beli bir uygulama sunucusuna konması gibi işlemler programcı olarak sadece entegrasyon testleri yazmamıza izin verecektir. Birim testleri yazamadığım için yeniden yapılandırma (refactoring) yetimi kaybetmiş olabilirim. Sadece entegrasyon testleri kullanılarak kodu seri bir şekilde yeniden yapılandırmak mümkün değildir. Bu iş için birim testleri gerekmektedir. Birim testleri yazabilmek için de iş mantığının POJO (Plain Old Java Object) yapısında olması gerekmektedir.

Bu super lean gibi sıfatlarla kendilerini pazarlayan çatılarla ciddi anlamda yazılım sistemleri geliştirmek mümkün değildir. Bu çatılar sadece hızlı bir şekilde prototip yapmak için kullanılabilirler. Eğer maksat her şeyi monolitik bir sınıfta toplamaksa, bunu kendim de yapabilirim. Bunun için super lean bir çatıya ihtiyacım yok!


EOF (End Of Fun)
Özcan Acar


Yorumlar

“Sözde Lean!” için 5 yanıt

  1. Dediklerine tamamen katiliyorum Ozcan. Hatta bazilari bu gibi “agile” teknoloji ornekelrini ele alip, kurumsal buyukluk ve kalitedeki yazilimlarla kiyaslamalar bile yapiyor.
    Eline saglik.

  2. Hocam merhabalar,

    Cache için yazılan attribute ler de bu kategoriye giriyor o zaman, örneğin;

    [CustomCache]
    public class SomeClass{…}

    Ama bu attribute sınıfını yazmazsak da, SomeClass içerisinde yazmamız gerekecek. Bunun için illa bir framework mü kullanmak gerekli, ya da bu konuda nasıl bir yol izleyeceğiz. SomeClass sınıfı, nasıl hem caching, hem logging hem de exception handling yapacak?

    1. Özcan Acar avatarı
      Özcan Acar

      SomeClass sinifi caching, logging ve hatta hatta exception handling kendisi yapmamali. Yaparsa, yazimda bahsettigim durum ortaya cikiyor: birden cok fazla sorumlulugu olan bir sinif.

      Caching, logging ve exception handling seperation of concerns mantigi cercevesinde AOP (Aspect Oriented Programming) kullanilarak aspekt olarak programlanip, uygulamaya eklenebilecek genel islevlerdir. Her uygulama parcasi bu tür islevleri kendisi implemente etmek yerine, AOP kullanilarak bu tür aspektler isletme mantigi ile harmanlanabilir. Bu sekilde SomeClass gibi isletme mantigi ihtiva eden siniflar kendi isleri ile mesgul olurken, AOP ile bahsettigim aspektler dolayli olarak isletme mantigi üzerinde kosturulabilir. Böylece sadece bir isle mesgul olan siniflar programlamak mümkün.

  3. Aslında bunu anladım, AOP yi de bayağı araştırdım. Bunun iyi olarak uygulandığı açık kaynak bir proje ve ya makale var mı? Yani örnek görmeden tam olarak anlaşılmıyor. Yapının nasıl olması gerektiğini anlıyorum, ama çalışır halini görmek farklı olacaktır.

    1. Özcan Acar avatarı
      Özcan Acar

      Pratik Spring (http://www.pratikprogramci.com/urun/pratik-spring-core-ozcan-acar/) kitabimda AOP’yi anlatan bir bölüm mevcut. Bunun yani sira AspectJ catisina bir göz atabilirsiniz.