Click here to Skip to main content
15,880,392 members
Articles / Programming Languages / C#

Software Architecture Cheat Blog 3: Open Closed Principle

Rate me:
Please Sign up or sign in to vote.
5.00/5 (1 vote)
3 Oct 2012CPOL2 min read 6.4K   4  
Open Closed Principle (OCP) states that software entities (classes, modules, functions, etc.) should be open for extension but closed for modifications.

Define Principle

Open Closed Principle (OCP) states that software entities (classes, modules, functions, etc.) should be open for extension but closed for modifications.

Violation Example

Let us consider a simple banking module that is responsible for calculating the interest of accounts with respect to the account type. Say the app owner bank offers to their clients three types of accounts: savings account, basic checking account, money market deposit account. Each of the account types has a different interest rate, and the interest is calculated on other factors such as amount deposited, average balance per month, and so on. Thus based on these business rules we design this class Accounts which calculates the interest based on the account type.

C#
public enum AccountTYpe
{
    Savings,
    Checking,
    MoneyMarket 
}

public class Accounts
{
    private AccountTYpe accountType { get; set; }

    public Decimal CalculateInterest()
    {
        Decimal interest = 0;
        if (accountType == AccountTYpe.Savings)
        {
            //consider business rules and calculate interest of savings account
            interest = 2.50m;
        }
        else if (accountType == AccountTYpe.Checking)
        {
            //consider business rules and calculate interest of checking account
            interest = 3.50m;
        }
        else
        {
            //consider business rules and calculate interest of money market account
            interest = 5.00m;
        }

        return interest;
    }
}

The above solution works perfectly for our client bank and the app went live and everyone was happy. A few months later the bank realized other banks are making money from certificates of deposit accounts, so we should do that too, so let's change our system to accommodate that. Now our revised system looks like this:

C#
public enum AccountTYpe
{
    Savings,
    Checking,
    MoneyMarket,
    CertificatesOfDeposit
}

public class Accounts
{
    private AccountTYpe accountType { get; set; }

    public Decimal CalculateInterest()
    {
        Decimal interest = 0;
        if (accountType == AccountTYpe.Savings)
        {
            //consider business rules and calculate interest of savings account
            interest = 2.50m;
        }
        else if (accountType == AccountTYpe.Checking)
        {
            //consider business rules and calculate interest of checking account
            interest = 3.50m;
        }
        else if (accountType == AccountTYpe.CertificatesOfDeposit)
        {
            //consider business rules and calculate interest of certificates of deposit account
            interest = 6.35m;
        }
        else
        {
            //consider business rules and calculate interest of money market account
            interest = 5.00m;
        }

        return interest;
    }
}

Considering the above scenario it is not hard to guess, it will go through the same process each time the bank wants to launch another account type or change an existing account type's business rules. This is where the open closed principle is violated.

Resolution

To solve this we can create a common interface which will be implemented by all classes that represent the account types. The benefit is future changes can be accommodated better without modifying the corresponding class.

C#
public interface IAccount
{
    Decimal CalculateInterest();
}

public class SavingsAccounts:IAccount
{
    public decimal CalculateInterest()
    {
        return 2.50m;
    }
}

public class CheckingAccounts : IAccount
{
    public decimal CalculateInterest()
    {
        return 3.50m;
    }
}

public class MoneyMarketAccounts : IAccount
{
    public decimal CalculateInterest()
    {
        return 5.00m;
    }
}

Using this approach we can add as many account types as needed, all we need is to add another class for that account type. Also modifications to the business logic reside in the respective account type class. Thus the IAccount interface implements the idea of open for extension but closed for modifications.

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
Bangladesh Bangladesh
I am a Software Engineer and Microsoft .NET technology enthusiast. Professionally I worked on several business domains and on diverse platforms. I love to learn and share new .net technology and my experience I gather in my engineering career. You can find me from here

Personal Site
Personal Blog
FB MS enthusiasts group
About Me

Comments and Discussions

 
-- There are no messages in this forum --