SOLID represents a series og guidelines that developers can use to simplify their code, of course under that circumstance that it’s done well. Learning these concepts has clearly made me a better developer! This post will take a look at what the SOLID principles are about and some very simple ways we can practice them while coding. In this example I will be writing code in PHP.

The Solid Principles in short

1. Single Responsibility

This is one of the most popular thing about the SOLID design principles – the single responsibility. This principle dictates that a class should have ONLY one reason to change.

2. Open-Close Principle

This is one of the principles that i often skipped in the past. I think that a lot of developers does this too, and i totally get them, but don’t do it. This techniques dictates that a class should be open to extension and closed for modification, which will help you in your design later on.

3. Liskov Substitution

By Barbara Liskov – this principle states that any implementation of an abstraction (interface) should be substitutable in any place that the abstraction is accepted. In other words – a derived class can be substituted at places where a base class is used.

4. Interface Segregation

The Interface Segregation Principle states that a client should never be forced to implement an interface that it doesn’t use. So.. please stop making fat interfaces..

5. Dependency Inversion

There’s a common misunderstanding that “dependency inversion” is simply another way to say “dependency injection.” However, the two are not the same. Not only high level Classes but low level Classes also depend on the abstractions in order to decouple the code.

In the beginning i must say that i was very confused about some of the many explanations on the web. A lot of the definitions you will find are not the exact definitions, because they are far mor perplexing. I have been taking courses on Laracasts and the teacher at Laracasts Jeffrey Way once tweeted the following, which i find funny.

Dependency Inversion, Inversion of Control, Dependency Injection, IoC Container. It’s no wonder why people get so confused. So much jargon!

Jeffrey Way – Laracasts

Below i have written a little about the five principles – only to convert the jargon into some understandable for beginners.

Single Responsibility

As mentioned earlier, this is the easiest principle to follow and practice in projects. Here is an example – Let’s for instance say that i want to make an API in my back-end, which of course receives a lot of requests. Every time a request is made, we need to authenticate and validate the received data, query the new data to our database, format a response and then send back the response to the client.

If this sounds trivial – GREAT! To make use of a Single Responsibility, we only need to do one thing – make sure all these tasks are made in separate classes. If you create all these tasks (functions) in one class, you fail this principle.

Imagine you are assigned a problem solving task for a project. First you have to figure out what line of code is the source to the issue or bug you got in the application. If you got all functions in one class, you will have to traverse hundreds or maybe thousands of lines.

Open-Close Principle

This principle ensures that our code is open for extension but closed for modification. It reduces the chance of developers editing the same piece of code again and again. It is a very useful thing when the requirements for the application may keep getting added in one or more sprints / iterations.

Again here is an example with authentication. Image you got an application with an authentication module which required the users to only enter username and password. You write the necessary code for the login module and then perform the login for the specific user.

What if we wan’t users to be able to login with Google or Facebook? Thee user is already logged in and they now bring a custom access token from one of the platforms, with which they can log in. This puts you into a situation, where you have to add new checks on what kind of user you are handling and what they are based on. Due to this, we have to proceed on adding more logic for our login module.

The problem here is that we are writing all logic in one LoginModule class with let’s say a function called login. If all logic for logging into the application is written into one method, i am sure that nobody want’s to touch that code. It is very crucial functionality for an application and breaking that, breaks the whole site.

Instead you should should make a interface for your login and separate the login classes for normal login and third party login begind that. This will flip the dependencies for the login functionality in the application. When a new developer want’s to write a new login module for another platform, they only have to implement the login interface and they are flying.

To sum up this open-close principle of SOLID we can tell that, if code can be extended, then write it in such a way from the beginning that it’s not necessary to modify it for extra requirements.

Liskov Substitution

The Liskov Substituion principle states that any implementation of an abstraction (interface) should be substitutable in any place the abstraction is accepted. So this tells us that we not only have a contract of input for the interfaces in the application, but also takes care of the returned aoutput of the different classes implementing our interface. They HAVE to of the same type.

Imagine two classes implementing an interface that returns different types of values. This will force the developer to check what kind of value is returned for the specific method in the class. If we do follow Liskovs principle, it won’t be necessary to check if the values are of the type an array, collection, list etc.

Interface Segregation

Interface Segregation tells the developer not to write code that forces a client to implement an interface that it doesn’t make use of. This principle will make sure that classes are sharing only the required knowledge nad not bloating themselves.

Hav you ever heard about “Fat Interface” – neither had i, until now 🙂 In short a fat interface is an interface that becomes fat when it’s handling too many contracts. If you got a fat interface, you a violating the Single Responsibility Principle in SOLID. Why? Because it is handling more than one responsibility at the time.

If you make your interfaces thin you are in most cases open to extension but closed for modification, hence adhering to the Open-Close Principle in SOLID. Yeah – SOLID principles are interlinked to each other. Fast sum up.. A class should not have extra knowledge that is not required.

Dependency Inversion

High level modules should never depend on Low level modules, end of story. Instead High level modules can depend upon an abstraction and the low level module then depends on that same abstraction. Not the simplest statement that i have come across.

A simple example

Let us suppose that we got a PasswordReminder class which can be a high level module (a high level module is a module that doesn’t focus on detailed implementation). This PasswordReminder class required a dbConnection property. To accomplish this we can simply inject a MySQLConnection class in the constructor of the class (also called dependecy injection) and allow acces on the dbConnection property.

Can you see the problem here? Doing what i descriped above will make the high level module depend on a low level module. We need to ask our self “Do PasswordReminder need the knowledge about the connection type?”. No way on earth it need that knowledge – solution.. Lets make an interface to handle that.

interface ConnectionInterface
{
     public function connect();
}

class DBConnection implements ConnectionInterface
{
     public function connect()
     {
          // Add some logic for your MySQL connection here
     }
}

class PasswordReminder
{
     private $dbConnection;

     // Make the Dependecy Injection using ConnectionInterface
     // remember this is different from Dependency Inversion

     function _construct(ConnectionInterface $dbConnection)
     {
          $this->dbConnection = $dbConnection;
     }
}

See what i did here. First i create an abstraction, the ConnectionInterface and then injected it into the PasswordReminder class’ constructor in order to access the dbConnection property.

What exactly happened is that the MySQLConnection class becomes DBConnection and implements the ConnectionInterface to override methods like connect. What i did was decoupling PasswordReminder from the MySQLConnection class using an abstraction. At the same time i inverted the dependecy on MySQLConnection using an abstraction ConnectionInterface.

From my earlier experience i can see that i made use of some techniques already but really learned some new stuff regarding Dependency Inversion. The principles is something every programmer should keep in mind while coding, this doesn’t mean that the developer has to take them into use every time. If they just keep in mind that we have to know what we are doing in a class.

A question i always ask myself after learning these principles is: “Does this class need the knowledge that i am passing to it?”. Often to answer that question correctly i make an interface and put necessary abstractions in place, which will make my code adhere to the SOLID principles.

Leave a Reply