Single Responsibility Principle

Click to share! ⬇️

single responsibility principle

The Single Responsibility Principle focuses on the concept of keeping a function, method, or class, focused on a narrow behavior that it does well. When we think about a given API, we can say it is a good API if it does one thing and never changes. Now when we say API, we really are referring to any function, method, or class however all of this holds true for the more traditional thinking of what an application programming interface is. Examples of popular APIs include the Facebook API, Twitter API, and Google Plus API. The Single Responsibility Principle states that a good application programming interface never changes. The SRP also states that an API does what it says it is going to do, or in other words, is adheres to it’s contract.

Characteristics of the Single Responsibility Principle

We’ve already started talking about what encompasses a good API. Let’s have a look at them in list form now.

  • A Good API Does One Thing
  • A Good API Never Changes
  • A Good API Behaves Like Its Contract
  • A Good API Has A Narrow Responsibility

It seems like there are a million ways to word this, so here is another one. A class should have one, and only one reason to change. Say what? That doesn’t sound all that helpful, what does it mean to have one reason to change. (Damn you nerdy programming geeks). The way I understood this is to think of editing code. When you have a program, and you want to change it’s behavior, what do you do? You scour through the source, find where the behavior you want to change is, and hack away. In object oriented terms, that could mean a situation like the following. Imagine you build custom cars and you deliver this model to a customer.

<?php

class Car
{
    public function speed()
    {
        return 'go fast';
    }
    
    public function steer()
    {
        return 'turn left';
    }
}

$car = new Car;

$car->speed(); // go fast
$car->steer(); // turn left

This code breaks the Single Responsibility Principle. We know this because, what if your customer says that he only wants his car to go slow and turn right. This is a problem since you just delivered a car that can only go fast and turn left. So you have to go back to the drawing board and edit your Car class in Two places. This is the breakage of the SRP, one class with two reasons to change. Here is a different way to write the same code using multiple classes. This way, we extract specific behavior into its own class. We’ll have a Car class which of course is our car. We’ll also create an Accelerator class and a Steering class. Even before we write any code, it is pretty clear what the responsibility of each class is. This way, if the customer says that he wants to go slow instead of fast, we only change one class. Let’s see.

<?php

class Car
{
    protected $speed;
    
    public function __construct(Accelerator $speed, Steering $steer)
    {
        $this->speed = $speed;
        $this->steer = $steer;
    }
    
    public function speed()
    {
        echo $this->speed->go();
    }
    
    public function steer()
    {
        echo $this->steer->turn();
    }
}

class Accelerator
{
    public function go()
    {
        return 'going fast';
    }
}

class Steering
{
    public function turn()
    {
        return 'turn left';
    }
}

$car = new Car(new Accelerator, new Steering);

$car->speed(); // going fast
$car->steer(); // turn left

So in this first iteration, we still have the same behavior. At this point however, each class has only one reason to change. If we want to change the speed, we change the Accelerator class only. If we want to change the steering, we change the Steering class only. This way, we use a suite of classes to build up an object (Hi Dependency Injection!). Anytime someone comes along after the fact and asks for a change, we simply find the one class that has that one responsibility, and we change it. Let’s change the Accelerator class.

class Accelerator
{
    public function go()
    {
        return 'going slow';
    }
}

This way, we made only one change in one class. We don’t even have to touch the Car class. It is oblivious to these things. All it knows is that it will be able to call a speed() method, and it will do what it is supposed to. Running our client code, we find the speed has in fact been changed.

$car = new Car(new Accelerator, new Steering);

$car->speed(); // going slow
$car->steer(); // turn left

We now need to fix the customers request that the Car turn right instead of left. This is another reason to change, and as such, we should not have to modify the same class. With our refactored code, we don’t have to. We simply find the class that is responsible for steering and change it once.

class Steering
{
    public function turn()
    {
        return 'turn right';
    }
}

With this one change to the responsible class, we can again run our client code, and all is fixed.

$car = new Car(new Accelerator, new Steering);

$car->speed(); // going slow
$car->steer(); // turn right

Hiding The Ugliness

Part of what this approach also does is to hide the ugliness. When we all first started coding, we would hack together something in the best way we could to make a desired result happen. After some amount of time, we may have even reached our goal and got our program to work. In fact, we may have even sat back, taken a look at the monstrosity of code in place and said, “What a beautiful piece of engineering” 🙂

In fact, beauty is in the eye of the beholder, and you know what, that pile of spaghetti just might be beautiful damn it! The thing is, much of that code is still critical and valuable. All we are doing is hiding it away in classes we can inject into our client code. We’ve come to expect the ability to make all kinds of logic happen with one or two simple lines of code. This is the higher level code. The reality is that it still depends on the lower level code, which is not nearly as pretty. The low level code is busy getting its hands dirty doing all the heavy lifting for you. It almost feels like a corporation where the higher ups just give orders, but don’t really do anything.

The Single Responsibility Principle Summary

The Single Responsibility Principle is really easy. Do one thing, and do it well. Your manager will thank you.

Click to share! ⬇️