Open Closed Principle
The open-closed principle says that a class should be opened for extension and closed for modification. What does that mean?
A class should be made easy to add features and hard to alter its core function.
Suppose that you need to write a password validator for a user creation flow. You already have a CreateUser
class. What can you do?
You can create a password validation method inside the CreateUser
class, but that would violate the Single Responsibility principle. You should separate the validation responsibility from the CreateUser
class. You can create a ValidatePassword
class to accomplish this. Great, that should do it!
However, a ValidatePassword
class is not really that flexible. This class can only validate a password input. An even more flexible solution would be to create a Validate
class with a password
method inside it. In the future, if you need to add more validation logic, you can just extend this Validate
class with more methods like email
and username
to validate user email and username!
Let's imagine what would have happened if you had created ValidatePassword
. In the future if you need to validate email and username, you will have to create ValidateEmail
and ValidateUsername
classes. I will bet you two boxes of donuts that there will be plenty of duplicate codes (ValidateEmail
, ValidateUsername
, and ValidatePassword
mostly do the same thing).
I understand that upcoming features are often unprecedented. Some classes are more subtle and harder to spot for reusability. Maybe the PM assured you last month that the only validation you would ever need was ValidatePassword
, so you created that class naively believing that there was no need to extend it in the future. However, this week your PM told you that you needed to validate email and username after all! No worries, as long as you catch them early on, you could easily abstract it and create the Validate
class.
This is the "open" part of the open-closed principle: the Validate
class is open for extension. Each time you need to extend the feature, just add a new interface. Need an email validation? Add an email interface. Need a username validation? Add a username interface.
What about the "closed" part of the open-closed principle? By definition, a class is closed. In practice, you would create an instance of that class object, something like passwordValidator = new Validate("password")
.
Once a class is defined, no one should alter it. The Validate
class validates different attributes. That's it. If you decided that the Validate
class should start saving password into the database, then you violated the "closed" part (you also violated the single-responsibility principle).
By keeping the open-closed principle, anyone who depends on passwordValidator
won't receive surprise bugs.
Anytime you start thinking, "Hey, I've written codes like this before...", it's a good chance that you can create an extensible, more abstract class.