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ượngPerson
vào cơ sở dữ liệu.save_to_json()
: Lưu đối tượngPerson
và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.