Today I will tackle a topic that new to intermediate software developers struggle with, that’s a concept of design principles,if you master the design principles it will greatly improve your productivity as a software developer.

I know in some large organisations I know there is a person responsible for implementing the design principles or enforce them or ensures that they are implemented during software development.

In the following weeks I will be covering a concept called the SOLID principles, covering one or two concept per week.

First let me define what solid principles are. SOLID is actually an acronym for

S-Single Responsibility Principle(SRP)

O-Open/Closed principle(OCP)

L-Liskov Substitution Principle(LSP)

I-Interface Segregation Principle(ISP)

D-Dependency Inversion Principle(DIP)

5 TOOLS AND TECHNOLOGIES EVERY DEVELOPER SHOULD MASTER

THE SINGLE RESPONSIBLE PRINCIPLE

singleresponsibilityprinciple
Single responsible principle

Robert “Uncle Bob” Martin in his book: Agile Principles Patterns and Principles in C# states:

“A class should have only one reason to change “

Like life if you focus on so many things you will fail, in the same way If a class has more than one responsibility, the responsibilities become coupled. Changes to one responsibility may impair or inhibit the class’s ability to meet the others. This kind of coupling leads to fragile designs that break in unexpected ways when changed.

Like in the image above,the pocket knife is a super knife it can do almost everything,but in the process of adding all the components that make it a super knife it has lost its real purpose that is being a pocket knife.

In the same way you can overload a class with a lot of functionality to a point that it loses its identity

Let me illustrate with a C# code example

The following C# example shows a class named “RectangleShape” that implements two methods, one that calculates its rectangle area and one that draws the rectangle. When the area calculation changes for some reason or the drawing method has to change, for example, another fill color is used, then the whole class is under change. Also if the properties are altered, it influences both methods. After a code change, the class must be tested as a whole again. There is clearly more than one reason to change this class.

Problem

/// <summary>
/// Class calculates the area and can also draw it on a windows form object.
/// </summary>

    public class RectangleShape
    {
        public int Height{ get; set; }
        public int Width { get; set; }
 
        public int Area()
        {
            return Width * Height;
        }
 
        public void Draw(Form form)
        {
            SolidBrush myBrush = new SolidBrush(System.Drawing.Color.Red);
            Graphics formGraphics = form.CreateGraphics();
            formGraphics.FillRectangle(myBrush, new Rectangle(0, 0, Width, Height);
        }
    }

Typically, the above class is used by consuming client classes like these:

/// <summary>
/// Consumes the RectangleShape */
/// </summary>
    public class GeometricsCalculator
    {
        public void CalculateArea(RectangleShape rectangleShape)
        {
            int area = rectangleShape.Area();
        }
    }   


/// <summary>
//// Consumes the RectangleShape */
/// </summary>
    public class GraphicsManager
    {
        public Form form {get;set;}

        public void DrawOnScreen(RectangleShape rectangleShape)
        {
            rectangleShape.Draw(form);
        }
    }

Solution

The next classes show how to separate the different responsibilities. Basic coding is used not taking other SOLID principles into account. It only just shows how to deal with the SRP principle. The RectangleDraw class consumes now a RectangleShape instance and a Form object.

/// <summary>
/// Class calculates the rectangle's area.
/// </summary>
    public class RectangleShape
    {
        public int Height { get; set; }
        public int Width { get; set; }

        public int Area()
        {
            return Width * Height;
        }
    }

/// <summary>
/// Class draws a rectangle on a windows form object.
/// </summary>
    public class RectangleDraw
    {
        public void Draw(Form form, RectangleShape rectangleShape)
        {
            SolidBrush myBrush = new SolidBrush(System.Drawing.Color.Red);
            Graphics formGraphics = form.CreateGraphics();
            formGraphics.FillRectangle(myBrush, 
            new Rectangle(0, 0, rectangleShape.Width,rectangleShape.Height));
        }
    }

The following code shows how to consume both classes:

/// <summary>
/// Consumes the RectangleShape */
/// </summary>
    public class GeometricsCalculator
    {
        public void CalculateArea(RectangleShape rectangleShape)
        {
            int area = rectangleShape.Area();
        }
    }

/// <summary>
/// Consumes the RectangleDraw and RectangleShape */
/// </summary>
    public class GraphicsManager
    {
        public Form form { get; set; }
        
        public void DrawOnScreen(RectangleDraw rectangleDraw, RectangleShape rectangleShape)
        {
            rectangleDraw.Draw(form, rectangleShape);
        }
    }

Before i wrap up for today let me point out the advantages:

Major benefits of this pattern are

  • Code complexity is reduced by being more explicit and straightforward

  • Loose coupling

  • Improved readability

 

%d bloggers like this: