Click here to Skip to main content
15,868,158 members
Articles / Programming Languages / C# 3.5

Learning the S.O.L.I.D Programming Principles: Open Closed Principle [Part - III]

Rate me:
Please Sign up or sign in to vote.
5.00/5 (3 votes)
25 Oct 2014CPOL4 min read 12.2K   5   4
Open closed principle

History

In our previous posts, we learned ‘What is S.O.L.I.D. Programming Principles’ and a detailed explanation with code of Single Responsibility Principle.

S.O.L.I.D. is an acronym introduced by Michael Feathers as:

  1. S for SRP: Single responsibility principle
  2. O for OCP: Open/closed principle
  3. L for LSP: Liskov substitution principle
  4. I for ISP: Interface segregation principle
  5. D for DIP: Dependency inversion principle

Single Responsibility Principle says, class should have single responsibility. In reference to this, I would say “A class should have single responsibility”.

Let's dive into the ocean – can we read this like “a class should not design to do multiple activities”.

This is a very vast topic and it is not possible to learn/explain it in a one-shot. I divided this into the following parts:

Introduction

In this whole article, we will learn Open Closed Principle in details with example.

First of all, let's revise what is OCP [ref. to Learning The S.O.L.I.D Programming Principles: Overview [Part - I]]?

A definition from wiki:

Quote:

software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification

Learning Open/Closed Principle (OCP)

I took many weeks to understand this principle and when I visited my old code, I was shocked to see that I violate OCP in many of my previously written codes.

Let's explore this with an example: we need to update our database from one server to another server (suppose we need to refresh our development database from production), but there are some rules like data-type should be the same, data value should be changed, etc.

C#
public class ValidateData
{
    public void SyncronizeData(ServerData data, SourceServerData sourceData)
    {
        if (IsValid(data, sourceData))
        {
            //save data
        }
    }

    private bool IsValid(ServerData data, SourceServerData sourceData)
    {
        var result = false;

        if (data.Type == sourceData.Type)
            result = true;

        if (data.IP != sourceData.IP)
            result = true;

        //other checks/rules to validate incoming data

        return result;
    }
}

Wait here to think about what is wrong with the above code…

Any guesses…

Ok, let's discuss now, take a look into class ValidateData. First of all, it is doing two activities, in other words, our class is responsible for two things:

  • to validate incoming data (from source server)
  • to save data

Now, think of a scenario, if someone wants to extend this so, it could use another external service. In this scenario, he/she would have no other choice and have to modify IsValid method. Also, if someone needs to make it as a component and provide to third parties for their use, then its users would have no way to add another service. This means this class is not open for extensions. On the other hand, if someone needs to modify the behavior to persist data, she/he needs to change the actual class.

To sum up, this class is directly violating OCP as this is neither open for extensions not closed for modifications.

So, what would be a better solution for this class so it should follow, OCP.

Remember abstraction, let's try to do something by creating an interface:

C#
public interface IDataValidator
{
    bool Validate(ServerData data, SourceServerData sourceData);
}

Here, I created an interface IDataValidator which is having only one method Validate. Method name describes itself, it's a part of DataValidator so, it should validate data so, it named as Validate :).

Now, create validators of type IDataValidator. Something like:

C#
public class IPValidator : IDataValidator
{
    public bool Validate(ServerData data, SourceServerData sourceData)
    {
        return data.IP != sourceData.IP;
    }

}
public class TypeValidator : IDataValidator
{
    public bool Validate(ServerData data, SourceServerData sourceData)
    {
        return data.Type == sourceData.Type;
    }
}

Forget redesign our class ValidateData as:

C#
public class ValidateData
{
    public bool IsDataValidated(ServerData data, SourceServerData sourceData)
    {
        IList<IDataValidator> validators = new List<IDataValidator>();
        validators.Add(new IPValidator());
        validators.Add(new TypeValidator());

        return IsDataValid(validators, data, sourceData);
    }

    private bool IsDataValid(IList<IDataValidator> validators,
                             ServerData data, SourceServerData sourceData)
    {
        foreach (var validator in validators)
        {
            if (validator.Validate(data, sourceData))
                return true;
        }
        return false;
    }
}

Stay here to discuss the above snippet! In the above, we have a ValidateData class, which is only responsible for validating data by certain validations/rules.

With the above changes, our class is not more stable and robust, we can add many validators as we want. Also, you can use this validator to save your data.

Ah! I forget to mention, you can save the data just by calling this validator to another class, it could be repository class or your custom class where you just persist your data.

I am not going to write that part of save, you can easily implement this by yourself. :)

Revisiting – Learning The S.O.L.I.D Programming Principles: Open Closed Principle [Part - III]

Open Closed Principle says “software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification”

How to Download the Source Code?

You can download complete souce code of examples used in this article from GitHub: Learning Solid.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Chief Technology Officer
India India
Learning never ends.

Comments and Discussions

 
SuggestionMisunderstanding Pin
ArchAngel12328-Oct-14 10:47
ArchAngel12328-Oct-14 10:47 
AnswerRe: Misunderstanding Pin
Gaurav Aroraa28-Oct-14 20:58
professionalGaurav Aroraa28-Oct-14 20:58 
QuestionYour updated ValidateData class Pin
rrotstein27-Oct-14 16:38
rrotstein27-Oct-14 16:38 
AnswerRe: Your updated ValidateData class Pin
Gaurav Aroraa27-Oct-14 22:20
professionalGaurav Aroraa27-Oct-14 22:20 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.