So far we have gone through Single Responsibility Principle and Open Closed Principle , which cover two SOLID principles. In this post, we will go through L ie Liskov Substitution principle.
If for each object o1 if 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.
Barbara Liskov
LSP originated as a way to guide use of Inheritence.
Let’s look at an example where an implementation of inheritence violates LSP.
Consider the Square/Rectangle problem. Here Square is not a proper substitute of Rectangle as height and width of rectangle are different from that of Square. For Rectangle, user needs to set width and height, but for Square, one has to set only side. And as Square is subtype of rectangle, it inherits both height and width of Rectangle. And if user wants to calculate area of square, he could easily set width and height as different resulting in wrong area/perimeter of square. And so developer would need to add special implementation to make sure to check if given instance of Rectangle is a Square.
LSP and Architecture
Let’s look at the example given in the book of taxi aggregator service that aggregates many taxi dispatch service. Customer uses this service to find the best taxi for them regardless of the taxi company. Once the customer selects the driver, the service dispatches the chosen taxi.
Let’s say the URI the service uses is part of the information contained within driver database. Suppose customer chooses Bob’s taxi, then our service dispatches the request to Bob using the URI stored for him in the data base
example – assuming dispatch uri for BOB is 24hrTaxi.com/driver/Bob, so the PUT request to Bob will be like 24hrTaxi.com/driver/Bob/pickupAddress/1234 happy st./pickupTime/1430/destination/LAX
All taxi services will need to conform to this interface to be able to interface with the aggregator service. Let’s say TaxiAnyTime.com, changes he interface and uses dest instead of destination. This is violating LSP, as all services are not conforming to one interface. And so we will need special logic in our dispatcher service to handle different parameters for this taxi service.
So LSP should be followed at architecture level as a simple violation of LSP can cause additional code/mechanisms to be put in the architecture as fallbacks.
Thanks for stopping by! I hope this gives a good preview into LSP. Eager to hear your thoughts and chat, please leave comments below and we can discuss.