(Turkish) SOLID 2 – Açık/Kapalı Prensibi

Bu yazımızın konusu Açık/Kapalı Prensibi (“Open-Closed Principle”- OCP). Öncelikle sizlere bu prensibe ilişkin kısaca bilgi vermeye çalışacağım, daha sonra da örnek bir kod parçası üzerinden bunu nasıl uygulayabileceğimize birlikte bakacağız.

Açık/Kapalı Prensibi (Open/Closed Principle)

Prensibinin amacını tek cümle ile aşağıdaki gibi özetleyebiliriz:

 “Yazılım birimleri (ki bunlar sınıflar, modüller veya fonksiyonlar olabilir) genişlemeye açık ama modifikasyona kapalı olmalıdır.” (Bertrand Meyer). 

Bu prensip, SOLID prensiplerin arasında en önemli olanlarından birisidir (Hatta Robert C. Martin tarafından nesne yönelimli tasarımın en önemli prensibi olduğunu ifade etmiştir) ve Nesne Yönelimli Tasarım yaklaşımının da tam kalbinde bulunmaktadır. 

Basit bir şekilde ifade etmek gerekirse, her gereksinim değiştiğinde, yazmış olduğumuz kabiliyete ilişkin kodları değiştirmek zorunda kalmamalıyız ya da yazılımlarımızı bunu göz önüne alarak geliştirmeliyiz.

Peki yapmazsak ne olur? Bir uygulama tasarladınız ve bu uygulamaya ilişkin değişiklikler gerekmekte, eğer bu değişiklikler, ilgili modül dahil birçok alt modülde de değişikliğe neden olup istenmeyen sonuçlara sebeb oluyor ise, bu bize aslında çok da doğru bir tasarım yapılmadığının ipucunu verebilir. Sonuç olarak bu şekilde programlar, idameleri zor, kırılgan ve karmaşık bir hale geliyorlar. Ayrıca bu tarz kabiliyetin kendisine ilişkin yapılan değişiklikler, test eforlarını arttırıp, yazılım modüllerinin tekrar oluşturulması ve dahi konuşlandırma (deployment) maliyetlerini artırır.

İşte açıklık/kapalılık prensibi tam olarak bu tarz sonradan ortaya çıkabilecek sorunları önlemek için ortaya konulmuştur. Bu prensibin doğru bir şekilde uygulanması ile birlikte, olası değişikliklerde, mevcut yazılımınızda gerçekleştirilecek olan değişikliklerin minimum seviyede tutulmasını sağlıyor olacaksınız. 

Peki bu prensibe riayet eden modülleri nasıl ifade edebiliriz:

  • Genişlemelere açıktırlar:
    • Modülü sergilediği kabiliyet, gereksinim değişiklikleri veya yeni gereksinimler ışığında, genişleyebilir. Burada, yeni kabiliyetler için modülün genişletilmesi zaten onun kodları değiştirilmesi anlamına gelmez mi diye düşünebilirsiniz ama mevcut sınıfı değiştirmeden de bunu yapabilmenin yöntemleri mevut.
  • Modifikasyonlara ise kapalıdırlar:
    • Modülün kendisine ilişkin kaynak kodların değişikliğine ise izin verilmez/gerek kalmaz. Örneğin, DLL veya .jar kütüphanelerinde bir değişiklik yapılmasına gerek kalmaz. Tabi burada hata düzeltmelerini ve dile ilişkin ya da benzeri güncellemeleri göz ardı etmemiz gerekiyor.

Peki bu prensipleri nasıl sağlayacağız? Bu konuya değinen ilk yazarlar, genelde bu prensibin, miras yolu ile karşılanabileceğini ifade etmişlerdi ki, artık ata sınıfın geliştirme detaylarına dayanan bir miras bize daha fazla bağımlılık getirmekte ve genelde kaçınılmaktadır. Bunun yerine, soyut sınıflar/metotlar ya da bir diğer ifade ile arayüzleri (C++’larda “pure abstract” sınıflar ve Java’lar daki Inteface sınıflar bu kategoriye dahil edilebilir) kullanan yaklaşım kabul görmektedir. Bu arayüzler modifikasyona kapalı, fakat genişlemeye açıktırlar. 

Bu sayede elde ettiğimiz en önemli kazanç, bu arayüzler sayesinde ek bir soyutlama seviyesi ve gevşek bağlaşım (türkçesi biraz garip oldu farkındayım. Bahsettiğim kavram loose coupling) elde edilmesidir. Bu arayüzleri gerçekleyen sınıfların birbirleri arasında herhangi bir kod paylaşımına da ihtiyaç olmayacaktır.

Şimdi basit bir çizim kabiliyeti geliştirdiğimizi düşünelim. Öncelikle OCP’yi göz önünde bulundurmadığımız duruma bakalım. Bu bağlamda, kabiliyetimizi geliştirirken, sadece çember ve kare çizeceğini düşündük ve aşağıdaki gibi sınıfları geliştirdik.

Yazılımımızı geliştirdik ve her şey güzel giderken, müşteri dikdörtgeni de şekiller arasında çizmemizi istedi, ne yapacağız? Öncelikle bir tane dikdörtgen sınıfı ekledik, şu ana kadar bir sıkıntı yok ama Painter sınıfımızı da değiştirmemiz gerekecek, işte burada OCP prensibimizin closed kısmı tarumar oldu. Peki bu kabiliyeti, Painter sınıfını değiştirmeden nasıl ekleyebilirdik? Interface desem, aklınıza ne gelir? Evet yanılmadınız, bir IShape ata sınıfı ile sanki daha kolay uyarlanabilir bir tasarım elde edeceğiz gibi görünüyor, tabi Painter sınıfına da bir dokunmamız gerekecek. Öncelikle mevcut sınıflarımızı bu bağlamda güncelleyelim:

Şimdi bu noktada dikdörtgen sınıfını eklediğimizde neler değişecekti? Aslında bakarsanız, aşağıdaki gibi Painter sınıfına artık dokunmamıza gerek bile kalmayacak. Hemen bakalım:

Gördüğünüz üzere ufak dokunuşlar ile ilk yazdığımız kodu OCP prensibine uygun ve daha genişleyebilir bir hale getirmiş olduk.

Burada değinmek istediğim bir diğer nokta da şu, yazılımların yaşam döngüsü süresince bazı değişikliklerin olabileceği her zaman göz önünde bulundurmalıyız. Yani bir diğer ifade ile gereksinimlerin veya ihtiyaçların hiçbir zaman değişmeyeceğini kabul ederek, yazılım tasarlayıp, geliştirmenin, günümüz şartları için hiçbir geçerliliği yoktur. Yazılımlarımızı gereksinim basit gereksinim değişikliklerine etkin bir şekilde cevap verecek şekilde geliştirmeliyiz. Ama bu mevzuyu da çok ileri bir noktaya taşıyıp, gereğinden karmaşık yazılım tasarımlarından da kaçınmalıyız. Tabi buradaki anahtar kelime “basit” neye göre, kime göre? İşte bu noktada, yazılım ürün hatları (inşallah ileride bu konuya da değineceğim) için önemli bir adım olan alan analizinin uygulanmasını tavsiye edeceğim. Bu analiz ile birlikte ilgili kabiliyete ilişkin aslında kapsam ve olası ortak ve değişkenlik gösteren nitelikler ve özellikler belirlenmektedir.

Sonuç olarak, bu prensibin başarılı bir şekilde uygulanması ile birlikte yazılımlarınıza değişiklikleri daha kolay ve kontrollü bir şekilde yapabileceksiniz. Örneklerde de gördüğümüz üzere, bu prensibi miras ve polimorfizmi kullanarak gerçekleştirebiliyoruz. Ayrıca bu bağlamda 

 

https://www.oodesign.com/open-close-principle.html

https://code.tutsplus.com/tutorials/solid-part-2-the-openclosed-principle–net-36600

http://joelabrahamsson.com/a-simple-example-of-the-openclosed-principle/

 

Kaynaklar:

http://joelabrahamsson.com/the-openclosed-principle-a-real-world-example/ => Gerçek hayattan kullanım örneği

 

https://www.youtube.com/watch?v=t86v3N4OshQ

https://www.youtube.com/watch?v=JLURCz3dDtY => ev gösterimi güzel

https://www.coursera.org/lecture/design-patterns/2-3-2-open-closed-principle-hYSeT

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.