Open/closed principle

This is part two of a five part series covering the SOLID principles. For more information on what the SOLID principles are, check out part one.

The rule

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

What does it mean?

In an ideal state, your application should have zero bugs and you are confident in the existing code. You are able to add features without introducing new bugs.

Writing code with this principle in mind will put you on the path to achieving this goal. You'll add new features by extending or writing new code without modifying old code.

Why it is important?

  • Reliable. The more existing code you touch and edit the more chance you have of introducing a bug to a working system.
  • Concise. Following this principle will force you to write cleaner code and reduce code smells.
  • Agile. You wont need to spend time refactoring existing code to add a new feature.

How can I use it?

An example of a violation of the principle is using conditional statements to check if a "thing" is a type of "thing".

The reason this violates the rule is that you are hard coding logic. At a later date when the logic changes or you want to add a new "thing" you'll need to modify the exisiting code.

Instead in this scenario we should change the way we wrote the code. Instead of checking if a "thing" is a type of "thing" we should tell our code what it is.

Lets look at an example of this and explore how we would improve it.

Example

In the demo below we'll create a steak helper, it's aim is help you cook the perfect steak.

Whats the code doing?
  • Create an instance of the helper
  • Pass in options, specifying how you want the steak cooked and how thick the steak is.
  • We call the instructions() method
  • A cooking time is returned based on how you want it cooked.
  • Additional cooking time is added depending on how thick the steak is.
  • Once we have this data we return a message containing the cooking instructions.

Are there any issues?

You are cooking for a friend who wants there steak cooked 'well done'. We don't have this in our system. Do we need to edit any exisiting code to add it?

The answer is yes. We would need to edit the baseCookingTime() function to add well done to the conditional statement. Lets refactor this code so we can add indefinite cooking methods without changing or modifying code.

Refactor

  • Pull out the different steak types into an array of objects.
  • Pass in the steakTypes to the SteakHelper.
  • Since we know what type of steak we want to cook, we can do a find, instead of using a conditional statement.
  • As the list of steakTypes grows, we wouldn't need to modify our SteakHelper code.

Wrap up

That's the open close principle. If you have any questions about it or some of the ES6 syntax I've used, ask a question in the comments section.

If you want to see how another person explains it then check out the links below. They are both short videos which go over the same principle.