Daha önce Liskov'un İkame Prensibi (LSP) ile Açık-Kapalı Prensibi (OCP) üzerine bir cevap yazdım ve her iki prensip de birbiriyle çok ilgili, ancak yine de birine sahip olan ancak diğeri olmayan bazı örneklerle kavramsal olarak farklı. Bu cevap yüzünden sadece OCP'ye kısaca değineceğim ve DIP'ye ve bu kene ne yapar?
İlk önce farklı ilkeleri açıklayarak OCP'nin Bağımlılık Tersine Çevirme İlkesi (DIP) ile nasıl bir ilişki içinde olduğunu ve bunlardan nasıl farklılaştığını tartışmaya çalışalım.
Bağımlılık Ters Çevirme İlkesi
Bob Amca'nın OOD İlkelerini okurken DIP'nin aşağıdakileri belirttiğini göreceksiniz:
Betonlara değil soyutlamalara bağlıdır.
Java'da bir soyutlama interface
ve abstract
anahtar kelimelerle elde edilir , yani kodun izlemesi gereken bazı yazılım varlıkları için bir "sözleşmeniz" vardır. Bazı programlama dillerinde kodun izleyeceği davranışları açıkça belirleyecek bir tesis bulunmadığından, derleyicilerin sözleşmeyi uygulamanıza yardımcı olması yerine soyutlamaların daha manuel bir şekilde izlenmesi gerekir. C ++ 'da sanal yöntemlere sahip sınıflarınız ve Javascript gibi dinamik programlama dilleriniz var, nesneleri aynı şekilde kullandığınızdan emin olmalısınız (Javascript söz konusu olduğunda bu, size yardımcı olmak için bir tür sistemi ekleyen TypeScript'te genişletilmiştir. derleyici tarafından doğrulanan yazılı sözleşmelerle).
Geleneksel olarak (programlamanın eski karanlık çağlarında bildiğiniz gibi) düşük seviye modüllerine bağlı olarak daha üst seviye modüllere sahip yazılım yapıları yazdığınız için bu ad "ters çevirme" terimini içerir. Örneğin ButtonAtKitchen
, bir KitchenLamp1
ve için işleme girdileri olması mantıklıydı KitchenLamp2
. Ne yazık ki, yazılım olması gerekenden çok daha spesifik hale geldi ve nesne grafiği şöyle görünecekti:
Yani yazılımı daha genel hale getirdiğinizde, "sözleşmeler" ekleyerek. Nesne grafiğindeki okların yönü nasıl tersine çevirdiğine dikkat edin. Mutfak lambaları artık a Button
. Başka bir deyişle, ayrıntılar artık tam tersine değil soyutlamalara bağımlı.
Böylece, Bob Amca'nın DIP'nin orijinal makalesinde ayrıntılı olarak açıklanan daha genel bir DIP tanımımız var .
A. Yüksek seviye modülleri, düşük seviye modüllerine bağlı olmamalıdır. Her ikisi de soyutlamaya bağlı olmalıdır. B. Soyutlamalar detaylara bağlı olmamalıdır. Ayrıntılar soyutlamalara bağlı olmalıdır.
Açık-Kapalı Prensibi
Bob Amca'nın ilkelerinden devam ederek OCP'nin aşağıdakileri belirttiğini göreceksiniz:
Bir sınıf davranışını değiştirmeden genişletebilmeniz gerekir.
Bunu başarmanın bir örneği, bir sınıfın modifikasyonlar için kapalı olduğu Strateji modelini kullanmaktır (yani dahili kodunu hiç değiştiremezsiniz), ancak aynı zamanda ortak çalışma bağımlılıkları (yani strateji sınıfları) aracılığıyla uzantıya açıktır .Context
Daha genel anlamda, herhangi bir modül genişletme noktaları ile genişletilebilecek şekilde üretilmiştir.
OCP DIP'ye benzer, değil mi?
Hayır , pek değil.
Her ikisi de soyutlamaları tartışıyor olsalar da kavramsal olarak farklıdırlar. Her iki ilke de farklı bağlamlarda, belirli bir modülde OCP ve birkaç modülde DIP üzerinde durmaktadır. Her ikisini de Gang of Four tasarım desenlerinin çoğunda olduğu gibi elde edebilirsiniz, ancak yine de yoldan uzaklaşabilirsiniz.
Yukarıda belirtilen DIP örneğinde, düğme ve mutfak lambaları ile, mutfak lambalarının hiçbiri genişletilebilir değildir (şu anda olması gerektiğini açıklayan herhangi bir gereklilik yoktur). Tasarım OCP'yi kırıyor ancak DIP'yi takip ediyor .
Bunun tersi (ve uydurulmuş) bir örnek, bir mutfak lambasının uzatılabilir olması (uzama noktası a gibi bir şeyle LampShade
) olacaktır, ancak düğme hala lambalara bağımlıdır . Bu edilir DIP kırma ama OCP'yi izler .
Endişelenme, olur
Bu aslında üretim kodunda sıkça göreceğiniz bir şeydir, bir kısmı bir ilkeyi kırabilir. Daha büyük yazılım sistemlerinde (örn. Yukarıdaki örneklerden daha büyük herhangi bir şey), bir ilkeyi çiğneyebilir, ancak genellikle kodu basit tutmanız gerektiğinden diğerini koruyabilirsiniz. Benim düşünceme göre, bu Tek ve Sorumluluk Prensibi (SRP) ile ilgili bağlamda olduğu için küçük ve bağımsız modüller için uygundur.
Bazı modül karmaşık hale geldiğinde, büyük olasılıkla tüm ilkeleri göz önünde bulundurarak bakmanız ve iyi bilinen bir şablona yeniden tasarlamanız veya yeniden düzenlemeniz gerekir.