Tired of looking for errors in log files? Use OneTrueError - Automatic exception management for .NET.

SOLID principles with real world examples

The following article aims to explain the five SOLID principles with real world examples. The SOLID principles are five programming principles which is considered to be the foundation of every well designed application. Following the principles will most likely lead to applications which are is easy to extend and maintain. That’s possible since you got small well defined classes with clear contracts.

All motivator images are created by Derick Baley.

Let’s get started with the principles.

Single Responsibility Principle

Single responsibility states that every class should only have one reason to change. A typical example is an user management class. When you for instance create a new user you’ll most likely send an welcome email. That’s two reasons to change: To do something with the account management and to change the emailing procedure. A better way would be to generate some kind of event from the account management class which is subscribed by a UserEmailService that does the actual email handling.

The most effective way to break applications it to create GOD classes. That is classes that keeps track of a lot of information and have several responsibilities. One code change will most likely affect other parts of the class and therefore indirectly all other classes that uses it. That in turn leads to an even bigger maintenance mess since no one dares to do any changes other than adding new functionality to it.

Making sure that a class has a single responsibility makes it per default also easier to see what it does and how you can extend/improve it.

Classes that are hard to unit test are often breaking SRP.

External links

* Wikipedia
* Example & tips on how to follow the principle (earlier post by me)

Open/Closed principle

Open/Closed principle says that a class should be open for extension but closed for modification. Which means that you can add new features through inheritance but should not change the existing classes (other than bug fixes).

The reason is that if you modify a class, you’ll likely break the API/Contract of the class which means that the classes that depend on it might fail when you do so. If you instead inherit the class to add new features, the base contract is untouched and it’s unlikely that dependent classes will fail.

Example violation

Here is a real world parser method (from a SO question which I’ve answered):

    public void Parse()
    {
        StringReader reader = new StringReader(scriptTextToProcess);
        StringBuilder scope = new StringBuilder();
        string line = reader.ReadLine();
        while (line != null)
        {
            switch (line[0])
            {
                case '$':
                    // Process the entire "line" as a variable, 
                    // i.e. add it to a collection of KeyValuePair.
                    AddToVariables(line);
                    break;
                case '!':
                    // Depending of what comes after the '!' character, 
                    // process the entire "scope" and/or the command in "line".
                    if (line == "!execute")
                        ExecuteScope(scope);
                    else if (line.StartsWith("!custom_command"))
                        RunCustomCommand(line, scope);
                    else if (line == "!single_line_directive")
                        ProcessDirective(line);
    
                    scope = new StringBuilder();
                    break;
    
                default:
                    // No processing directive, i.e. add the "line" 
                    // to the current scope.
                    scope.Append(line);
                    break;
            }
    
            line = reader.ReadLine();
        }
    }

It works great. But the method have to be changed each time we want to add support for a new directive. It’s therefore not closed for modification.

Solution

Lets create an interface which is used for each handler (for '$' and '!' in the example above):

    public interface IMyHandler
    {
        void Process(IProcessContext context, string line);
    }

Notice that we include a context object. This is quite important. If we create a new parser called SuperCoolParser in the future we can let it create and pass a SuperAwsomeContext to all handlers. New handlers which supports that context can use it while others stick with the basic implementation.

We comply with Liskovs Substitution Principle and doesn’t have to change the IMyHandler.Process signature (and therefore keeping it closed for modification) when we add new features later on.

The parser itself is implemented as:

    public class Parser
    {
        private Dictionary<char, IMyHandler> _handlers = new Dictionary<char, IMyHandler>();
        private IMyHandler _defaultHandler;
    
        public void Add(char controlCharacter, IMyHandler handler)
        {
            _handlers.Add(controlCharacter, handler);
        }
    
        private void Parse(TextReader reader)
        {
            StringBuilder scope = new StringBuilder();
            IProcessContext context = null; // create your context here.
    
            string line = reader.ReadLine();
            while (line != null)
            {
                IMyHandler handler = null;
                if (!_handlers.TryGetValue(line[0], out handler))
                    handler = _defaultHandler;
    
                handler.Process(context, line);
    
    
                line = reader.ReadLine();
            }
        }
    }

If you go back and look at the ! handling you’ll see a lot of if statements. That method likely have to be changed to add support for more features. Hence it do also violate the principle. Let’s refactor again.

    public interface ICommandHandler
    {
        void Handle(ICommandContext context, string commandName, string[] arguments);
    }
    
    public class CommandService : IMyHandler
    {
        public void Add(string commandName, ICommandHandler handler) 
        {
        }
    
        public void Handle(IProcessContext context, string line)
        {
           // first word on the line is the command, all other words are arguments.
           // split the string properly
    
           // then find the corrext command handler and invoke it.
           // take the result and add it to the `IProcessContext`
        }
    }

External links

* Wikipedia

Liskovs Substitution Principle

Liskovs Substitution Principle states that any method that takes class X as a parameter must be able to work with any subclasses of X.

The principle makes sure that every class follows the contract defined by its parent class. If the class Car has a method called Break it’s vital that all subclasses breaks when the Break method is invoked. Imagine the suprise if Break() in a Ferrari only works if the switch ChickenMode is activated.

Violation

Let’s use the motivator image as inspiration and define the following classes:

    public interface IDuck
    {
       void Swim();
    }
    public class Duck : IDuck
    {
       public void Swim()
       {
          //do something to swim
       }
    }
    public class ElectricDuck : IDuck
    {
       public void Swim()
       {
          if (!IsTurnedOn)
            return;
    
          //swim logic  
       }
    }

And the calling code:

    void MakeDuckSwim(IDuck duck)
    {
        duck.Swim();
    }

As you can see, there are two examples of ducks. One regular duck and one electric duck.

The electric duck can only swim if it’s turned on.The MakeDuckSwim method will not work if a duck is electric and not turned on.

That breaks LSP since any user of the IDuck interface expects the duck to swim when calling MakeDuckSwim.

Solution

You can of course solve it by doing something like this (in the method that uses the ducks)

    void MakeDuckSwim(IDuck duck)
    {
        if (duck is ElectricDuck)
            ((ElectricDuck)duck).TurnOn();
        duck.Swim();
    }

But that would break Open/Closed principle and has to be implemented everywhere that the ducks are used (and therefore still generate instable code).

The proper solution would be to automatically turn on the duck in the Swim method and by doing so make the electric duck behave exactly as defined by the IDuck interface.

    public class ElectricDuck : IDuck
    {
       public void Swim()
       {
          if (!IsTurnedOn)
            TurnOnDuck();
    
          //swim logic  
       }
    }

External links

* Wikipedia

Interface Segregation Principle

ISP states that interfaces that have become “fat” (like god classes) should be split into several interfaces. Large interfaces makes it harder to extend smaller parts of the system.

There is nothing that says that there should be a one-to-one mapping between classes and interfaces. It’s in fact much better if you can create several smaller interfaces instead (depends on the class though).

Violation

The MembershipProvider in ASP.NET is a classical example of a violation. MSDN contains a large article (which 4 out of 34 have found useful) which contains a long and detailed instruction on how to properly implement the class.

Solution

The provider could have been divided in several parts:

* MembershipProvider – A facade to the below interfaces
* IAccountRepository – Used to fetch/load accounts
* IPasswordValidator – Checks that the password is valid (according to business rules)
* IPasswordStrategy – How to store PW (hash it, use encryption or just store it in plain text)

Now you only have to implement a small part if you need to customize the provider (for instance IAccountRepository if you are using a custom data source). There’s a saying: “Favor composition over inheritance” which the membership providers illustrates well. The original solution used inheritance while mine used composition.

External Links

* Wikipedia

Dependency Inversion Principle

The principle which is easiest to understand. DIP states that you should let the caller create the dependencies instead of letting the class itself create the dependencies. Hence inverting the dependency control (from letting the class control them to letting the caller control them).

Before

    public class Volvo
    {
        B20 _engine;

        public Volvo()
        {
           _engine = new B20();
        }
    }

After

    public class Volvo
    {
        IEngine _engine;

        public Volvo(IEngine engine)
        {
           if (engine == null) throw new ArgumentNullException("engine");
           _engine = engine;
        }
    }

Which makes it a lot more fun since we now can do the following:

    var myVolvo = new Volvo(new BigBadV12());

(Nice real world example, huh? ;))

Update

I messed up a bit. Dependency Inversion states that you should depend upon abstractions and that lower layers should not be aware of higher layers. I’ll get back to that. Dependency Injection is when you inject dependencies into the constructors instead of creating them in the class. Inversion Of Control is that the container controls your objects and their lifetime.

A. HIGH LEVEL MODULES SHOULD NOT DEPEND UPON LOW LEVEL MODULES. BOTH SHOULD DEPEND UPON ABSTRACTIONS.
B. ABSTRACTIONS SHOULD NOT DEPEND UPON DETAILS. DETAILS SHOULD DEPEND UPON ABSTRACTIONS

The original principle targets modules while I also like to apply it at class level too. It makes the principle easier to apply (so the text below is how I apply the principle).

Depend on abstractions simply means that you should depend on as generic class/interface as possible. For instance IUserRepository instead of DbUserRepository or HttpRequestBase instead of HttpRequest. The purpose is that your code should be as flexible as possible. The more abstract the dependencies are, the easier it is to refactor them or create new implementations.

Depending on abstractions also make your code less likely to change if the dependency change.

External links

* Wikipedia
* Introduction

Summary

Feel free to leave a comment if something is unclear. It will not just help you, but all future readers.

This entry was posted in Architecture and tagged , . Bookmark the permalink.
  • http://www.bizcacha.com Eduardo

    Very nice article. Really likes the real world samples.

  • Johan Karlsson

    Bra läsning! Jag tar hem den till frugan!

    • http://www.gauffin.org jgauffin

      Blev hon glad över överraskningen? ;)

  • Björn

    Great examples, as always! I come to think of something: When I’m cleaning up my godlike classes and such, I often find myself thinking that it’s really hard to organize all my new and neat interfaces, refactored classes, specializations etc. in a satisfactory way. So there’s another challenge right there. But a fun one!

  • http://www.threenine.co.uk Gary Woodfine

    Good article. Made me think back to an e-book I read a few years ago on Los Techies.
    http://lostechies.com/wp-content/uploads/2011/03/pablos_solid_ebook.pdf

    Great as a quick reference to that article.

  • Elkhan

    Very good work !
    Gary, thx for a nice reading material !!!

  • http://randonom.com Sean Glover

    I’m sure this article will hit SOLID home for a lot of programmers that are on the fence about how they actually apply in the real world. Well done.

  • http://vishalsjadhav.wordpress.com/ Vishal

    Hi, Thank you for such a simplest yet the most effective explanation of SOLID, I love those motivational posters. Keep up the good work !

  • http://vishalsjadhav.wordpress.com/ Vishal

    *Simple…ahh I can’t even express thank you :X

  • ATEMPI

    “But that would break Open/Closed principle and has to be implemented everywhere that the ducks are used (and therefore still generate instable code).”

    Why is it breaking the OCP?

  • Alexander Volochnev

    Great article, thank you!

  • Yuri Fedoseev

    Images don’t load

  • Shalabh Saxena

    Thank you!! its was an excellent going through the pages…

  • Pingback: Anonymous

  • Pingback: SOLID – OOP Principles | A Developer's Insight