Günümüzde birçoğumuz C#, Java gibi nesne yönelimli programlama dilleri kullanıyoruz. Peki kullandığımız dillerin gücünden ne kadar faydalanabiliyoruz? Geliştirdiğimiz uygulamalar, zaman içerisinde değişebilecek ihtiyaçlara ne kadar güçlü karşılık verebiliyor? Eğer object oriented programlama yapıyor isek, dünya üzerinde standart kabul edilen 5 temel prensibi bilmemiz gerekiyor.
1. (S)ingle Responsibility Principle
2. (O)pen/Closed Principle
3. (L)iskov ‘s Substitution Principle
4. (I)nterface Segregation Principle
5. (D)ependency Inversion Principle
Solid’e ek olarak Kiss, Yangi, Dry, Reuse Release Equivalence, Common Closure prensipleri de bulunmaktadır.
Şimdi kısaca bu prensiplerin neler olduğundan bahsedelim:
1.Single Responsibility Principle
Her ne kadar kaliteli kod yazmak için özen göstersek de, çalışma hayatında önümüze sadece kendi geliştirmiş olduğumuz projeler gelmiyor. Tek bir class içerisinde yazılmış binlerce satır kodu okuyup anlamaya çalışmak (belki sadece küçük bir revizyon için) zorunda kalabiliyoruz. Böyle durumlarda ekip arkadaşlarınızla aranızda şöyle konuşmalar geçtiği olur:
+Şu projede biraz optimizasyon yapsak mı?
– Abi çalışıyorsa hiç dokunmayalım.
Projenin içerisindeki her bir yapı, diğer yapılara o kadar bağımlıdır ve yapılan işler o kadar iç içe geçmiştir ki; küçük bir değişikliğin neleri etkileyeceğini kestirmeniz çok zordur ve genelde böyle projeler çöp proje olarak görülür. İçerisindeki class’ları methodları alıp başka bir projede kullanamazsınız.
Eğer tek sorumluluk prensibine uyarsanız bu şekilde binlerce satırlık class’larınız methodlarınız olmaz. Her class’ın, her mothodun sadece tek bir yaptığı iş vardır, böylece bir değişiklik yapmak için sadece bir nedeniniz olmuş olur. Genişleyebilir, tekrar kullanılabilir ve test edilebilir yapılar kurmak için tek sorumlulukilkesini dikkate almamız gerekir.
2.Open/Closed Principle
Açık kapalı prensibi, yazılım geliştirirken kullandığımız varlıkların (class, method vs.) gelişime açık, kodların ise değişime kapalı olması ilkesidir. Örneğin; bir loglama altyapısı oluşturduğunuzu düşünün, Veritabanına ve XML’e kayıt tutuyorsunuz. Daha sonradan Eventloglara da log tutma ihtiyacı hissettiğinizde, sadece Eventloglara kayıt tutan kodları yazmanız yetecek, kodunuzda hiçbir değişiklik yapmadan bu yapı sisteme entegre olacak. Bunun için uygulayacağımız çözüm şu şekilde olabilir:
Burada LogTo methoduna ILogger interface’inden implemente olmuş bir class veriyoruz. Yani; daha sonrasında gene ILogger interface’i üzerinden implemente olmuş EventLog isimli bir class yazarsak Logger sınıfı üzerinde hiçbir değişiklik yapmamız gerekmeden, sisteme n sayıda log tutan yapı entegre edebileceğiz.
3.Liskov ‘s Substitution Principle
Liskov’un yerine geçme prensibi alt sınıflardan oluşturulan nesnelerin üst sınıfların nesneleriyle yer değiştirdiklerinde aynı davranışı göstermek zorunda olduklarını söyler. Yani; türetilen sınıflar, türeyen sınıfların tüm özelliklerini kullanmak zorundadır. Eğer kullanmaz ise ortaya işlevsiz, dummy kodlar çıkacaktır. Bu durumda üst sınıfta if else blokları kullanarak tip kontrolü yapmamız gerekebilir ve böylelikle Açık Kapalı prensibine de ters düşmüş oluruz.
Burada IDeveloper interface’ini implemente eden Junior Developer ve Senior Developer class’ları olduğunu görüyoruz. Ancak proje geliştirilirken bir sorun olduğunu farkettik. Junior Developer’ımız solid ilkelerini kullanamıyor Yapıyı bu şekilde kurmaya devam edersek ya bu methodun içini boş bırakıcaz ya da NotImplementedException throw edicez ve ClientApp uygulamamız IDeveloper interface’i üzerinden, IDeveloper’dan implemente olan tiplerini kullanıp Açık Kapalı prensibine bağlı kalabilecekken eğer JuniorDeveloper değil ise SolidIlkeleriniKullan() diyen bir if else bloğuna sahip olucak.
Peki böyle bir durumda çözüm nasıl olabilirdi? Bu yanlış tasarımın önüne nasıl geçeriz?
Class Diagramından da anlaşıldığı gibi Developer sınıfını soyut yaptık ve ISolidKullanabilir isimli bir Interface oluşturduk. Böylelikle Liskov prensibine bağlı kaldığımız gibi, oluştuduğum dll’i kullanan Client Uygulaması da if else bloğuna gerek kalmadan Açık Kapalı prensibine uygun olabilecek.
4.Interface Segregation Principle
Arayüz ayırım prensibi, bir arayüze gerektiğinden fazla yetenek eklemememiz gerektiği söyler.
Yukarıdaki Diagrama baktığımızda IArac Interface’inde Calistir, Durdur ve KlimayiAc method imzalarının tanımlanmış olduğunuz görüyoruz. Ancak burada bir sorun var. BMV class’ı bütün methodları implemente edebilirken Murat131 de klima özelliği yok.
Böyle bir durumda Arayüz ayırım prensibinin bize önerdiği çözüm şu: Eğer interface’iniz implemente olacağı tüm sınıflarda desteklenemiyorsa Interface’inizi bölün. Bu ilkeye uyarak yapıyı tekrar kuralım:
Burada IKlimaliArac interface’ini IArac interface’inden türettik. BMV sınıfı IKlimaliArac, Murat131 ise IArac interface’ini implemente ederek Arayüz Ayırma Prensibine uygun bir tasarıma sahip olmuş oldu.
5.Dependency Inversion Principle
Bağımlılığın ters çevirilmesi ilkesine göre üst seviye sınıflar, modüller, methodlar vs. alt seviyeli sınıflara bağımlı olmamalıdır. Alt sınıflarda yapılan değişiklikler üst sınıfları etkilememelidir.
Yangi Principle : You Aren’t Gonna Need It!
Kaynak : http://tarikkaygusuz.com/