Solid prensibi: yazılımın esnek, sürdürülebilir, anlaşılır, kod tekrarını önleyen Solid prensiplerinin ikinci harfi olan “O” harfine karşılık gelen prensip diyebiliriz. 1988 yılında Fransız Akademisyen Bertrand Meyer tarafından ortaya atılmış olup, kendisi tanımını şu şekilde yapmıştır.
“Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification.”
İşin Türkçesi; yazılımda kullanılan varlıkların değişime kapalı, gelişime açık olması prensibi.
Neden ihtiyaç duyarız?
Yazılımda kod blokları çoğu zaman aynı kalmaz, zaman içinde değişikler meydana gelebilir. Analiz sürecinde eksiklikler olabilir, yazılımda yeni ve önemli bir update gelmiş olabilir, müşterinin yeni istediği özellikler olabilir veya yazılım süreci en başında adım adım planlanmış olabilir. Bu gibi durumlarda Open Closed prensibi, yeni olacak değişiklikleri eklerken projemizin ilgili bölümündeki genel davranışların değiştirmeden, birkaç küçük değişiklikle yapacağımız geliştirmeleri projemize entegre etmemiz gerektiğini anlatıyor. Yani ana bölüme müdahale etmeden geliştirme yapmamızı anlatıyor. Nedeni çalışan projemizde birçok bölümde yeni hatalara sebebiyet verebilme ihtimali diyebiliriz. Çünkü büyük bir projede bu gibi durumlarda test süreci gerektirir, bu da firmalar açısından olması gerekenden daha büyük bir zaman kaybına sebebiyet verebilir.
Örnek bir proje ile hem open closed kullanılmayan durumu hem de kullanıldığı durumu ele alalım:
Bir Computer classımızın olduğunu varsayalım. Oluşturduğumuz class içerisinde Brand olarak Asus-Lenovo isminde 2 enum değerimiz olsun. Daha sonra Computer class’ından implemente olmuş Asus ve Lenovo isminde 2 class oluşturalım ve constructor’larında gerekli enum değerlerini verelim.
public class Computer
{
public Brand Brand { get; set; }
}
public enum Brand
{
Asus,
Lenovo
}
public class Asus : Computer
{
public Asus()
{
this.Brand = Brand.Asus;
}
}
public class Lenovo : Computer
{
public Lenovo()
{
this.Brand = Brand.Lenovo;
}
}
Daha sonra ComputerFactory adında bir classımızın olduğunu varsayalım. Bu class içerisinde ProduceComputer isminde parametre olarak Computer’dan türemiş classları alabilen bir metod olsun ve bu metoda verilen objedeki brand enum değerine göre ilgili bilgisayarı üreten fonksiyonları çağırsın.
public class ComputerFactory
{
public void ProduceComputer(Computer computer)
{
switch (computer.Brand)
{
case Brand.Asus:
ProduceAsus((Asus)computer);
break;
case Brand.Lenovo:
ProduceLenovo((Lenovo)computer);
break;
}
}
private void ProduceAsus(Asus asus)
{
Console.WriteLine("Asus Produced\n");
}
private void ProduceLenovo(Lenovo lenovo)
{
Console.WriteLine("Lenovo Produced\n");
}
}
Main metodu içinde aşağıdaki gibi sırasıyla metotları çağırdığımızda proje çalışacak ve bize sırasıyla Asus Produced, Lenovo produced yazacaktır.
class Program
{
static void Main(string[] args)
{
ComputerFactory cf1 = new ComputerFactory();
cf1.ProduceComputer(new Asus());
ComputerFactory cf2 = new ComputerFactory();
cf2.ProduceComputer(new Lenovo());
Console.ReadLine();
}
}
Yukarıdaki projede Hp computer eklemek istediğimizde, müdahale edeceğimiz class ların sayısı çok fazla olmakta. Önce enum olarak hp eklemeliyiz, daha sonra hp classı oluşturup Computer classından türetmeliyiz. ComputerFactory clasımızda bulunan switch bölümüne müdahale edip motosiklet için case yazmalıyız. En sonunda çağırmalıyız. Böyle bir durumda bütün classlarda değişiklik yapmak zorunda kaldık.
Open-Closed prensibine uygun olarak bu örneği tekrarlayalım.
Computer isminde bir abstract clasımız ve Produce isminde abstract void metodumuzun olduğunu varsayalım. Daha sonra oluşturduğumuz Asus ve Lenovo Classlarını computer classından implemente edelim.
public abstract class Computer
{
public abstract void Produce();
}
public class Asus : Computer
{
public override void Produce()
{
Console.WriteLine("Asus Produced\n");
}
}
public class Lenovo : Computer
{
public override void Produce()
{
Console.WriteLine("Lenovo Produced\n");
}
}
ComputerFactory classımızda Computer alan ProduceComputer isminde bir metodumuz bulunmaktadır.
public class ComputerFactory
{
public void ProduceComputer(Computer computer)
{
computer.Produce();
}
}
Main metodu içinde aşağıdaki gibi sırasıyla metotları çağırdığımızda proje çalışacak ve bize sırasıyla Asus Produced, Lenovo produced yazacaktır.
static void Main(string[] args)
{
ComputerFactory cf1 = new ComputerFactory();
cf1.ProduceComputer(new Asus());
ComputerFactory cf2 = new ComputerFactory();
cf2.ProduceComputer(new Lenovo());
Console.ReadLine();
}
Burada biz hp eklemek istediğimizde Hp classını Computer clasından türeyecek şekilde oluşturmak ve main bölümde çağırmak.
Bu yapının avantajlarına gelecek olursak;
- Bağımlılıklar ortadan kalkarak oluşturulan proje daha generic bir yapıya geçmiş olması.
- Projede geliştirme yapılacak olunması durumunda zaman tasarrufu sağlanmış oluyor, hızlı ve güvenli olması,
- Projemiz daha esnek hareket etme olanağı sunmuş olması,
- Yapılacak bir eklemede çok büyük bir değişiklik yapılmadan projenin geliştirilmesi sağlanmış olması.
Böylelikle proje open-closed prensibine uygun hale gelmiştir.


Yorum Yap