In order to say that you write clean code, you have to understand and you have to know how to apply what the acronym S.O.L.I.D hides. The programmer Robert C. Martin coined it with the purpose of remembering these five rules that every clean coder must disclose and use.

These principles are applied to object-oriented programming. The main goal is that our programs were more easily maintainable and understandable as well as allowing them to grow and evolve in a clean and intelligent way.

The five principles are:

  1. Single responsibility.
  2. Open-closed.
  3. Liskov substitution.
  4. Segregation interface.
  5. Dependency inversion.

If you would like to write good code, apply these principles. Do you lose the calm fighting your code? Are your programs full of wtf’s? Is your code hostile? You might need S.O.L.I.D.

In this post I write about the first principle.

Robert C. Martin defined SRP inspired by the concept of cohesion explained by Tom DeMarco. When I read about SRP, the most difficult part to understand was precisely “responsibility”.

What is a responsibility?.

A reason to change.

And what is a reason to change ?: One of the explanations that I like the most is the one that attends to the subject of that responsibility, that is to say: to whom does that responsibility respond?.

A class should only respond to one need.

If a class has several responsibilities, it will also be articulating several relationships of responsibility with several actors.

We can not understand responsibility as something concrete at the technical level, nor assimilate it to the work of a function or of a whole class. The responsibility is something wider, it is a semantic explanation about what the class does, not a definition of the tasks that it executes.

It is a mistake to think that this principle entails classes of a single function. A single responsibility can be defined by different functions, or by one, it would be stupid to establish a number. What it is important here is that our class responds to a single demand, to a single need. If my class only responds to one need, then there is only one reason why it can be modified: the change of the need itself.

Imagine a program that needs to use the API of a web service. We can think about building a class that makes a call to the service, treat the response and update a database with the information received.

class WebServiceConnector
{
    public function makeCall() {}

    public function parseResponse() {}

    public function connectDatabase() {}

    public function updateInfo() {}
}

By slightly analyzing this class, we see that there are indeed many reasons to change, that is, it is very likely that we will have to modify this class for different reasons.

Imagine that we use a mysql database but that when our system grows to three hundred million records, we decided to use a hypertable database. We will have to make changes related to databases in a class where, for example, we find calls to web services: two responsibilities that definitely have nothing in common.

If the web service we use changes its interface, we will make changes in the function that makes the calls, while our database, our data parsing and our updates in database do not need to be modified.

This class responds to the need to communicate with a web service, to analyze the XML documents received, to manage the communication with the database and also to update information in a database. It is a Frankenstein class that aims to please many actors: XML documents, web services or databases.

All these responsibilities, grouped into a single class are coupled. That is, they have a maximum level of coupling when in fact they are objectively different.

It is necessary to separate them:

class SoapClient {}

class Parser {}

class DatabaseDriver {}

class ApiConnector {}

Here I do not intend to be exhaustive, just reflect the need for SRP conceptually or philosophically. Of course, we must ask ourselves if these classes that we have created after a first try have a single responsibility, that is, if they have only one reason to change, and if not, analyze and modify them accordingly.

This principle is the basis of everything else. If the programmer does not put effort and hours in a good design, separating the responsibilities and avoiding the coupling, many other good practices and principles will be very compromised, like testing.