PTOM: Single Responsibility Principle

The Single Responsibility Principle

This post is about the first letter in Uncle Bob’s SOLID acronym, Single Responsibility Principle, and a continuation of The Los Techies Pablo’s Topic of the Month – March: SOLID Principles.  Sean has already posted on this, but I’d like to “contribute”.

Note about the SOLID acronym and this blog “storm”:
This “principle” is more or less common sense, as are most of the other items in the SOLID acronym.  I like the idea of this series because I personally have interviewed with companies who would ask about possible code scenarios and I respond with one of these principles or one of the GOF patterns and they look back at me with a blank stare.  I know these are just labels, but if they can reduce the miscommunication possibilities and start standardizing our industry, I’m all for it.  I know some of the new ideas and labels out there are still being hammered out (i.e., like the BDD discussions as of late), but that is part of the process and what has to happen in such a young industry like ours.

Single-Responsibility Principle (SRP):

A class should have only one reason to change.

A good anti-example is the Active Record pattern.  This pattern is in contradiction of SRP.  A domain entity handles persistence of it’s information. (Note: There is nothing wrong with using Active Record; I’ve recently used it on a quick demo site and it worked perfectly)  Normally, you would have a controller method/action pass a “hydrated” entity to a method of a repository instance.

Like my favorite quote says:

Talk is cheap, show me the code ~ Linus Torvalds

let’s look at some .NET code.

Anti-SRP (Active Record)

Imagine you have a User entity that has a username and password property.  I’m using the Castle Active Record libraries for this example.

 sing System;
 sing Castle.ActiveRecord;
  amespace ActiveRecordSample
 
    [ActiveRecord]
    public class User : ActiveRecordBase<User>
    {
        private int id;
         private string username;
         private string password;
          public User()
         {
         }
          public User(string username, string password)
         {
             this.username = username;
             this.password = password;
         }
          [PrimaryKey]
         public int Id
         {
             get { return id; }
             set { id = value; }
         }
          [Property]
         public string Username
         {
             get { return username; }
             set { username = value; }
         }
          [Property]
         public string Password
         {
             get { return password; }
             set { password = value; }
         }
     }
 }

As you can see you use attributes to dictate how your properties map to columns in your database table.  Your entity name usually matches your table name, when using just the ActiveRecord attribute with no explicit table name (i.e., [ActiveRecord("UserTableName")].

To save the user you would take an instantiated user and just call user.Save();  This would cause an update to fire if the user instance had identity (aka an Id) and insert if it did not.

Translation to SRP

What I would normally do is have an architecture like the following:

image

The UserRepository would be used by a web controller (I use monorail for my web projects), being passed a User instance, and Save(user) would be called.

using System.Collections.Generic;
using Castle.MonoRail.Framework;
using SrpPost.Core;
using SrpPost.Data;
namespace SrpPost.Web.Controllers

 [Layout("default"), Rescue("generalerror")]
 public class UserController : SmartDispatcherController
   {
       private readonly IUserRepository userRepository;
       public UserController(IUserRepository userRepository)
       {
           this.userRepository = userRepository;
       }
       public void Index()
       {
           RenderView("userlist");
       }
       public void Save([DataBind("user", Validate = true)] User user)
       {
           userRepository.Save(user);
           Flash["LoginError"] = "User saved successfully.";
           RenderView("userlist");
       }
   }
}


So, what it boils down to is that the user class now knows nothing on how it is persisted to the database.

SRP is one of the hardest principles to enforce because there is always room for refactoring out one class to multiple; each class has one responsibility.  It is personal preference because class explosion does cause some people to become code zealots.  One of my other favorite quotes lately is:

Always code as if the guy maintaining your code would be a violent psychopath and he knows where you live.

Enjoy!

Related Articles:

    Post Footer automatically generated by Add Post Footer Plugin for wordpress.

    About Jason Meridth

    Continuously learning software developer trying to not let best be the enemy of better
    This entry was posted in Agile, C#, castle, monorail, principles, SOLID. Bookmark the permalink. Follow any comments here with the RSS feed for this post.

    One Response to PTOM: Single Responsibility Principle

    1. Martin Odhelius says:

      The last pattern you are using actually looks like the Data Acess Object-pattern (DAO) http://en.wikipedia.org/wiki/Data_Access_Object and is in fact much better than the Active Record-pattern in most situations, especially when you want to handle several different data sources or when you want to migrate data between different db:s for example.