Có phải là vi phạm Nguyên tắc Đóng mở để cập nhật hằng số đại diện cho giá trị trong thế giới thực không?


10

Tôi có một lớp tính thu nhập ròng hàng năm của công nhân. Nó có một hằng số đại diện cho một tỷ lệ thuế. Nhưng một ngày thuế suất đã thay đổi, vì vậy tôi cần sửa mã.

Có phải hành động sửa hằng số này cho thấy sự vi phạm Nguyên tắc Đóng mở , vì nó quy định rằng một lớp nên được đóng lại để sửa đổi?


10
Phần mềm thay đổi vì thế giới thực thay đổi. Mặt khác, việc tạo ra một tỷ lệ phần trăm thuế không đổi không phải là vi phạm Nguyên tắc Đóng mở vì đó chỉ là một việc không biết gì. Tỷ lệ phần trăm thuế là một mặt hàng có thể thay đổi rõ ràng nên được ràng buộc trong thời gian chạy.
Richard Chambers

4
Tôi hoàn toàn đồng ý với Richard. Nếu bạn phải thay đổi mã để sửa "hằng số" này, thì OCP là vấn đề ít nhất của bạn.
Robert Harvey

3
Những gì cấu thành vi phạm OCP là rất chủ quan và dù sao thì toàn bộ điều này có phần lỗi thời (vì kế thừa thực hiện không còn là cách thực hành tốt nhất nữa). Đây là một câu hỏi điển hình trong đó bạn phải đoán người hỏi câu hỏi nghĩ gì.
Robert Bräutigam

2
@DocBrown: điều gì tạo nên một "yêu cầu mới"? Bạn chỉ cho tôi một số mã, tôi có thể chỉ ra các yêu cầu mới chắc chắn sẽ yêu cầu thay đổi mã, bất kể bạn tuân thủ OCP như thế nào. Vì vậy, trở lại câu hỏi: Nếu nhà phát triển hỏi chuyên gia kinh doanh về nó, và không có kỳ vọng về mức thuế thay đổi nhiều hơn một lần trong vài năm, thì không có lý do gì để làm cho nó có thể cấu hình hoặc tiêm được. Chỉ cần giữ nó đơn giản và chuẩn bị cho những gì bạn biết . Và đối với những điều đó, chắc chắn, làm cho nó bên ngoài lớp học. Vì vậy, nó phụ thuộc .
Robert Bräutigam

1
@ RobertBräutigam: quan điểm của tôi là, IMHO không có thứ gọi là "tuân thủ OCP", chỉ có "tuân thủ OCP trong bối cảnh của một số loại yêu cầu nhất định". Chắc chắn có thể có một số chủ quan mà các thành phần nên là "tuân thủ OCP". Nhưng trong trường hợp được mô tả trong câu hỏi này, theo cách tôi hiểu, một yêu cầu thay đổi đã được xác định, do đó "lớp tính toán thu nhập" này rõ ràng không tuân theo OCP trong bối cảnh yêu cầu cụ thể này.
Doc Brown

Câu trả lời:


14

OCP có thể được hiểu rõ hơn khi nghĩ về các lớp hoặc thành phần được cung cấp bởi nhà cung cấp A trong một loại thư viện hộp đen, để người dùng B, C và D sử dụng (lưu ý đây chỉ là mô hình tinh thần tôi đang sử dụng cho rõ ràng, không thành vấn đề nếu trong thực tế người dùng duy nhất của lớp là chính A).

Nếu B, C và D có thể sử dụng hoặc sử dụng lại các lớp được cung cấp cho các trường hợp sử dụng khác nhau mà không cần sửa đổi mã nguồn của thư viện, thì thành phần sẽ đáp ứng OCP ( đối với danh mục các trường hợp sử dụng ). Có nhiều cách khác nhau để đạt được điều này, như

  • làm cho lớp có thể kế thừa (thường kết hợp với mẫu phương thức mẫu hoặc mẫu chiến lược)

  • bằng cách cung cấp "điểm tiêm" cho tiêm phụ thuộc

  • bằng cách cung cấp các tham số cấu hình cho lớp hoặc thành phần (ví dụ: bằng cách có tham số hàm tạo "phần trăm thuế", như trong trường hợp của bạn hoặc bằng cách sử dụng một số cơ chế cấu hình khác)

  • có thể các phương tiện khác, tùy thuộc vào ngôn ngữ lập trình hoặc hệ sinh thái

Các ví dụ điển hình bạn tìm thấy trong sách giáo khoa thường thuộc loại thứ nhất hoặc loại thứ hai (tôi đoán bởi vì trong mắt các tác giả của cuốn sách đó, loại thứ ba quá tầm thường không đáng để đề cập).

Như bạn thấy, điều này không liên quan gì đến việc cấm bất kỳ thay đổi mã nguồn nào của nhà cung cấp A (như sửa lỗi, tối ưu hóa hoặc thêm các tính năng mới theo cách tương thích ngược), điều này hoàn toàn không liên quan đến OCP. OCP là về cách A thiết kế giao diện và độ chi tiết của các thành phần trong lib, do đó các kịch bản tái sử dụng khác nhau (như tương tự với các mức thuế suất khác nhau) không tự động tạo ra các yêu cầu thay đổi.

Vì vậy, bất chấp những gì người khác nói với bạn ở đây, câu trả lời rõ ràng là "có" , đó sẽ là vi phạm OCP.

EDIT: dường như ở giữa một người nào đó đã viết một bài đăng trên blog chi tiết về chính xác chủ đề này. Mặc dù các phần của nó có thể được diễn đạt tốt hơn (như Derek Elkins đã chỉ ra), có vẻ như tác giả thường chia sẻ quan điểm của tôi rằng "hoàn thành OCP" không phải là tài sản tuyệt đối, nhưng một điều chỉ có thể được đánh giá trong bối cảnh nhất định danh mục thay đổi yêu cầu.


OK, vì vậy OCP là về việc cung cấp hành vi mở rộng cho các trường hợp sử dụng khác nhau với một trong ba phương tiện bạn đã liệt kê, phải không? Nhưng nếu ví dụ của OP ngụ ý rằng điều gì đó cơ bản sắp thay đổi thì sao? Tôi không biết OP của nước nào, nhưng ở nước tôi, thuế suất là thứ không thay đổi thường xuyên. Đó là một ví dụ nghèo nàn, nhưng có lẽ nó được cố tình trích xuất trong một hằng số, để nhấn mạnh điểm này. Tôi khá chắc chắn rằng nó không có nghĩa là có thể cấu hình hoặc mở rộng. Vì vậy, có lẽ câu hỏi là về "điều này không liên quan gì đến việc cấm bất kỳ thay đổi nào về mã nguồn của nhà cung cấp A".
Vadim Samokhin

Ít nhất tôi đã hiểu nó theo cách đó. Anh chàng tội nghiệp đã xóa câu trả lời được chấp nhận của mình đã làm như vậy hoặc tôi đoán. Bạn đã nhìn thấy nó từ một góc độ khác - tôi hiểu quan điểm của bạn và đồng ý với nó. Nhưng có vẻ như bình luận khôn ngoan nhất được đưa ra bởi @Robert Bräutigam. Cho đến bây giờ tôi vẫn chưa nhận ra rằng OCP là chủ quan.
Vadim Samokhin

1
Tôi đoán nếu tôi từng được hỏi cùng một câu hỏi, có một câu hỏi tôi nên hỏi khi trả lời: "hành vi đó có phải được mở rộng hoặc cấu hình bằng cách nào đó không?". Nếu có - hơn là sửa đổi trực tiếp bản thân một lớp là vi phạm OCP. Nếu không - hơn OCP đơn giản là không áp dụng trong tình huống đó.
Vadim Samokhin

1
@Zapadlo: Tôi nghĩ rằng nếu một thành phần đáp ứng OCP cho một loại yêu cầu thì không chủ quan - trong hầu hết các trường hợp, nếu một yêu cầu mới cần sửa đổi mã nguồn của một thành phần hoặc nếu thành phần đó hỗ trợ yêu cầu này ." các phương pháp có thể thực hiện nó không bị giới hạn 3 phương tiện đầu tiên tôi được liệt kê, xem chỉnh sửa của tôi quan niệm của bạn về tính chủ thể có thể được gây ra bởi vì OCP chỉ có một cái tên gây hiểu lầm và có hại khá giải thích trong nhiều sách giáo khoa..
Doc Brown

Quan niệm của tôi về sự chủ quan được gây ra bởi thực tế là tôi đã không hiểu đầy đủ những gì bạn nói - nhưng tôi đoán bây giờ, tôi đoán vậy. Cảm ơn rất nhiều cho ý kiến ​​sâu sắc và câu trả lời của bạn.
Vadim Samokhin

4

Như những người khác đang nói, lý tưởng là lớp thu nhập của người lao động sẽ cho phép tham số hóa hằng số, làm cho lớp này độc lập với giá trị đó.

Cuối cùng, ứng dụng gọi điện cũng có thể cho phép tham số hóa theo cấu hình bên ngoài (ví dụ: một tệp). Khi chúng tôi có cấu hình bên ngoài, chúng tôi có thể thay đổi thuế suất - mặc dù hãy xem xét rằng nếu tệp cấu hình chỉ được đọc một lần khi khởi động, thì ứng dụng sẽ phải được khởi động lại để phần trăm thuế được cập nhật có hiệu lực, vì vậy đó là điều cần giữ lí trí. Chúng tôi có thể cung cấp một tính năng ứng dụng để đọc lại cấu hình khi được hướng dẫn làm như vậy hoặc chúng tôi có thể cung cấp một cơ chế phức tạp hơn để thông báo khi tệp cấu hình thay đổi ...

Về lâu dài, bạn có thể thấy rằng các vấn đề về thuế đòi hỏi nhiều hơn chỉ là tỷ lệ phần trăm - ví dụ: một ngày, luật thuế phức tạp hơn và yêu cầu một số phần trăm và một số hằng số (ví dụ: số tiền dưới 10 nghìn đô la bị đánh thuế ở mức X%, trong khi phần còn lại bị đánh thuế ở mức Y%).

Điều này về cơ bản gợi ý sử dụng một mẫu chiến lược, trong đó lớp chính được đề cập ở đây chấp nhận một đối tượng chiến lược để tính thuế.

Các chiến lược khác nhau (và% hằng số và $ hằng) nên có thể được chọn từ tệp cấu hình, và bây giờ, việc thêm một chiến lược mới yêu cầu thêm một số mã mới, nhưng không nhất thiết phải cập nhật mã hiện có.

Mỗi chiến lược có thể biết cách phân tích / giải thích các đối số cấu hình bên ngoài của chính nó, cùng với cách tính thuế thực tế.

Về mặt động lực, thuế có thể phụ thuộc nhiều hơn vào địa phương quản lý, do đó bạn có thể có địa phương liên quan đến thu nhập hoặc với nhân viên (hoặc cả hai). Trong cấu hình bên ngoài, chúng tôi có thể liên kết miền địa phương với chiến lược thuế.


Cũng thấy tiêm phụ thuộc , nơi chúng tôi quản lý những điều này một cách rõ ràng.


1
Câu hỏi không phải là nếu đó là một ý tưởng tồi để chôn vùi thứ gì đó như phần trăm thuế trong mã, tôi chắc chắn điều đó là hiển nhiên đối với hầu hết chúng ta ở đây (bao gồm cả OP). Câu hỏi là "điều này có vi phạm OCP không?" Vì vậy, tôi không thấy câu trả lời của bạn đề cập đến câu hỏi này như thế nào.
Doc Brown

1

Nếu bạn cần sửa đổi lớp để thay đổi giá trị thuế, thì thiết kế của nó thực sự vi phạm OCP. Thiết kế phù hợp, cho những gì bạn đã mô tả cho đến nay, là dành cho lớp máy tính lấy giá trị thuế làm tham số.

Nếu lớp của bạn được kích hoạt (có nghĩa là nó không phải là lớp tĩnh), bằng cách tạo thuộc tính lớp biến thuế, có giá trị được đưa vào thông qua hàm tạo, bạn cũng sẽ cải thiện sự gắn kết của lớp.

Nói tóm lại, thiết kế hiện tại của bạn làm cho lớp của bạn phụ thuộc vào một giá trị không đổi thực sự không phải là hằng số (xác định hằng số là một giá trị sẽ không bao giờ thay đổi cho dù thế nào, như giá trị PI). Nó vi phạm OCP. Thay đổi thiết kế để nhận giá trị thuế dưới dạng đối số của hàm tạo.


0

Hoàn toàn đồng ý với @Becuzz và tôi chỉ muốn tóm tắt điều này: OCP là về việc tìm kiếm các khái niệm trừu tượng được sử dụng lại (do đó, hữu ích) được đưa vào một lớp. Vì vậy, hành vi của lớp được sửa đổi không phải bằng cách thay đổi mã của nó, mà bằng cách cung cấp cho nó các triển khai khác nhau. Điều này được thể hiện rõ ràng trong cuốn sách " Phát triển phần mềm, nguyên tắc, mô hình và thực tiễn " của Robert Martin , kiểm tra chương tương ứng "Nguyên tắc đóng mở", "Trừu tượng là chìa khóa". Nó làm rõ một quan niệm sai lầm khác rằng hành vi chỉ có thể được sửa đổi với sự kế thừa. Chính Bertrand Meyer đã đề xuất rằng vào năm 1988 trong cuốn sách của mình, đối tượng xây dựng phần mềm hướng đối tượng , chứ không phải Robert Martin.


-2

Cách tôi nhìn thấy nó không vi phạm nguyên tắc đóng mở. Tuy nhiên, thực tế là thứ gì đó nhất định thay đổi theo thời gian (chẳng hạn như phần trăm thuế) là một hằng số thiết kế: bạn không nên thay đổi giá trị của hằng số mà là cách bạn xử lý phần trăm thuế. Đây phải là một số loại cài đặt có thể được sửa đổi mà không biên dịch lại toàn bộ.


"Lỗ hổng thiết kế" là nó vi phạm nguyên tắc đóng mở khi bạn cần biên dịch lại mã để thay đổi hằng số?
Erdrik Ironrose
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.