SOLID Principles in Software Development - 2 OCP
The Open/Closed Principle (OCP) is the second principle of the SOLID principles and states that software entities (classes, modules, functions) should be open for extension but closed for modification. In simple terms, this means that you can add new functionality to your code without altering existing code. This approach minimizes the risk of introducing bugs into already tested functionality and allows the software to evolve in a safe and controlled manner.
The key to implementing the OCP is to design code that is extensible using techniques such as inheritance, polymorphism, and dependency injection. We achieve this by using abstractions (e.g. base classes or interfaces) rather than directly depending on concrete implementations. In this post, we will explore the OCP with a practical example using Python and an API that handles operations for different types of users.
Imagine (imagine, because you’ll notice it’s a horrible way to do it) an API that handles different user roles, such as “Admin” and “Guest”. An initial design that does not respect the OCP might look like this:
class User:
def __init__(self, username):
self.username = username
def get_permissions(self):
if self.username == "admin":
return ["read", "write", "delete"]
elif self.username == "guest":
return ["read"]
else:
return []
In this design, every time a new role is added, such as “Editor” or “SuperAdmin”, the get_permissions
method needs to be modified. This violates the OCP principle, since the existing code is not closed for modifications. Each change increases the risk of introducing bugs and makes the system less maintainable.
Now, let’s see what this would look like by applying the SOLID OCP principle. We can redesign the system using a base class and subclasses that encapsulate the logic specific to each role:
class User:
def __init__(self, username):
self.username = username
def get_permissions(self):
raise NotImplementedError("Subclasses must implement this method")
class Admin(User):
def get_permissions(self):
return ["read", "write", "delete"]
class Guest(User):
def get_permissions(self):
return ["read"]
In this design, the User
class acts as an abstraction, and each specific role (Admin
, Guest
, etc.) implements its own logic. Now, to add a new role, we simply create a new subclass, without touching the existing code.
Let’s take this example to a slightly broader place, an API with Flask. Suppose we want to implement an API route that returns a user’s permissions based on their role. Using the OCP-based design, the implementation would look like this:
from flask import Flask, jsonify
app = Flask(__name__)
@app.route("/permissions/<username>")
def get_user_permissions(username):
roles = {
"admin": Admin(username),
"guest": Guest(username),
}
user = roles.get(username.lower(), User(username))
try:
permissions = user.get_permissions()
except NotImplementedError:
return jsonify({"error": "Invalid role"}), 400
return jsonify({"username": username, "permissions": permissions})
if __name__ == "__main__":
app.run(debug=True)
With this approach, if a new role is added, such as “Editor”, we just need to create a new subclass of User
and register the role in the roles
dictionary. There is no need to modify the rest of the system.
The Open/Closed Principle not only improves code quality, but also promotes sustainable and scalable development practices. In a production environment, where requirements are constantly changing, applying this principle ensures that we can adapt quickly without compromising the stability of the system.
o/

Marco
Romero
Hi! I am a software developer with a solid development background and experience in various technical areas. I complement my technical skills with studies in teaching, which has enhanced my ability to communicate complex concepts clearly and effectively, as well as to collaborate in dynamic environments.
I have a proven track record in problem solving and incident management, applying a methodical and results-oriented approach. I quickly adapt to new technologies and methodologies, keeping up with industry trends to deliver innovative and efficient solutions.
- Name
- Phone
- Web
- Home
- Marco Antonio Romero Torrez
- +54 280 484 2576
- marcoromero.dev@gmail.com
- marcoromero.com.ar
- Puerto Madryn, Chubut - Argentina