S.O.L.I.D Design Principles

Object Oriented Programming (OOP) is today the most commonly used programming style used by the majority of Software Designers and Developers. We are all familiar with various OOPs concepts like classes, objects, inheritance etc... Are our application designed properly and scalable? Most of us have seen and worked on spaghetti code that are tangled with eachother. The design goes for a toss when the customer comes up with a change in the system and that change is a nightmare for the developers. Many such road-blocks vanishes if the application design follows the S.O.L.I.D Design Principles.

Bob Martin's S.O.L.I.D Principle is a collection of best-practices to design object oriented systems. These principles help to design and develop loosely coupled, scalable and highly maintainable OO applications. SOLID is an acronym for the following principles:

Single Responsibility Principle (SRP)

The 'Single Responsibility Principle' states "THERE SHOULD NEVER BE MORE THAN ONE REASON FOR A CLASS TO CHANGE." Changes in a system are inevitable. A change might be a new feature request, a bug fix, or refactoring. If a particular class handles multiple responsibilities, then implementing a change would be more difficult than implementing the same on a class that handles single and specific responsibility. This principle urges that different responsibilities should be handled by separate class.

Open-Closed Principle (OCP)

The Open-Closed Principle states that "SOFTWARE ENTITIES SHOULD BE OPEN FOR EXTENSION , BUT CLOSED FOR MODIFICATION." When you are implementing a requirement change, the system must be designed in such a way that you add new code and 'do not touch' the existing code that already works. Ouch!!! That's sounds impossible, isn't it? It is impossible to design a system that is 100% closed for modification. We should aim for strategic closures.

Liskov Substitution Principle (LSP)

The Liskov Substitution Principle states "FUNCTIONS THAT USE POINTERS OR REFERENCES TO BASE CLASSES MUST BE ABLE TO USE OBJECTS OF DERIVED CLASSES WITHOUT KNOWING IT." Inheritance is a very powerful concept that helps in code re-usability and maintainability. If the design confirms with this principle, replacing the existing derived class with another derived class wouldn't require the methods that uses the base class' reference to change. LSP and OCP goes hand in hand. If a design violates LSP, then when we use a new derived class (open for extension), the methods that refers the base class will also have to be modified (but not closed for modification).

Interface Segregation Principle (ISP)

The Interface Segregation Principle states "CLIENTS SHOULD NOT BE FORCED TO DEPEND UPON INTERFACES THAT THEY DO NOT USE." This principle deals with interface pollution. We might find interfaces that are not cohesive. It is possible to segregate such interfaces by grouping and separating member functions that are used by different clients. If the design adheres to this principle, and the interface has to be changed, the number of clients that will be affected will be minimal. Many more clients would have been affected in case the interface was polluted.

Dependency Inversion Principle (DIP)

Dependency Inversion Principle includes two parts:

  1. High level modules should not depend upon low level modules. Both should depend upon abstractions.
  2. Abstractions should not depend upon details. Details should depend upon abstractions.

This principle deals with how to avoid a design that is rigid (Difficult to make changes), fragile (Any changes would break the system) and immobile (Difficult to use separate and reuse modules). This principle drives the design of higher-level modules to be independent of the underlying lower-level modules through abstractions.