green red and yellow wall

Liskov Substitution Principle (Liskov’un Yerine Geçme Prensibi)

Bu prensibin odak noktası; alt seviyedeki nesnelerin, üst seviyedeki nesneler ile yer değiştirebilir olmasını sağlamaktır. Alt seviye bir sınıf, üst seviyesi olan sınıf ile aynı şekilde davranmalı ve üst sınıfın tüm özelliklerini kullanabilmelidir.

Bu prensibi Open/Closed Principle (Açık Kapalı Prensibi) aklımızın bir köşesinde tutarak anlamaya çalışırsak kavramamız çok daha kolay olacaktır.

Alt seviye sınıfın bağlı oldukları üst seviye sınıf ile aynı şekilde davranabilmesi ne demek?
Vehicle adında bir sınıfımız olsun. Sonra bu sınıfı inherit eden (miras alan) Airplane ve Train sınıflarımız olsun. Vehicle sınıfı içerisinde closeDoors ve doFly metodumuz olursa;

Airplane için doFly metodu uygulanabilir, fakat Train :/ Trenler uçamaz… Bu durumda Train sınıfı içerisinde doFly metodu için NotImplementedException fırlatabiliriz fakat bu iyi bir çözüm olmaz. Eğer bu tabloyu closeDoors için değerlendirecek olursak karşımıza bir sorun çıkmaz çünkü uçak ve tren için kapıları kapatma metodu kullanılabilir.

Peki doğru çözüm nedir?
Doğru çözüm ortak noktaları içeren sınıflar oluşturmak, ayrıştıkları noktalar için arayüzler (Interfaces) kullanmak olacaktır. Yani doğru çözümümüz şu şekilde olacaktır;

Vehicle sınıfımız içerisinde yalnızca closeDoors metodu bulunur. Çünkü ortak noktaları kapılarının olması ve kapatılabilir olmasıdır. Airplane için ise IFlyable adında bir interface (arayüz) oluşturup, içerisinde doFly metodunu tanımlayıp bunu implement etmeliyiz.

Doğru çözüm ile Vehicle sınıfını referans aldığımız bir yerde Airplane ya da Train kullanabilir olduk. Yani ana sınıf olan Vehicle yerine ondan türetilmiş Airplane, Train sınıflarını koyabildik. Artık ana sınıf yerine türetilen alt sınıfları koyabilir ve stabil şekilde kullanabiliriz.

Ayrıca elimize gelen aracın uçabilir olup olmadığını kontrol etmek için ise IFlyable interface’inden türeyip/türemediğini kontrol etmemiz yeterli olacaktır.

Faydası ne oldu?
Eğer iyi olmayan çözümü uygulasaydık ve doFly için NotImplementedException fırlatsaydık bu metodu kullanmak istediğimiz her yerde exception handling yapmamız gerekirdi hatta olası akış bozukluklarına (yarıda kesilme, eksik tamamlanma) sebep olabilirdik. Bu prensibi dikkate alarak uyguladığımız iyi çözümde ise IFlyable interface kontrol edeceğimizden olası hataların önüne geçmiş olduk ve mimari açıdan çok daha doğru bir yapı kurmuş olduk. Eğer bir gün uçabilen araçlarımızın listesine ihtiyacımız olursa bu interface’in referanslarına bakarak kolayca ulaşabileceğiz.

Inherit ettiğiniz sınıflardan beklenmedik exceptionlar fırlamadığı akıl dostu projelerde görüşmek üzere…