Repost of https://dev.to/rhuzaifa/explained-open-close-principle-in-2-minutes-29dd
Before we begin.
Ever heard about SOLID ?.
SOLID are 5 software development principles or guidelines based on Object-Oriented design making it easier for you to make your projects scalable and maintainable.
They are more like best practices than rules. Open/Close is a principle of SOLID Design.
So What Is It?
Open/Close is the O of SOLID.
It says
Software entities (classes, modules, functions, etc.) should be open for extension but closed for modification. Bertrand Meyer
Like you should not re-write your existing code to be compatible with the newer one.
Meaning
✔️ Can add more code.
✔️ Can Extend functionality to old code by adding new code.
❌ Can Modify old code used by other modules.
Goal
Get the system to a point where you can never break the core of your system. You can add more functionality but not modify the one used by other modules.
It is easier to follow this principle if you already follow the Single Responsibility Principle and it really comes in handy once you also follow the Liskov Substitution Principle.
This prevents those situations in which changing one class also requires you to update all depending classes.
We will use inheritance to demonstrate an example.
A SIMPLE USE CASE
Let’s say someone is paying for items bought from an E-commerce store. This is what it might look like in payment.ts
(ignore the syntax)
class Payment {
public payWithCash(){
// handle cash pay logic here
public payWithCredit(){
// handle credit pay logic here
}
}
function makePayment(payMethod: string) {
const payment = new Payment();
if(payMethod === 'cash'){
payment.payWithCash();
} else if(payMethod === 'credit'){
payment.payWithCredit();
}
}
⚠️ What if we want to add a new payment type? We would have to add a new method and modify our code.
class Payment {
public payWithCash(){
// handle cash pay logic here
public payWithCredit(){
// handle credit pay logic here
}
public payWithCoupon(){
// handle coupon pay logic here
}
}
function makePayment(payMethod: string) {
const payment = new Payment();
if(payMethod === 'cash'){
payment.payWithCash();
} else if(payMethod === 'credit'){
payment.payWithCredit();
} else if(payMethod === 'coupon'){
payment.payWithCoupon();
}
}
This is not in line with the Open/Close Principle.
With the Open/Close Principle we would modify our code payment.ts
as follows.
interface PaymentMethod {
pay() : boolean
}
class Cash implements PaymentMethod {
public pay(){
// handle cash pay logic here
}
}
class CreditCard implements PaymentMethod {
public pay(){
// handle credit pay logic here
}
}
function makePayment(payMethod: PaymentMethod) {
if(payMethod.pay()){
return true;
}
return false;
}
Now if we, later on, want to add a new payment option like wire transfer then we only need to add a new class, no changes needed to the existing code.
class WireTransfer implements PaymentMethod {
public pay(){
// handle wire transfer pay logic here
}
}
Since we are using the interfaces, be sure to check out if you are following Interface Segregation principle of SOLID.
Should You Use It?
You should use Open/Close if you want clean code but there are situations in which you should just go ahead and do your own stuff. It really depends on what you are doing.
Tip
You can get away with modifying your existing unit tests and just write a new one for the code you added.
So here it is. Do you like the article? Be sure to leave a comment.
What’s Next
Why The Dependency Inversion Principle Is Worth Using.