Java Kodunuzun Nesne-Merkezli Olmadığının 10 İşareti – I

Nesne-merkezli programlamanın “ne”liği konusu pek çok kişi için halen muğlaktır. C++, Java, Python ya da C# gibi nesne-merkezli bir dil kullanıyor olmanın yazdığımız programları doğrudan nesne-merkezli yapmayacağı çok açık. Çünkü bu dillerde hem prosedürel/yordamsal program yazmak için yeterince imkan vardır hem de programcılar daha az nesne-merkezli kod yazmanın yollarını rahatlıkla bulmakta ya da bu yollara düşmektedirler. Java gibi nesne-merkezli diller bize nesne-merkezli kod yazmak için imkanlar sunmaktadır ama örneğin en azından nelerin nesne olacağı ve nesnelerin  aralarındaki ilişkilerin nasıl olacağı gibi kararlar tamamen biz geliştiricilerin/tasarımcıların sorumluluğundadır. Bu sorumluluğu yerine getirmede sıkıntılar yaşadığımız müddetçe Java’nın bize sağlıklı bir nesne-merkezli yapı oluşturmak için yardım etmesi mümkün değildir.

Ben Java ilk çıktığı zamandan bu yana Java’yı kullanmaktayım. Ve hayatımı, son 10 senede zaman zaman, son 6 senede ise tamamen Java ve Yazılım Mühendisliği eğitimleri vererek ve danışmanlıkları yaparak kazanmaktayım. Bu süre zarfında çok farklı tür ve yaklaşımla yazılmış pek çok Java kodu gördüm. Bu Java kodlarının pek çoğu emin olun, Java ile kod geliştirdiği için kodunun doğrudan nesne-merkezli olduğunu düşünen geliştiriciler tarafından yazılmıştı. Halbuki bu hiç bir şekilde doğru değildir. Yani Java’yı kullanarak bir sınıf oluşturup, içine üç-beş tane private nesne değişkeni (instance variables) tanımlayıp, sonra da bu sınıfa set/get metotlarını koymak, kesinlikle kodunuzu nesne-merkezli yapmaz. Nesne-görünümlü yapabilir ama nesne-merkezli programlamanın, bundan daha fazla olduğunu söylememiz gereklidir.

Nesne-merkezli kod yazmak, sınıflar tanımlayıp onlardan nesne oluşturmaktan çok daha fazlasıdır. En önemlisi örneğin, yukarıda da bahsettiğimiz gibi nelerin nesne olacağı ve nesnelerin aralarındaki ilişkiler gibi kararlar tamamen biz geliştiricilerin/tasarımcıların sorumluluğundadır. Doğru nesneleri bulmak ve aralarındaki ilişkileri sağlıklı bir şekilde oluşturmak çoğu zaman bulunan nesneleri Java’da tanımlamaktan çok daha zordur. Gang of Four yani GoF (ya da dörtlü çete) yazdıkları Design Patterns kitabında şöyle demektedirler:

“The hard part about object-oriented design is decomposing a system into objects. The task is difficult because many factors come into play: encapsulation, granularity, dependency, flexibility, performance, evolution, reusability, and on and on. They all influence the decomposition, often in conflicting ways.”

Türkçe olarak bu alıntıyı şöyle kurgulayabiliriz:

“Nesne-merkezli tasarımın zor tarafı sistemi nesnelere parçalamaktır. Bu iş zordur çünkü bunu yaparken pek çok faktör işin içine girer: kapsülleme, nesnenin boyutları (büyüklüğü), bağımlılık, esneklik, performans, gelişim, tekrar kullanım vb. Bütün bu faktörler, çoğu zaman birbirlerine ters düşecek şekilde bu parçalamayı etkilerler. ”

Doğru nesneleri bulmak yeterli değildir. Aslolan doğru nesneleri bulup, onları ve aralarındaki ilişkileri doğru bir şekilde kurgulayabilmektir öyle ki daha az karmaşık ve daha kolay değişebilen yazılımlara sahip olalım.

GoF’un tasarım şablonları bu zor işte bize yardımcı olurlar. Kitaplarındaki şablonlar, doğru nesneleri bulup doğru bir şekilde kurgulamak için farklı tasarım seçenekleri sunar. Bunu da geliştirdiğimiz yazılımın daha rahat değişebilmesi için yaparlar. “Design for change” (degişiklik için tasarla), GoF’un kitabının ilk bölümündeki üç temel prensiptenn birisidir. “Program to an interface, not an implementation” (arayüze program yaz, gerçekleştirmeye değil) ve “favor object composition over class inheritance” (nesne bileşimini sınıf kalıtımına tercih et) kitabın ilk bölümünde savunulan diğer iki prensiptir.

Nesne-merkezli tasarım ve programlama üzerine çalışan bilge kişiler yukarıdaki gibi pek çok prensip ortaya koymuşlardır. “Single responsibility principle” (tek sorumluluk prensibi) ya da “dependency inversion principle” (bağımlılığin ters çevrilmesi prensibi) senelerdir bu konuda duyduklarımız arasındadır. Bu anlamda SOLID kısaltması en temel 5 prensibi anlatmaktadır.

Ben bu yazı dizisinde bu tip prensipleri açıklamak yerine, sıklıkla karşılaştığım ve kodumuzu az ya da çok nesne-merkezli olmaktan çıkaran işaretlere ya da kötü alışkanlıklara değinmek istedim ve bu amaçla bir liste yaptım:  Java Kodunuzun Nesne-Merkezli Olmadığının 10 İşareti (ya da Ingilizce olarak Top Ten Signs That Your Java Code Is not Object-Oriented).

Bu listedeki yanlış uygulamalar (ya da anti-patterns), yazdığımız Java kodunu hem daha karmaşık hem de daha az değişebilir yapmaktadır. Listedeki her maddeyi örneklerle açıklayacağım gibi, nesne-merkezli paradigmanın hangi en temel prensiplerini bozduğunu da ifade edeceğim. Dolayısıyla her madde içın ayrı bir yazı olacak. Sizden de hem bu liste için hem de listede olmayan ama sizin sıklıkla gördüğünüz bu tür yanlış uygulamalar için bana yardım etmenizi rica ediyorum.

İşte liste:

  1. Sınıflarda aşırı miktarda statik metot kullanımı (Excessive use of static methods in classes.)
  2. Yüksek içerik bağımlılığı (high content coupling). Bir başka sınıfın nesne değişkenlerine doğrudan erişim ya da aşırı set ve get metodu çağrısı. (Direct access to the instance variables or excessive number of calls to setters and getters of another class.)
  3. Kodunuzda hiç alan nesnesinin olmaması ya da olsa bile yetersiz olmaları. (No or very thin domain objects in the code.)
  4. Kodunuzda hiç ya da çok az sayıda arayüz olması. (No or very few interfaces in the code.)
  5. Aralarında benzerlik ilişkisi olan nesneleri modellemek için kalıtım kullanmamak. (No inheritance hierarchy to model is-a relationships between objects.)
  6. Çok sayıda metoda sahip olan sınıflar. (Classes with lots of methods.)
  7. Karmaşık metotlar. (Complex methods.)
  8. Demeter prensibini ihlal eden metotlar. (Methods that break the Demeter law.)
  9. Aşırı miktarda karar ifadelerine sahip olan metotlar. (Methods that include excessive number of decision statements.)
  10. Sıra dışı durumları ifade etmek için Exception nesneleri oluşturmamak. (No Exception objects to represent exceptional situations.)

Yanlış uygulamalardan kaçındığımız şiir gibi kodlar yazmak amacıyla…

Toplam görüntülenme sayısı: 2560