SOLID principles can go wrong

square-peg-round-hole

Many developers try to improve their programming practices by learning the SOLID principles. No harm here, this is a very good thing, the only problem is that without some experience (I mean a lot of it), you can easily make your code utterly complicated using the same principles that were designed to make your code nice and maintainable.

Here is a working sample application , that is used to “exemplify” the SOLID principles.

We have a basic Shape class with lots of subclasses. Each subclass has its own properties.


public abstract class Shape 
{
    public abstract double Area();
    
    public virtual double Volume() 
    { 
        throw new NotImplementedException("You cannot determine " +
           "volume from here...Method not implemented."); 
    }
}

public class Circle : Shape
{
    public int Radius { get; set; }
    public override double Area() { return 3.14 * Radius * Radius; }
}

public class Triangle : Shape
{
    public int Height { get; set; }
    public int Base { get; set; }
    public override double Area()
    {
        return 0.5 * Base * Height;
    }
}

public class Rectangle : Shape
{
   public int Length { get; set; }
   public int Breadth { get; set; }
   public override double Area()
   {
        return Length * Breadth;
   }
}

public class Square : Shape
{
    public Square() { }
    public int Side { get; set; }
}

Of course we have a factory that helps us build the shapes. Every good SOLID tutorial code must have a factory class, it is mandatory:

public class ShapeFactory<K, T> where T : class, K, new()
{
    static K k;
    private ShapeFactory() { }

    public static K Create()
    {
        k = new T();
        return k;
    }
}

And finally the actual application where we will use this monstrous code:

class Program
{
    private static void Main(string[] args)
    {
        try
        {
            var c = ShapeFactory<Shape, Circle>.Create();
            if(c is Circle)
            {
                var circle = c as Circle;
                circle.Radius = 5;
                Console.WriteLine(string.Format("{0}", circle.Area()));
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine("Error: {0}", ex.Message);
        }
        Console.Read();
    }
}

As you can see the code is really nice, it has all the fancy stuff in it, inheritance, factory pattern etc. The author is probably really proud of his SOLID design.

Well, I think this is an over engineered piece of crap. I think we should always implement the simplest thing that works nothing more nothing less (see the Be minimalist article). I know that this is a tutorial code and it’s used by people to learn the SOLID principles, but I think it’s important to be aware of how horribly wrong these principles are in the wrong context. In this specific code we need to answer the following questions:

Do we need to inherit all the shapes from the Shape parent class? I mean, do we ever plan to iterate through a list of Shapes and calculate the area and volume for them? If not, the inheritance has absolutely no point. In fact I would say that inheritance is overused these days, and when it is overused we end up with ugly inheritance dependency graphs.

Is the construction of any of the “shape” objects particularly difficult, time consuming, tricky? Does the factory class provide any value or it is completely useless? In case it has no real reason to exist, I wouldn’t use it, the new operator is far more clear.

I think that we all, must be aware of the fact, that some SOLID principles applies in some very specific scenarios. Forcing them into the wrong places can cause ugly and over complicated code.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s