Open Closed Principle (OOP Principles-1)

Standart

Uzun zaman oldu yazmayalı. Uzunca bir süredir tatil modundayım anca çıkabildim tatil havasından 😀 neyse geyik yapmayı bırakıp konuma döneyim en iyisi. Nedir bu Open Closed Principle? Aslında mevzu çok basit bir amaç içeriyor oda yazmış olduğumuz bir programın hali hazırda yazılmış kısımlarına müdahale etmeden programa yeni özellikler kazandırabilmek yani programı genişletmek. Yani kısaca yazılmış bir programın kaynak kodunun genişletmeye açık değişime kapalı olmasıdır. Neden böyle bir şey yapmaya ihtiyac duyacağız diye soracaklar olabilir. Bu soruları açıklığa kavuşturacak örneklerle birlikte gidermeye çalışacağım kısmetse

İlk örneğimizde bu prensibe uyulmadan yazılmış kodları inceleyip ileride karşımıza çıkaracağı sorunlardan bahsedeceğim.


// Open-Close Principle - Kötü örnek
class GraphicEditor {

 	public void drawShape(Shape s) {
 		if (s.m_type==1)
 			drawRectangle(s);
 		else if (s.m_type==2)
 			drawCircle(s);
 	}
 	public void drawCircle(Circle c) {....}
 	public void drawRectangle(Rectangle r) {....}
} 

class Shape {
 	int m_type;
}

class Rectangle extends Shape {
 	Rectangle() {
 		super.m_type=1;
 	}
}

class Circle extends Shape {
 	Circle() {
 		super.m_type=2;
 	}
} 

Görüldüğü üzere Graphic editor sınıfı Shape türünde parametre alan bir çizim methodu içeriyor. Ve Shape sınıfından türetilmiş daire ve dörtgen ise şimdilik programın çizebildiği şekiller. Peki yeni bir şekil eklemek istesek mesela üçgen de çizsin istiyoruz program programın yeni hali aşağıdaki gibi olacak sadece değişiklikleri ekliyorum.


//uygulamaya yeni eklenen üçgen sınıfı
class Triangle extends Shape {
 	Triangle() {
 		super.m_type=3;
 	}
} 

//GraphicEditor sınıfı ise şu şekilde değişecek
class GraphicEditor {

 	public void drawShape(Shape s) {
 		if (s.m_type==1)
 			drawRectangle(s);
 		else if (s.m_type==2)
 			drawCircle(s);
                else if (s.m_type==3)
 			drawTriangle(s);
 	}
 	public void drawCircle(Circle c) {....}
 	public void drawRectangle(Rectangle r) {....}
        public void drawTriangle(Triangle t) {....}
} 

Görüldüğü gibi yeni bir özellik eklerken daha önceden yazdığımız kodlarıda değiştirmek zorunda kaldık(GraphicEditıor sınıfı). Eğer yüzlerce şekil eklemek zorunda kalsaydık ve böyle tek tek değiştirmek nekadar maliyetli olacaktı? Peki programı yıllar önce yazdıysak ekleyeceğimiz genişletmelerin nerelerde defect oluşturacağını kesinlikle tam kestiremeyiz ve genişletelim derken elimizde satırlarca düzeltilmeyi bekleyen hata ile kala kalırız. Peki böyle bir durumdan nasıl kurtuluruz? Her sınıf kendi çizdirme methodunu içerse GraphicEditıor sınıfı her nesneyi hangi tür bu diye kontrol etmek zorunda kalmayacaktır sadece nesne.draw ile tür bilgisine ihtiyaç duymadan çizim yapabilecek.


// Open-Close Principle Doğru örnek
class GraphicEditor {
 	public void drawShape(Shape s) {
 		s.draw();
 	}
}

abstract class Shape {
 	abstract void draw();
}

class Rectangle extends Shape  {
 	public void draw() {
 		// dörtgen çiz
 	}
} 

class Circle extends Shape  {
 	public void draw() {
 		// daire çiz
 	}
} 

Eğer bu kodun üçgen çizmesini istiyorsak aşağıdaki sınıfı tanımlamak yeterki olacak ve kodda başka bir değişiklik yapmamıza da gerek yoktur.


class Triangle extends Shape  {
 	public void draw() {
 		// üçgen çiz
 	}
} 

Yorum bırakın