S.O.L.I.D Programming Principles explained
Tags: Solid, Principles, Java, Design Patterns, Programming

S — Single-Responsibility Principle SRP

The single responsibility principle states that a class should have one and only one responsibility / function. For example:

Now lets say we wanted to draw square and circle. In order to implement the draw functionality, we have two options:

Add a draw method to each class and write the code for drawing. This would lead Square and Circle classes to also have the responsibility of drawing the given shape and this is against SRP. Each draw method will have its own method implementation based on the class.

2. Create another class named ShapeDrawer which will draw any given input Shape. This option will make the code abide by the SRP principle.

O — Open-closed Principle OCP

Objects or entities should be open for extension and closed to modification.

This principle states that a class, once written should not be open to modification incase new functionality needs to be added to it; rather, in order to add new functionality, the class should be made in such a way that it is easily extendible.

Consider the above code snippet again:

As can be seen, in case a new shape is added like a triangle, the ShapeDrawer class will need to be modified by adding another method drawTriangle and this goes against the Open-closed Principle.

Below code snippet shows how we can make the ShapeDrawer class to become easily extendible: by modifying the above Square and Circle example by creating a Shape interface and then implementing the interface in both Square and Circle classes, as below:

Please note above how the ShapeDrawer class implementation has changed.

L — Liskov Substitution Principle LSP

Liskov Substitution Principle states that a subtype should be substitutable for a type without altering the correctness of the program.

Please consider the below quote from Uncle Bob (Robert C. Martin) explaining what the Liskov Substitution Principle means:

Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it.

Any subclassing of a superclass or implementation of an abstraction (interface) must adhere to the requirements and conventions of the interface to the abstraction.

For example:

I — Interface Segregation Principle ISP

Interface Segregation Principle states that a consumer method, interface implementation or a subclass should not be forced to depend on methods it does not use.

Following is the modified example for ISP adherence.

D — Dependency Inversion Principle DIP

The Dependency Inversion Principle states as follows:

High-level modules should not depend on low-level modules. Both should depend on Abstractions. Abstractions should not depend on details. Details should depend on abstractions.

Suppose we have a PasswordReminder class which accesses a MySQLConnection object to connect to the database and return the password.

As can be seen, the PasswordReminder class depends directly on MySQLConnection object. This is troublesome and violates the DIP because what if tomorrow we decide to migrate our database to Teradata? We will have to rewrite the class again, which would violate the Open-Close Principle.

The PasswordReminder class should be database agnostic and shouldn’t care about a specific database engine. In order to make PasswordReminder database agnostic, we create an interface:

Lets say we want to add a TeradataConnection object, now we have to only create a TeradataConnection class as use it in the PasswordReminder class.

Conclusion

S.O.L.I.D principles are very important to write maintainable, reusable and easily extendible code bases. Further, these principles are also inter-related. Like if we apply the Open-Closed Principle & Liskov Substitution Principle, we would automatically be ensuring Dependency Inversion Principle. It all starts from the first principle of Single-Responsibility and boils down to how we separate program functionality in our code without creating direct dependencies.