SINGLE RESPONSIBILTY (because you can does not mean you should)

Every software developer must have stumbled upon the term SINGLE RESPONSIBILITY. I mean after the DRY principle it is the most commonly talked about principle in software design and development. The term itself is self-explanatory but going by Wikipedia definition: SR is a computer-programming principle that states that every module or class should have responsibility over a single part of the functionality provided by the software, and that responsibility should be entirely encapsulated by the class, module or function.

Although the concept is easy to understand, but it is one of the trickiest principles to implement. I had my own share of misinterpreting this principle too, what does SR really mean? Does it mean my class should have just one method? Is CRUD operation a breach of SR? those are the questions that lurked over my head until I finally understood what SR is really about.

According to Martin C.R, he defined responsibility as the reason to change, what does he mean by that? This is where our codes will do a better explanation than just writing.

My codes will be written in PHP for this article, but it is not really about the codes it is about the principle which can be applied to any object-oriented programming language.

Okay, let us write a script that will collect the users in our database, and send each user “STAY SAFE” message since that is the hot potato in town at the moment.

<?php

class User

{

//database parameters
    const SERVERNAME = "localhost";
    const DBNAME = "test";
    const USERNAME = "root";
    const PASSWORD = "";

//define message to be sent in the email
    public $message = "Stay safe, please CoViD-19 IS real";

    public function getUsers(){
        //query to get all users
        $sql = "SELECT EMAIL FROM USERS";
        $result = $this->dbConnection()->query($sql);
        $users = $result->fetch_assoc();

        return $users;
    }


    public function dbConnection() {
       //connection logic
       $con = new myqsli(SERVERNAME, USERNAME, PASSWORD, DBNAME);
        if ($con->connect_error) {
            die('connection failed' . $con->connect_error);
        }

        return $con;
    }


    public function sendNotificationToUser(array $users){

       //loop through all users and send covid 19 email
        foreach ($users as $key => $user) {
            mail($user['email'], "STAY SAFE", $this->message);
        }
    }
}

Viola our script works, but it has thrown SR out of the window, so what are the implications of the ditching the famous SR principle?

First let us talk about how our working codes have failed the SR principle. Take a look at the codes again and guess how many responsibilities lie on the shoulder of our user class? You are right, 3 responsibilities;

1 Responsible for connecting to the database

2 Responsible for the business logic

  1. Responsible for sending out notification

Well those are some non-cohesive tasks for our user class, but you might want to justify your responsibilities action by saying what about CRUD operations in most frameworks where by you can create a resource controller that update, create, delete and read. Professional coders do that too, does it mean that they are also violating SR too. Big question, this is where the real meaning of SR comes in. Your Class should have just only one reason to change. So, what are the changes that can bring about modification in our class.

1 Let assume we want to move our database from MySQL to a different database such as mongo DB, that means we have to change our database connection logic.

2 We want to send notification to users that are only active, we have to change the business logic which is our query statement.

3 We no longer want to send notification through email, but via SMS messages, hence another reason for our class to change.

Woosh!!!!, we have seen for ourselves that the user class is doing too much and it could be a disaster waiting to happen when we want to make some changes to our codes.

So how do we solve this problem. We need to divide our class into three classes, so each class can focus on one responsibility, so let us do some refactoring, shall we?

<?php
class DBConnection{

//database parameters
const SERVERNAME = "localhost";
const DBNAME = "test";
const USERNAME = "root";
const PASSWORD = "";        



public function connect(){
   $con = new myqsli(SERVERNAME,USERNAME,PASSWORD,DBNAME);
    if ($con->connect_error) {
            die('connection failed' . $con->connect_error);
   }
   return $con;

 }
}

class Notification{
//define message to be sent in the email
public $message = "Stay safe, please CoViD-19 IS real";

public function sendNotification(array $users){
    //loop through all users and send covid 19 email
            foreach ($users as $key => $user) {
                mail($user['email'], STAY SAFE, $this->message);
            }
     return "covid-19 email has been sent";

}

}



class User{

   public function getUsers(DBConnection $con){
     //query to get all users
            $sql = "SELECT EMAIL FROM USERS";
            $result = $con->connect()->query($sql);
            $users = $result->fetch_assoc();

            return $users;
   }
}

With this we have successfully passed the responsibility to three different classes. Whenever we want to make changes our database, we can go to the database class and whenever we want to change our notification from mail to SMS, we can do that in our notification class. Going forward updating our codes or changing the logic won’t be an uphill task unlike updating the codes we wrote initially because we have adhered to the SR principle.

Note: The code was written to explain the SR principle, it still leaves a lot to be desired in terms of code quality.

No Comments Yet