Liskov Substitution (LSP) Prensibi

liskov substitutaion prensibi

Solid prensiplerinin üçüncü maddesi Liskov Substitution prensibi ile yine birlikteyiz, bir önceki madde Open Closed Prensibinde de bu konuya biraz değindik.

Derived classes must be substitutable for their base classes.

Robert C. Martin

Liskov’un yerine geçme prensibi aslında OOP prensiplerinden Polymorphism (Çok biçimlilik) ile yakından ilgilidir. Buna göre türetilmiş sınıflar, alt sınıflarıyla yer değiştirebilmeli ve türetilmiş sınıf ile aynı davranışı sergilemelidir. Bu prensip aynı zamanda OCP’nin bir uzantısı olmakla birlikte, önceki prensipte kullandığımız örnek üzerinden ilerleyeceğiz. Refactor ettiğimiz kodu tekrar hatırlayalım.

public abstract class Shipment
{
    public int Id { get; set; }
    public string Name { get; set; }
    public double Weight { get; set; }
    public abstract decimal CalculateCost();
}

public class OverlandShipment : Shipment
{
    public override decimal CalculateCost()
    {
        return Weight * 1.5;
    }
}

public class OverseaShipment : Shipment
{
    public override decimal CalculateCost()
    {
        return Weight * 2.0;
    }
}

public class OverairShipment : Shipment
{
    public override decimal CalculateCost()
    {
        return Weight * 2.5;
    }
}

Mevcut kodumuza yeni bir özellik olarak özel günlerde ücretsiz gönderim de yapmak istiyoruz. Hemen özelliğimizi uygulamaya ekleyelim. Ancak burada bir sorunla karşı karşıyayız, ücretsiz gönderinin bir ücreti olmayacağı için implementasyon içerisinde ya hata fırlatacağız ya da default değer dönerek uygulamanın patlamasını engelleyeceğiz.

public class FreeShipment : Shipment
{
    public override decimal CalculateCost()
    {
        throw new NotImplementedException();
        // return 0;
    }
}

Bu yapı bize istediğimiz esnekliği sunmamaktadır, hemen Interface‘lerin gücüne inanarak kodumuzu biraz esnetelim.

public interface IShipment
{
    int Id { get; set; }
    string Name { get; set; }
    double Weight { get; set; }
}

public interface IShipmentCost
{
    decimal CalculateCost();
}

public abstract class Shipment : IShipment
{
    public int Id { get; set; }
    public string Name { get; set; }
    public double Weight { get; set; }
}

Şimdi de oluşturduğumuz arayüzleri (interface) uygulayalım, artık yalnızca ücrete tâbi olan kargolar ücret hesaplayabilecek.

public class OverlandShipment : Shipment, IShipmentCost
{
    public override decimal CalculateCost()
    {
        return Weight * 1.5;
    }
}

public class OverseaShipment : Shipment, IShipmentCost
{
    public override decimal CalculateCost()
    {
        return Weight * 2.0;
    }
}

public class OverairShipment : Shipment, IShipmentCost
{
    public override decimal CalculateCost()
    {
        return Weight * 2.5;
    }
}

public class FreeShipment : Shipment { }

You may also like...

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir