Building S.O.L.I.D - Liskov Substitution Principle

Named after it's creator, Barbara Liskov, the Liskov Substitution Principle states that if object B is a subtype of object A, then object B must be able to be substituted for object A without issue. A concrete example in C# is as follows:

/* 
    Base class from which concrete reports are created
*/
public class BaseReport {
    public string Title { get; set; }
    public string ReportBody{get; set; }
    public void OutputWebPage() { ... }
}

/* 
    A concrete report, detailing sales numbers
*/
public class SalesReport : BaseReport {
}

In the example above, we can observe a base type (BaseReport) and a sub-type (SalesReport). If our code follows the constraints of the Liskov Substitution Principle, anywhere we accept a BaseReport type must also be able to accept a SalesReport type without failure or loss of functionality. In this example, we can observe an OutputWebPage function in the base class. We can imagine, for the sake of explanation, that the report body is an HTML encoded string, and the OutputWebPage function takes the body and outputs it to a browser.

In future, there becomes a need for a new report containing product counts. This report comes from a different source, and the body is CSV encoded. If we were to create a new class, ProductReports, that inherits from BaseReport, the OutputWebPage function would attempt to output our CSV body, which is not a desired function. This violates the Liskov Substitution Principle as a ProductReport cannot be substituted for a BaseReport without an unintended change in functionality.

In this particular case, the web functions could have been refactored out into an HTML Outputtable class that only HTML compatible reports would implement, such as in the example below.

/* 
    Base class from which concrete reports are created, this time 
    without the incompatible function.
*/
public class BaseReport {
    public string Title { get; set; }
    public string ReportBody{get; set; }
}

/* 
    Derived class adding additional functionality to support the 
    HTML compatible reports. 
*/
public class HtmlCompatibleReport : BaseReport {
    public void OutputWebPage() { ... }
}

/* 
    A concrete report, detailing sales numbers with compatibility
    for outputting HTML. 
*/
public class SalesReport() : HtmlCompatibleReport {
}

/* 
    A concrete report, detailing product numbers, without compatibility 
    for outputting HTML. 
*/
public class ProductReport() : BaseReport {
}

The Liskov Substitution Principle assists us in writing code that:

  • Allows you assurance your code is workable & testable
  • Reduces errors in inheritance
  • Prevents unintended functionality
  • Promotes open/closed and interface segregation prinicipals

This article is my 3rd oldest. It is 426 words long, and it’s got 0 comments for now.