8 Haziran 2016 Çarşamba

2 - OPEN/CLOSED PRINCIPLE (OCP) (Açık Kapalı Prensibi)

  Merhaba daha önceki yazımda SOLID prensiplerinden Single Responsibility Principle konusunu anlatmıştım,bu yazımda da SOLID kısaltmasındaki O 'ya denk gelen Open/Closed Principle - Açık Kapalılık Prensibine değiniyor olacağım. Konuya uzatmadan giriş yapmak gerekirse OCP bize;

"Yazılım varlıkları (Class,Modül, Fonksiyon, Method vb.) gelişime AÇIK, değişime KAPALI olamalıdır!"

diyor. Bu cümlenin orijinal hali ise Bertrand Meyer' in aşağıdaki ifadesidir.

 "software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification"

   Peki yazılım varlıklarının gelişime açık, değişime kapalı olması ne manaya geliyor? Bunu şu şekilde düşünebiliriz, ana görevi yüklenen class,modül,fonksiyon gibi yapıların zaman içerisinde kodsal olarak değiştirilmemesi, fakat yani eklenecek özelliklere de açık halde kalması gerektiğidir. "Hem yeni özellik ekleyip, hem de var olan yapıyı değiştirmeden bu işi nasıl yapabilirim? Sonuçta bir yerlere kod eklemek zorundayım ve yapıda mutlaka kodsal değişiklik yapmam gerekecek!" dediğinizi duyuyorum :) Anlaması da kurgulaması kadar zor bir yapıya daha hoş geldiniz diyorum. 
   OCP 'yi daha iyi anlatmak için, prensibin çıkış amacından bahsetmek gerekiyor galiba. Bu prensip kurgulanan yazılımın "Sürekli Değişime Maruz Kalacağı" düşünülerek ortaya çıkmıştır, nitekim de öyledir. Hiç bir projenin başlangıç aşamasından sonunda kadar olacak süreç belli değildir, hatta öyle projeler olur ki %50-60 oranında değişiklik dahi yapılır. Bunun bir çok sebebi vardır ve bu sebeplere burada girmek istemiyorum aksi halde yazı bitmez :) Bu kadar çok değişikliğin yapıldığı projelerde kodlar sürekli sil baştan yazılmak zorunda kalınmasın diye, varlıkların gelişime açık değişime kapalı olması gerekliliği ortaya çıkmıştır. Unutmayın ki her projede gelişim devamlı olacak, sürekli yeni istekler yeni geliştirmeler olacaktır. Tasarımları yaparken ilerde oluşabilecek yeni özellikleri de düşünerek yapmamız gerekecektir ki doğal olarak gelişime açık olsun.

Örnek - 1 :
 Şimdi e-ticaret yapan bir firmanın fatura hesaplama evresini düşünelim ve fatura dip toplam tutarının hesaplandığı tasarımı çıkaralım.















Futuraya ait toplam tutarın hesaplanmasında problem gözükmüyor. Şimdi bir de sipariş tutarının hesaplandığı ve sipariş tutarında iskonto hesabının yansımadığını düşünelim. 
























   Görüldüğü üzere ana işlevi yerine getiren "TutarHesapla()" fonksiyonunu değiştirmek zorunda kaldık.Hatta ilerde farklı belge tipleri (İrsaliye, Fiş vs) geldikçe de sürekli değiştirmek zorunda kalacağımız bir yapı oldu. Bu tarz bir program bağımlılıklardan dolayı hatalıdır, eklemek istediğimiz her belge tipinde ana fonksiyonu sürekli değiştirmek zorunda kalacağımız aşikar ve bu durumda hem ileride düşeceğimiz sıkıntılar hem de çıkabilecek binbir türlü hata gözünüzün önünde canlanmıştır.
   Şimdi gelelim yapımızı OCP' ye uygun hale getirmeye.Öncelikle ana işlevi yerine getiren metodu değişime kapalı hale getirip, programı da gelişime yeni modüllerin eklenmesine açık hale getirmem gerekiyor. Ayrıca enum tipli yapıdan da sıyrılmam gerekiyor. Peki bunu nasıl yaparım derseniz, işte tam da bu noktada abstract class 'lar devreye giriyor.























     Son yapılan refactoring ile şimdi programın gelişime açık, değişime kapalı olması prensibini gerçeklemiş oldum.Artık tek yapmam gereken "Belge" sınıfından türeyen yeni bir sınıf inşa etmek olacak (gelişime açık), ayrıca "TutarHesapla()" fonksiyonunda artık hiç bir değişiklik yapmak zorunda kalmıyorum (değişime kapalı). Tüm bunlara artı olarak bir önceki yazıda anlatmış olduğum SRP 'ye de uygun olduğunu görebilirsiniz, her sınıfın kendine ait 1 işlevi ve her metodunda 1 görevi vardır. Aslında üstteki yapı Liskov Prensibine de uyuyor, fakat bir sonra ki yazımda o noktaya değineceğim için şuan girmiyorum.

Örnek - 2 :
Bir önceki örnek OCP uygulamanın en basit tekniğinden (abstract class) birisiydi. Şimdi ise biraz daha farklı olarak Interface yapısı ile programı OCP 'ye uygun hale getiririz ona bakalım.Öncelikle hatalı yapıyı kurgularsak, aşağıdaki gibi olacaktır.



Intarface kullanılmasına rağmen "TutarHesapla()" metodunda hem gereksiz yere hemde OCP'ye uymayan tarzda kodlar yazılmıştır. Bu kısım eklenen her belgede yine değiştirilmek zorunda kalacaktır. Şimdi burayı değişime kapalı hale getirip, daha genel bir yapıya aşağıdaki gibi çevirebiliriz. Dip not olarak aslında alttaki örneğin de SRP ve Liskova uyduğunu unutmayınız.

























     SOLID' in  O'su olan OCP'nin olayı aslında temel olarak bu kadar. Yazılımda kodlarla oynanmadan zaten bir geliştirme olamaz, fakat amacımız temel işlevi üzerinde barındıran kodlarda değişiklik yapmadan, belli kısımlarda ekleme yaparak mümkün mertebe çok az kod yazacak şekilde istenen geliştirmeyi tamamlayabilmektir. Böylelikle bu ilkenin temel amacının minimum kod yazma olduğunu belirtebiliriz.
Bir sonraki yazım olacak olan SOLID 'in L'si Liskov Subtutition Principle 'de görüşmek üzere.

Hiç yorum yok:

Yorum Gönder