13 Ocak 2023 Cuma

SOLID prensiplerinden Open-Closed prensibinin python kodları eşliğinden yakından incelenmesi

Merhaba, 

Bugünkü yazımızda SOLID prensiplerinden 'Open-Closed Rrensibi' ni inceleyeceğiz.


Temsil edilen O harfi "Open-Closed Principle" (Açık-Kapalı Prensibi) anlamına gelir. Bu prensip, bir sınıfın veya modülün geliştirilmeye açık olmasının yanı sıra, uzantılar yapılarak kapatılması gerektiğini ifade eder. Bu, sınıfın veya modülün işlevselliğini genişletmek için değiştirilmemesi, ancak ekstra işlevsellik eklemek için uzantılar yapılması gerektiğini ifade eder.

Open-Closed Principle kullanmak, yazılımın daha esnek, daha test edilebilir ve daha az hata içerme olasılığına sahip olmasını sağlar. Özellikle, bu prensip ile yazılım kodunun değiştirilmesi gerektiğinde, mevcut kodun değiştirilmemesi ve yerine yeni kodun eklenmesiyle sorunlar çözülebilir. Bu, yazılımın daha uzun bir ömür yaşamasına ve daha az bakım gerektirmesine olanak tanır. Ayrıca, Open-Closed Principle kullanmak, yazılımın daha kolay test edilebilir olmasını sağlar çünkü sınıflar ve modüller arasındaki bağımlılıklar azaltılmış olur.

Open-Closed Principle kullanmazsanız, yazılım kodunuzun daha az esnek ve daha zor test edilebilir olmasına neden olabilir. Kodunuzun işlevselliğini genişletmek istediğinizde, mevcut kodun değiştirilmesi gerekebilir ve bu değişiklikler, başka yerlerde beklenmedik hatalara neden olabilir. Ayrıca, mevcut kodun değiştirilmesi, yazılımın daha hızlı çürümesine ve daha fazla bakım gerektirmesine neden olabilir.

Bunu bir python kodu ile açıklayalım :

 

class Rectangle: def __init__(self, width, height): self._width = width self._height = height def get_area(self): return self._width * self._height class Square(Rectangle): def __init__(self, side): super().__init__(side, side) class Circle: def __init__(self, radius): self._radius = radius def get_area(self): return 3.14 * (self._radius ** 2) class AreaCalculator: def __init__(self, shapes): self._shapes = shapes def get_total_area(self): total_area = 0 for shape in self._shapes: total_area += shape.get_area() return total_area


Burada, Rectangle, Square ve Circle sınıfları, get_area metodunu kullanarak alanlarını hesaplamak için tasarlanmıştır. AreaCalculator sınıfı ise, verilen şekillerin alanlarını toplamak için kullanılır. Bu örnekte, Rectangle ve Circle sınıfları "Open-Closed Principle" prensibine uymaktadır. Çünkü, bu sınıfların işlevselliği genişletilmek istendiğinde değiştirilmemektedir, ancak yeni sınıflar oluşturulmaktadır (örneğin Square sınıfı) ve bu sınıflar, genişletilmiş işlevselliği sağlamaktadır.

Bu örnekte, AreaCalculator sınıfı, verilen şekillerin alanlarını toplamak için kullanılmaktadır. Bu, AreaCalculator sınıfının, verilen şekillerin türlerinden bağımsız olarak çalışmasını sağlar. Bu, AreaCalculator sınıfının daha esnek ve daha az hata içerme olasılığına sahip olmasını sağlar.

Şimdi de bu prensibin ihlal edildiği bir örnek oluşturalım.

 

class Rectangle: def __init__(self, width, height): self._width = width self._height = height def get_area(self): return self._width * self._height class Square: def __init__(self, side): self._side = side def get_area(self): return self._side * self._side class Circle: def __init__(self, radius): self._radius = radius def get_area(self): return 3.14 * (self._radius ** 2) class AreaCalculator: def __init__(self, shapes): self._shapes = shapes def get_total_area(self): total_area = 0 for shape in self._shapes: if isinstance(shape, Rectangle) or isinstance(shape, Square): total_area += shape.get_area() return total_area


Burada, Rectangle, Square ve Circle sınıfları, get_area metodunu kullanarak alanlarını hesaplamak için tasarlanmıştır. AreaCalculator sınıfı ise, verilen şekillerin alanlarını toplamak için kullanılır. Bu örnekte, Rectangle ve Square sınıfları "Open-Closed Principle" prensibini ihlal etmektedir. Çünkü, AreaCalculator sınıfı, Rectangle ve Square sınıflarının alanlarını toplamak için kodunu değiştirmiştir. Bu değişiklikler, AreaCalculator sınıfının başka yerlerde beklenmedik hatalara neden olmasına olanak tanır.

Ayrıca, AreaCalculator sınıfı, Circle sınıfını dahil etmemektedir. Bu, AreaCalculator sınıfının daha az esnek ve daha zor test edilebilir olmasına neden olur.

Biraz daha detaya inersek :

 
def get_total_area(self): total_area = 0 for shape in self._shapes: if isinstance(shape, Rectangle) or isinstance(shape, Square): total_area += shape.get_area() return total_area

Bu kod bloğunda, AreaCalculator sınıfı, verilen şekillerin her birisini döngü içinde kontrol eder. Eğer şekil bir Rectangle sınıfı veya Square sınıfının bir örneği ise, şeklin alanını toplamaya ekler. Bu, AreaCalculator sınıfının sadece Rectangle ve Square sınıflarının alanlarını toplamasını sağlar.

Bu örnekte, AreaCalculator sınıfı, Rectangle ve Square sınıflarının alanlarını toplamak için kodunu değiştirmiştir. Bu değişiklikler, AreaCalculator sınıfının, daha sonra eklenen yeni şekil türlerini dahil etmemesi sonucunu doğurur. Örneğin, Circle sınıfının alanını toplamak istediğinizde, AreaCalculator sınıfının kodunu değiştirmek zorunda kalırsınız. Bu, AreaCalculator sınıfının daha az esnek ve daha zor test edilebilir olmasına neden olur.

Bu nedenle, Open-Closed Principle kullanmak, yazılımın daha esnek, daha test edilebilir ve daha az hata içerme olasılığına sahip olmasını sağlar.





Aşağıda bir başka kod parçacığında ihlalin nasıl olduğunu tekrar görelim.
 
class Shape: def __init__(self, type): self.type = type def draw(self): if self.type == "circle": # draw circle elif self.type == "square": # draw square # ...

Bu kod parçası, "open-close" prensibini ihlal eder çünkü "Shape" sınıfı, eklenen yeni bir şekil için her seferinde değiştirilmelidir. Örneğin, eğer yeni bir şekil tipi olarak "dikdörtgen" eklenirse, "Shape" sınıfının "draw" metodu değiştirilmelidir. Bu, "Shape" sınıfının açık olduğu anlamına gelir, ancak her yeni şekil için değiştirilmesi gerektiğinden kapalı değildir. Bu nedenle, "Shape" sınıfının değiştirilmesine gerek kalmadan yeni şekil tipleri eklenmelidir.

Teşekkürler
Cem Selmanoğulları