SOLID Design Principle

In this article I am going to talk about the SOLID principles which are a refinement of object-oriented design principles, consisting of five design principles formulated by Robert Martin.

“SOLID” where ‘S’ stands for Single Responsibility, ‘O’ for Open/Closed Principle, ‘L’ for Liskov’s Principle, ‘I’ for Interface Segregation and lastly ‘D’ for Dependency Inversion.

I will try to explain each of these principles briefly and I assume that any experienced developer and architects should be familiar with these terms.

Single Responsibility Principle

The principle states that classes should focus on one primary task. Every method and properties that you have in that class should be defined in accordance with the primary purpose of that class.

A class that does just one thing is better as compared to a class that does a lot of things and has a greater responsibility. For a class that has a greater responsibility it is inevitable that developer will make changes in the class thus making it difficult to maintain. Keeping our code simple is the effective way to meet maintainability in longer run.

Code representing SRP.
public class MobilePhone
{
public void Dial(String number);
public void Hangup();
public void SendText(Char c);
public Char ReceiveText();
}

Open Closed Principle
It states that “A class should be open for extension but closed for modification”. This can be achieved through abstraction of the class that can lead to changes overtime. You can use interfaces and code injection or generics to make your classes extendable.
Low coupling between interfacing modules is beneficial because it instructs the caller to work with an abstraction of its counterpart rather than with a concrete implementation.

public abstract class Shape
{
public abstract void Render();
}
class Square : Shape
{
private int _side;
// Override the abstract method to draw a square
// The concrete implementation is not important in this discussion
public override void Render()
}
public class Renderer
{
public void Draw(IList shapes)
{
foreach(Shape s in shapes)
s.Render();
}
}

In such a way the Renderer class is closed for modification but still open for extension because it can deal with any class that exposes the Shape abstraction—for example, any class that derives from Shape. Similarly, you can have a Renderer class that receives its working type as a generic argument.

Liskov ‘s Substitution Principle
It states that a Derived types must be completely substitutable for their base types. The principle explains that we should always extend base class functionality without replacing the functionality already in place.

Below is the violation of Liskov ‘s Substitution Principle.
// Violation of Likov's Substitution Principle
class Rectangle
{
protected int m_width;
protected int m_height;
public void setWidth(int width){
m_width = width;
}
public void setHeight(int height){
m_height = height;
}
public int getWidth(){
return m_width;
}
public int getHeight(){
return m_height;
}
public int getArea(){
return m_width * m_height;
}
}
class Square extends Rectangle
{
public void setWidth(int width){
m_width = width;
m_height = width;
}
public void setHeight(int height){
m_width = height;
m_height = height;
}
}
class LspTest
{
private static Rectangle getNewRectangle()
{
// it can be an object returned by some factory ...
return new Square();
}
public static void main (String args[])
{
Rectangle r = LspTest.getNewRectangle();

r.setWidth(5);
r.setHeight(10);
// user knows that r it’s a rectangle.
// It assumes that he’s able to set the width and height as for the base class
System.out.println(r.getArea());
// now he’s surprised to see that the area is 100 instead of 50.
}
}

Interface Segregation Principles
The principle states that client component should not be forced to implement interfaces that they do not need. It happens because interface is poorly designed. The Single Responsibility Principle should be true for interfaces as well.
Below I would like to reference an example taken from Programming Microsoft ASP.NET 4 to explain the principle.
If you’re asked to simply define a door, you would probably come up with an interface with just a couple of Lock and Unlock methods and perhaps a Boolean property IsDoorOpen. However, if you know that you also need to deal with timed doors that sound an alarm if left open for too long, you might arrange something like this.
public interface IDoor
{
void Lock();
void Unlock();
Boolean IsDoorOpen { get; }
Int32 OpenTimeout { get; set; }
event EventHandler DoorOpenForTooLong;
}

The apparent plus of this design is that it gives you just one interface that can serve up both scenarios: timed and regular doors. This is an apparent benefit because it forces you to have two extra members on any class that implements the interface: the event DoorOpenForTooLong and the timeout property. Why on earth should you have these members where they aren’t needed?
The natural solution is to use slimmer interfaces. The IDoor interface should be split into two smaller and much more specifc interfaces—say IDoor and ITimedDoor:

public interface IDoor
{
void Lock();
void Unlock();
Boolean IsDoorOpen { get; }
}
public interface ITimedDoor
{
Int32 OpenTimeout { get; set; }
event EventHandler DoorOpenForTooLong;
}
Now if you need to create RegularDoor and TimedDoor classes, you proceed as shown here:
public class RegularDoor : IDoor
{
...
}
public class TimedDoor : IDoor, ITimedDoor
{
...
}

Unlike classes, interfaces can be easily summed up; so there’s really no reason to have fat interfaces any more.

Dependency Inversion Principle
What if you have combined together different parts and formed a system. During development you faced some problem with the architecture and find a need to modify and change the building block of the system. Here comes the Dependency Inversion.
The principle says that every high-level module should always depend on abstractions of lower level modules. This is just a reformulation of the concept of interface-based programming.
Just imagine a method that reads bytes from a stream and writes them out to some buffer:

void Copy()
{
Byte byte;
while(byte = ReadFromStream())
WriteToBuffer(byte);
}

The pseudo code just shown depends on two lower level modules: the reader and writer. According to the principle, we should then abstract the dependencies to interfaces—say, IReader and IWriter.
Most of the time, We use this pattern when we have some legacy code that we need to make easier to extend that is hard to redesign in a different way—for example, in a way that uses dependency injection.
The resulting code looks like this:
void Copy(IReader reader, IWriter writer)
{
Byte byte;
while(byte = reader.Read())
writer.Write(byte);
}

In this way we can ensure maintainability by dividing our System into various layers which contributes to readability and, subsequently, to maintainability and testability.

Advertisements

2 thoughts on “SOLID Design Principle

  1. i m sorry to say that , this is just a copy paste of the book , not your own art of work, it would have been better if you had used some of your own brain

  2. Thanks for your comment , i believe that in order to learn design patterns you need to understand the concept behind it and it is always better to refer example from books.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s