Take advantage of Liskov Substitution Principle to reduce coupling and facilitate code reusability in your application The term SOLID is a popular acronym used to refer to a set of five principles of software architecture. These include: SRP (Single Responsibility), Open/Close, Liskov’s Substitution, Interface Segregation, and Dependency Inversion. LSP (Liskov Substitution Principle) is a fundamental principle of OOP and states that derived classes should be able to extend their base classes without changing their behavior. In other words, derived classes should be replaceable for their base types, i.e., a reference to a base class should be replaceable with a derived class without affecting the behavior. The Liskov Substitution Principle represents a strong behavioral subtyping and was introduced by Barbara Liskov in the year 1987. According to Barbara Liskov, “What is wanted here is something like the following substitution property: If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T, the behavior of P is unchanged when o1 is substituted for o2 then S is a subtype of T.” A classic example of violation of the Liskov Substitution Principle is the Rectangle – Square problem. The Square class extends the Rectangle class and assumes that the width and height are equal. Consider the following class. The Rectangle class contains two data members — width and height. There are also three properties — Height, Width, and Area. While the first two properties set the height and the width of the rectangle, the Area property has a getter that returns the area of the rectangle. class Rectangle { protected int width; protected int height; public virtual int Width { get { return width; } set { width = value; } } public virtual int Height { get { return height; } set { height = value; } } public int Area { get { return height * width; } } } A Square is a type of rectangle all of whose sides are of equal size, i.e., the width and height of a Square is the same. class Square : Rectangle { public override int Width { get { return width; } set { width = value; height = value; } } public override int Height { get { return width; } set { width = value; height = value; } } } Consider another class called ObjectFactory. class ObjectFactory { public static Rectangle GetRectangleInstance() { return new Square(); } } Note that the setters for the Width and Height properties in the Square class have been overridden and modified to ensure that the height and width are the same. Let’s now create an instance of the Rectangle class using and set its height and width properties. Rectangle s = ObjectFactory.GetRectangleInstance(); s.Height = 9; s.Width = 8; Console.WriteLine(s.Area); The above code snippet when executed would display the value 64 in the console. The expected value is 72 since the width and height mentioned is 9 and 8 respectively. This is a violation of the Liskov Substitution Principle. This is because the Square class that has extended the Rectangle class has modified the behavior. To ensure that the Liskov Substitution Principle is not violated, the Square class can extend the Rectangle class but shouldn’t modify the behavior. The behavior has been changed by modifying the setters for both the properties Width and Height. The values of height and width are same if it is a Square — they shouldn’t be the same if it is a Rectangle. How do we fix this, i.e., ensure that this principle is not violated? Well, you can have a new class introduced called Quadrilateral and ensure that both the Rectangle and the Square classes extend the Quadrilateral class. public class Quadrilateral { public virtual int Height { get; set; } public virtual int Width { get; set; } public int Area { get { return Height * Width; } } } Now, both the Rectangle and Square classes should extend the Quadrilateral class and set the values of the Width and Height properties appropriately. In essence, the derived classes should have the necessary functionality to set values to these properties based on the type of the Quadrilateral instance you need to calculate area for. Note that both the Height and Width properties have been marked as virtual in the Quadrilateral class meaning that these properties should be overridden by the classes that derive the Quadrilateral class. Liskov Substitution Principle is an extension of the Open Close Principle and is violated when you have written code that throws “not implemented exceptions” or you hide methods in a derived class that have been marked as virtual in the base class. If your code adheres to the Liskov Substitution Principle you have many benefits. These include: code re-usability, reduced coupling, and easier maintenance. Related content feature 14 great preprocessors for developers who love to code Sometimes it seems like the rules of programming are designed to make coding a chore. Here are 14 ways preprocessors can help make software development fun again. By Peter Wayner Nov 18, 2024 10 mins Development Tools Software Development feature Designing the APIs that accidentally power businesses Well-designed APIs, even those often-neglected internal APIs, make developers more productive and businesses more agile. By Jean Yang Nov 18, 2024 6 mins APIs Software Development news Spin 3.0 supports polyglot development using Wasm components Fermyon’s open source framework for building server-side WebAssembly apps allows developers to compose apps from components created with different languages. By Paul Krill Nov 18, 2024 2 mins Microservices Serverless Computing Development Libraries and Frameworks news Go language evolving for future hardware, AI workloads The Go team is working to adapt Go to large multicore systems, the latest hardware instructions, and the needs of developers of large-scale AI systems. By Paul Krill Nov 15, 2024 3 mins Google Go Generative AI Programming Languages Resources Videos