Thông báo: Download 4 khóa học Python từ cơ bản đến nâng cao tại đây.
Nguyên tắc Đóng-Mở trong Python
Trong bài viết này, bạn sẽ được giới thiệu về nguyên tắc Đóng-Mở (Open-Closed Principle - OCP), một trong năm nguyên tắc quan trọng của SOLID trong thiết kế phần mềm. Nguyên tắc này giúp đảm bảo rằng hệ thống của bạn có thể dễ dàng mở rộng bằng cách thêm các tính năng mới mà không cần thay đổi mã nguồn hiện tại, từ đó giảm thiểu rủi ro gây ra lỗi và duy trì sự ổn định của hệ thống. Hãy cùng tìm hiểu cách áp dụng nguyên tắc này trong Python để xây dựng các hệ thống linh hoạt và dễ bảo trì hơn.

Giới thiệu về nguyên tắc Đóng-Mở trong Python
Nguyên tắc Đóng-Mở là một trong năm nguyên tắc trong bộ nguyên tắc SOLID. Chữ "O" trong SOLID đại diện cho nguyên tắc này:
- S – Nguyên tắc Trách nhiệm đơn lẻ (Single Responsibility Principle)
- O – Nguyên tắc Đóng-Mở (Open-Closed Principle)
- L – Nguyên tắc Thay thế Liskov (Liskov Substitution Principle)
- I – Nguyên tắc Phân tách Giao diện (Interface Segregation Principle)
- D – Nguyên tắc Đảo ngược Phụ thuộc (Dependency Inversion Principle)
Nguyên tắc Đóng-Mở quy định rằng một lớp, phương thức, hay hàm nên mở rộng cho việc thêm chức năng mới nhưng đóng lại đối với việc chỉnh sửa mã đã tồn tại.
Nguyên tắc này giúp hệ thống dễ dàng mở rộng mà không cần sửa đổi mã nguồn đã có, tránh gây ra lỗi không mong muốn.
Bài viết này được đăng tại [free tuts .net]
Ví dụ vi phạm nguyên tắc Đóng-Mở
Xét ví dụ sau:

class Person:
def __init__(self, name):
self.name = name
def __repr__(self):
return f'Person(name={self.name})'
class PersonStorage:
def save_to_database(self, person):
print(f'Save the {person} to database')
def save_to_json(self, person):
print(f'Save the {person} to a JSON file')
if __name__ == '__main__':
person = Person('John Doe')
storage = PersonStorage()
storage.save_to_database(person)
Ở ví dụ trên, lớp PersonStorage có hai phương thức:
save_to_database(): Lưu đối tượngPersonvào cơ sở dữ liệu.save_to_json(): Lưu đối tượngPersonvào file JSON.
Nếu muốn thêm chức năng lưu vào file XML, ta phải thay đổi lớp PersonStorage, điều này vi phạm nguyên tắc Đóng-Mở, vì lớp này không mở rộng mà lại yêu cầu sửa đổi.
Cách tuân thủ nguyên tắc Đóng-Mở trong Python
Để lớp PersonStorage tuân thủ nguyên tắc Đóng-Mở, ta cần thiết kế sao cho có thể thêm các chức năng mới mà không sửa đổi mã hiện tại.

Trước tiên, định nghĩa một lớp trừu tượng PersonStorage chứa phương thức trừu tượng save():
from abc import ABC, abstractmethod
class PersonStorage(ABC):
@abstractmethod
def save(self, person):
pass
Tiếp theo, tạo các lớp kế thừa như PersonDB và PersonJSON để lưu đối tượng Person vào cơ sở dữ liệu hoặc file JSON:
class PersonDB(PersonStorage):
def save(self, person):
print(f'Save the {person} to database')
class PersonJSON(PersonStorage):
def save(self, person):
print(f'Save the {person} to a JSON file')
Nếu muốn lưu đối tượng vào file XML, ta có thể dễ dàng tạo thêm một lớp mới PersonXML:

class PersonXML(PersonStorage):
def save(self, person):
print(f'Save the {person} to an XML file')
Và có thể sử dụng lớp PersonXML để lưu đối tượng Person vào file XML:
if __name__ == '__main__':
person = Person('John Doe')
storage = PersonXML()
storage.save(person)
Kết hợp tất cả lại với nhau:
from abc import ABC, abstractmethod
class Person:
def __init__(self, name):
self.name = name
def __repr__(self):
return f'Person(name={self.name})'
class PersonStorage(ABC):
@abstractmethod
def save(self, person):
pass
class PersonDB(PersonStorage):
def save(self, person):
print(f'Save the {person} to database')
class PersonJSON(PersonStorage):
def save(self, person):
print(f'Save the {person} to a JSON file')
class PersonXML(PersonStorage):
def save(self, person):
print(f'Save the {person} to an XML file')
if __name__ == '__main__':
person = Person('John Doe')
storage = PersonXML()
storage.save(person)
Kết bài
Nguyên tắc Đóng-Mở giúp bạn tạo ra các hệ thống phần mềm linh hoạt và dễ dàng mở rộng mà không cần sửa đổi mã đã tồn tại, đảm bảo tính ổn định và giảm thiểu rủi ro phát sinh lỗi khi thực hiện các thay đổi. Bằng cách áp dụng nguyên tắc này, mã nguồn của bạn sẽ trở nên dễ bảo trì hơn, đồng thời giúp bạn dễ dàng phát triển và tích hợp các tính năng mới mà không ảnh hưởng đến các phần khác của hệ thống.

Các kiểu dữ liệu trong C ( int - float - double - char ...)
Thuật toán tìm ước chung lớn nhất trong C/C++
Cấu trúc lệnh switch case trong C++ (có bài tập thực hành)
ComboBox - ListBox trong lập trình C# winforms
Random trong Python: Tạo số random ngẫu nhiên
Lệnh cin và cout trong C++
Cách khai báo biến trong PHP, các loại biến thường gặp
Download và cài đặt Vertrigo Server
Thẻ li trong HTML
Thẻ article trong HTML5
Cấu trúc HTML5: Cách tạo template HTML5 đầu tiên
Cách dùng thẻ img trong HTML và các thuộc tính của img
Thẻ a trong HTML và các thuộc tính của thẻ a thường dùng