DEV Community

loading...
Cover image for Explained: OPEN/CLOSE Principle In 2 Minutes

Explained: OPEN/CLOSE Principle In 2 Minutes

huzaifa99 profile image Huzaifa Rasheed Updated on ・3 min read

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();
  }
}
Enter fullscreen mode Exit fullscreen mode

⚠️ 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();
  }
}
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

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
  }
}
Enter fullscreen mode Exit fullscreen mode

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.

Discussion (0)

Forem Open with the Forem app