Thursday, August 20, 2015

Single Reponsibility Principle in .NET

Recently, I was reading about SOLID principles and how they can help us write better code. SOLID principles help make our code more supple so it can easily change with change in requirements. It helps us in writing our code more towards object oriented design rather than procedural code. It also helps make our code less rigid as well as less fragile and easy to reuse. I will be discussing all these principles one by one continuing in subsequent posts.

In today's blog post, I will be discussing one of the SOLID principles which can help in better design and implementation of the system, i.e. Single Responsibility Principle (SRP).

Single Responsibility Principle (SRP)

According to this principle, a class should have only one reason to change. If the class is doing too much then there might be multiple reasons for it's changes.
In other words, each class should do only one thing and do it well. It helps in separations of concerns. Let's look at an example to understand this:

For example you have a method like this:

public class Employee

{

      /*

        other properties and methods 

      */

      public ActionResult Details(int? id)

        {

            Log.Debug("Reading Employee " + employeeId);

            if (id == null)

            {

             return new 
             HttpStatusCodeResult(HttpStatusCode.BadRequest);

            }

            Employee employee = db.Employees.Find(id);

            if (employee == null)

            {

                Log.Debug("Employee not Found" + employeeId);

                return HttpNotFound();

            }

            Log.Debug("Returning Employee " + employeeId);

            return View(employee);

        }

      //....

}

By looking at this code, you can clearly see that this method is doing more than intended. For retrieving the employee, it's doing all the logging as well. If in future, we need to change logging mechanism, then we will have to revisit the code, as well as if we change the way employees are retrieved, then also we need to change this code. So there are multiple reasons for this class to change.

So, one way to solve this problem is to have a separate logger like this:


public class EmployeeLogger

    {

        public void Reading(int id)

        {

            Log.Debug("Retrieving Employee " + id);

        }

        public void Returning(int id)

        {

            Log.Debug("Returning Employee " + id);

        }

        public void NotFound(int id)

        {

            Log.Debug("No Employee found " + id);

        }

    }


Now, the Employee class might look like:


public class Employee

{

      private EmployeeLogger _logger = new EmployeeLogger(); 

      /*

        other properties and methods 

      */

public ActionResult Details(int? id)

        {

            _logger.Reading(employeeId);

            if (id == null)

            {

             return new 
             HttpStatusCodeResult(HttpStatusCode.BadRequest);

            }

            Employee employee = db.Employees.Find(id);

            if (employee == null)

            {

                _logger.NotFound(employeeId);

                return HttpNotFound();

            }

            _logger.Returning(employeeId);

            return View(employee);

        }

//... 

}

So now the logging responsibility belongs to EmployeeLogger class. If in future, we need to change the way employee logging is supposed to be done, we can change only the EmployeeLogger and don't need to make changes to the Employee Details method.
Currently, you might think that we have written a lot more code for a very small benefit. But, as the code base grows larger and the requirements change, you will see the benefit of it in the long run. Also, this provides us as a good base for better design and other SOLID principles to apply upon, as we will see in subsequent posts.

Conclusion

The SRP is one of the easiest to understand out of the SOLID principles but it's hard to get it right. Following the principle at each and every time might be an overkill but in general we should try to adhere to it as and when needed. The understanding of when to apply the principle and to what extent comes with experience and practice.

For future updates to my weekly blog, please subscribe to my blog via the "Subscribe To Weekly Post" feature at the right and follow me on Twitter. Until then Happy Coding :)


No comments:

Post a Comment