In this Object Oriented world, learning SOLID principles had become one of the most interesting things. Today’s topic is somewhat related to SOLID.
If you are new to SOLID, then SOLID is an object oriented principle which will guarantee that our software module won’t break with change requirement of a software.
Confused!!! Let’s make it easy. You can say that, “Software systems built by applying SOLID principles are easy to maintain and extend over time”.
I am a trainer. I do corporate training in many organizations. Recently, I did one training on Design pattern in Step by Step Schools. As a part of this training, I was discussing about SOLID patterns with my students. It went well with the following topics:
- What is SOLID?
- Understand S – Single Responsibility principle in SOLID
- Understand O – Open Closed principle in SOLID
Then I started L – Liskov substitution principle. I started with the definition of this principle.
It says “Subclasses should be substitutable for base classes”.
By hearing such definition, all my students were astonished.
They said, “This principle just doesn’t make sense at all.”
Actually, they were somewhat right. As per the object oriented programming rule, we can always write the following syntax:
Base b=new Derived ();
We can always have a function like below:
public void SomeFunction(Base b){....}
Which can be invoked as below:
SomeFunction(new Derived1());
or
SomeFunction(new Derived());
It means, “We can always use child class instance where base class is expected.”
But in reality, the above statement is not true. Let me give you a simple and realistic example.
Assume that we have a project with a database having table Customer
with three columns – Name
, Address
and Age
. In that case, we ultimately end up with the following class in our code.
public class Customer
{
public string Name{get;set;}
public string Address{get;set;}
public int Age{get;set;}
}
Now, let’s say we have one more table in Database called Employee
with columns – Name
, Address
and Age
.
Object oriented programming is full of useful principles that are worth following. One of the must follow principles is DRY – Don’t repeat yourself. It says “Once a particular code is written, don’t write it again, simply reuse it”. From freshers to those who are experienced, everybody respects this principle and tries their best to follow it.
By keeping DRY in mind and considering the existing Supplier
class, new Employee
class can be created as follows:
public class Employee:Customer{}
Technically, the above statement seems correct, but logically it’s incorrect. The above inheritance relationship states that “Every customer
is an Employee
”, which is not actually not true all the time.
We cannot actually use Customer
where it’s expecting to have employee
. This is where we say “we designed our system in a way where every derived class is not substitutable for the base class” or more simply, we say “we are violating the Liskov substitutional principle”.
What’s the Proper Design Then?
After hearing all this explanation, one of my students quickly asked, “Sir, then what is the correct design?”
Well, considering both DRY and LSP is followed, our classes can be designed as follows:
public class Person{
property string Name{get;set;}
propertystring Address{get;set;}
property int Age{get;set;}
}
public class Employee:Person{
}
public class Customer:Person{
}
Any code that expects person
will work with both Employee
and Customer
.
So that’s one part of my “Step of the step” story. Hope you enjoyed the post. Please post comments, share the link in your FB, twitter, linked in, etc. Stay tuned, I will be back soon with one more new story.
CodeProject