Understanding The SOLID Principles….

Sandini Pitawala
6 min readFeb 26, 2021

SOLID Principles is a coding standard that should provide a simple definition for all developers to properly build software to prevent bad design.

It was promoted by Robert C Martin and it is used throughout the continuum of object-oriented design. It makes the code more extensible, logical, and easier to read when implemented correctly.

How do we recognize rot as a potential code? Possibly, these signs suggest code rot to come:

  • Rigidity — small changes causes the entire system to rebuild.
  • Fragility — changes to one module causes other unrelated modules to misbehave. Imagine a car system in which changing the radio station affects windows.
  • Immobility — a module’s internal components cannot be extracted and reused in new environments.

The SOLID principles of Object Oriented Design include these five principles:

Five Object Oriented Principles that should be followed when designing software
Five Object-Oriented Principles that should be followed when designing software

01. Single Responsibility Principle(SRP)

“A class should have only one reason to change, and a class should have only one responsibility.”

Let’s look at this specific class. This class represent a simple book.

In here, we store name, author and text associated with an instance of a Book. Let’s add some methods for querying the text now,

Imagine a scenario where we need to get output of the book details and add a print details methods in to a similar class. Isn’t it violate the principle of having single responsibility? indeed it violate. So what is the most ideal approach to get the output.

We should implement a different class that is concerned uniquely with printing details as demonstrated beneath.

02. Open-Closed Principle(OCP)

“Objects or entities should be open for extension, but closed for modification”

Let’s further explore the idea with an example of a fast code. Assume that you have implement a guitar class as shown below.

It works well and it’s loved by users. But you may think this needs to be updated after a few months to be even more appealing by adding a new pattern. It can cause errors that we didn’t expect if you just apply the new pattern to the same application. So the best method is to use our principle of open-closed and simply extend the guitar class.

We can then be confident that nothing is going to happen to our current class.

03. Liskov Substitution Principle(LSP)

“Every subclass/derived class should be able to substitute their parent/base class”

The most complex of the 5 principles is Liskov substitution. Simply put, if class A is a subtype of class B, then without disrupting our program’s actions, we should be able to substitute B with A.

So that is simply, Derived classes must be substitutable to their base classes.

Above, we define a simple Car interface with a couple of methods that all cars should be able to fulfill — turning on the engine, and accelerating forward.

Now let’s implement our interface for a motorcar and provide some code for the methods:

We are now having electrical vehicles also. We should perceive what will happen while implementing that.

We are inherently altering the behavior of our software by throwing a car without an engine into the mix. This violates the Liskov Substitution principle and is a little more difficult to fix than our previous 2 principles.

One potential solution would be to rework our model into interfaces that take the engine-less condition of our car into account.

04. Interface Segregation Principle(ISP)

“Clients should not be forced to implement methods they do not use”

Let’s begin with an interface that outlines our roles as a bear keeper,

As we know, petting bears is even more risky. We have no option here, according to the code, instead of integrating all three methods in the same implementation.

Let’s fix this by splitting our large interface into 3 separate ones,

We can now introduce strategies that matter to us without any hesitation, thanks to interface segregation.

And then, we should leave the risky stuff to the crazy people,

05. Dependency Inversion Principle(DIP)

“Higher level modules should not depend on lower level modules, but they should depend on abstractions.

Abstractions should not depend on details. Details should depend upon abstraction.”

Let’s understand the Dependency Inversion principle through an example,

It is worth, if we have not keyboard and mouse to work on Windows. To solve this problem, we create a constructor of the class and add the instances of the keyboard and monitor. After adding the instances, the class looks like the following,

Now we can work on the Windows machine with the help of a keyboard and mouse. But we still face the problem. Because we have tightly coupled the three classes together by using the new keyword. It is hard o test the class windows machine.

To make the code loosely coupled, we decouple the Windows98Machine from the keyboard by using the Keyboard interface and this keyword.

In the above code, we have used the dependency injection to add the keyboard dependency in the Windows98Machine class. Therefore, we have decoupled the classes.

Why should we use SOLID principles?

  • It reduces the dependencies so that a block of code can be changed without affecting the other code blocks.
  • The principles intended to make design easier, understandable.
  • By using the principles, the system is maintainable, testable, scalable, and reusable.
  • It avoids the bad design of the software.

“Next time when you design software, keeps these five principles in mind. By applying these principles, the code will be much more clear, testable, and expendable.”

--

--