Skip to main content

SOLID: Open/Closed Principle

About 5 years ago, I wrote a series of short articles on the SOLID principles, shared by email to my colleagues as a weekly, Monday morning read. They were then archived for reference to our internal knowledge base. That's getting a revamp and re-platforming now, and given their age, I'm not sure these pieces will be making the cut. Given it's fairly timeless stuff, seems a shame for them to disappear into the virtual ether, so I'll save them for posterity here.

The SOLID Principles

The SOLID principles are a well established set of tenets intended to guide software design toward a maintainable solution. They are widely applicable and operate at a high level, so are well worth considering for almost any type of application we are looking to build, using any framework or language.

For the full set of articles in the series, see:

O is for Open/Closed Principle

The open/closed principle states that objects or entities should be open for extension, but closed for modification. This is effectively saying that once you've designed and built a class, unit tested it and released it into production, it shouldn't be modified to add new functionality to meet new requirements. You can fix bugs, but if there's something new you shouldn't changing the interface or implementation of the class itself to avoid regression bugs.

Pretty strict right? Following this guidance would indicate that to add new functionality you would need to inherit from the original class and add the new behaviour with new or overridden methods. That's likely too much to follow to the letter and probably not something that is really feasible to do. Attempting to do so would likely mean too much time and effort is spent trying to predict the future, which as another principle - YAGNI - suggests, that's not something we generally want to try to do to any level of detail.

As the discussion here suggests though, it can be something you consider as a class is first modified due to changing requirements, in order to make further changes easier in the future.

I worked on a project that involved building a survey application during which there was a good example illustrating modifying a class to adhere to this principle. The application contained a class that represented a multiple choice question, where each option is associated with a score. We then had a method responsible for calculating the maximum score available in a given set of questions.

Later we needed to add the facility to have single-select questions (radio-buttons instead of check-boxes in the user interface). In this case the maximum score available isn't the sum of all the scores on the options, it's the maximum score associated with any given option (as the user can only select one).

One way to support this would be via a condition in the method that calculates the maximum available score - checking to see the type of the question and finding the maximum or sum total of the scores for the question options as appropriate. We might avoid that by though by refactoring to adhere to the open/closed principle, introducing an abstract base class and method, and implementing it as appropriate in separete concrete classes for multiple and single select questions.