Tôi hiểu ý định của nguyên tắc đóng mở. Nó có nghĩa là để giảm nguy cơ phá vỡ một cái gì đó đã hoạt động trong khi sửa đổi nó, bằng cách nói với bạn cố gắng mở rộng mà không sửa đổi.
Tuy nhiên, tôi đã gặp một số khó khăn khi hiểu nguyên tắc này được áp dụng như thế nào trong thực tế. Theo hiểu biết của tôi, có hai cách để áp dụng nó. Beofore và sau khi có thể thay đổi:
Trước: chương trình trừu tượng hóa và 'dự đoán tương lai' càng nhiều càng tốt. Ví dụ: một phương thức
drive(Car car)
sẽ phải thay đổi nếuMotorcycle
s được thêm vào hệ thống trong tương lai, vì vậy nó có thể vi phạm OCP. Nhưng phương phápdrive(MotorVehicle vehicle)
ít có khả năng phải thay đổi trong tương lai, vì vậy nó tuân thủ OCP.Tuy nhiên, thật khó để dự đoán tương lai và biết trước những thay đổi sẽ được thực hiện cho hệ thống.
Sau: khi cần thay đổi, hãy mở rộng một lớp thay vì sửa đổi mã hiện tại.
Thực hành # 1 không khó hiểu. Tuy nhiên, thực tế # 2 là tôi gặp khó khăn trong việc hiểu cách áp dụng.
Ví dụ: (tôi đã lấy nó từ một video trên YouTube): giả sử chúng ta có một phương thức trong một lớp chấp nhận CreditCard
các đối tượng : makePayment(CraditCard card)
. Một ngày Voucher
s được thêm vào hệ thống. Phương pháp này không hỗ trợ chúng nên nó phải được sửa đổi.
Khi thực hiện phương thức ở nơi đầu tiên, chúng tôi đã không dự đoán được tương lai và chương trình theo các thuật ngữ trừu tượng hơn (ví dụ: makePayment(Payment pay)
vì vậy bây giờ chúng tôi phải thay đổi mã hiện có.
Thực hành # 2 nói rằng chúng ta nên thêm chức năng bằng cách mở rộng thay vì sửa đổi. Điều đó nghĩa là gì? Tôi có nên phân lớp lớp hiện tại thay vì chỉ thay đổi mã hiện có không? Tôi có nên tạo một số loại trình bao quanh nó chỉ để tránh viết lại mã không?
Hoặc nguyên tắc thậm chí không đề cập đến 'cách sửa đổi / thêm chức năng chính xác', mà chỉ đề cập đến 'làm thế nào để tránh phải thay đổi ở nơi đầu tiên (tức là chương trình để trừu tượng hóa)?