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
Lets consider a simple banking module that is responsible for calculating interest of accounts respect to account type. Say app owner bank offers to their client three types of accounts : savings accounts, basic checking accounts, money market deposit account. Each of the account type has different interest rate, and interest is calculated on different other factors such as amount deposited, average balance per month and so on. Thus based on this business rules we designed this class Accounts which calculates interest based on account types.
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; } }
Above solution work perfectly for our client bank and app went to live and every one is happy. Few months later bank realize other banks are making money from certificates of deposit account , so we should do that, lets change our system to accommodate that. Now our revised system looks like this,
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 its not hard to guess, it will go through same process each time bank wants to launch another account type or made change on existing account types business rules. This is where open closed principle violates.
Resolution
To solve this We can create an common Interface which will be implemented by all classes represent account types. Benefit is later change can be accommodate better without modifying other corresponding class.
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; } }
Through approach we can add as many account type is needed, all we need is add another class for that account type. Also modification of business logic resides in respective account type class. Hence IAccount interface implement the idea of open for extension but closed for modifications.
I have a problem with the overall premise of your article but I still think its really informative. I really like your other posts. Keep up the great work. If you can add more video and pictures can be much better. Because they help much clear understanding. 🙂 thanks
thanks, if you can elaborate in which section I can be more descriptive ,I could try explain a bit details.