Làm thế nào để xác định nếu một lớp đáp ứng nguyên tắc trách nhiệm duy nhất?


34

Nguyên tắc trách nhiệm duy nhất dựa trên nguyên tắc gắn kết cao. Sự khác biệt giữa hai là một lớp có tính gắn kết cao có một tập hợp các trách nhiệm có liên quan chặt chẽ với nhau, trong khi các lớp tuân thủ SRP chỉ có một trách nhiệm.

Nhưng làm thế nào để chúng ta xác định liệu một lớp cụ thể có tập hợp các trách nhiệm hay không và do đó chỉ có tính gắn kết cao, hoặc liệu nó chỉ có một trách nhiệm và do đó tuân thủ SRP? Nói cách khác, không phải nó ít nhiều chủ quan, vì một số người có thể coi một lớp rất chi tiết (và như vậy sẽ tin rằng lớp tuân thủ SRP), trong khi những người khác có thể coi nó không đủ chi tiết?



Câu trả lời:


21

Tại sao có, nó rất chủ quan, và nó là chủ đề của nhiều cuộc tranh luận sôi nổi, đỏ mặt mà các lập trình viên tham gia.

Không thực sự có một câu trả lời nào, và câu trả lời có thể thay đổi khi phần mềm của bạn trở nên phức tạp hơn. Những gì đã từng là một nhiệm vụ được xác định rõ ràng cuối cùng có thể trở thành nhiều nhiệm vụ được xác định kém. Đó luôn là sự cọ xát. Làm thế nào để bạn chọn cách thích hợp để phân chia một chương trình thành các nhiệm vụ?

Về lời khuyên duy nhất tôi có thể đưa ra là: hãy sử dụng phán quyết tốt nhất của bạn (và đồng nghiệp của bạn). Và hãy nhớ rằng những sai lầm có thể (thường) được sửa chữa nếu bạn bắt kịp chúng sớm.


Tôi ước rằng khoa học máy tính giống như khoa học thực tế hơn. Chủ quan không có chỗ trong khoa học thực sự. Mặc dù các nguyên tắc RẮN vẫn ổn theo quyền riêng của chúng, chúng cần được lặp đi lặp lại để giảm thiểu tính chủ quan và tối đa hóa tính khách quan. Điều đó chưa xảy ra, điều này khiến tôi đặt câu hỏi về tính hợp pháp của họ trong thế giới thực.
DarkNeuron

13

Bob Martin (Chú Bob), người khởi nguồn các nguyên tắc RẮN trong đó SRP là người đầu tiên, nói về điều này (tôi đang diễn giải, không thể nhớ lại các từ thực tế):

Một lớp chỉ nên có một lý do để thay đổi

Nếu nó có nhiều hơn một lý do, nó không tuân thủ SRP.


14
Đó chỉ là lặp lại định nghĩa thực sự, nhưng thực sự tuân thủ srp vẫn còn khá chủ quan.
Andy

7

Tôi có thể cung cấp cho bạn một số quy tắc của ngón tay cái.

  • Làm thế nào dễ dàng để đặt tên lớp? Nếu một lớp khó đặt tên, có lẽ nó đang làm quá nhiều.
  • Lớp học có bao nhiêu phương thức công khai? 7 +/- 2 là một quy tắc tốt. Nếu lớp có nhiều hơn thế, bạn nên nghĩ về việc chia nó thành nhiều lớp.
  • Có các nhóm phương pháp công khai gắn kết được sử dụng trong các bối cảnh riêng biệt?
  • Có bao nhiêu phương thức riêng tư hoặc thành viên dữ liệu? Nếu lớp có cấu trúc bên trong phức tạp, có lẽ bạn nên cấu trúc lại nó để các phần bên trong được đóng gói thành các lớp nhỏ hơn riêng biệt.
  • Và quy tắc đơn giản nhất: lớp học lớn như thế nào? Nếu bạn có tệp tiêu đề C ++ chứa một lớp duy nhất dài hơn vài trăm dòng, có lẽ bạn nên tách nó ra.

2
Về điểm thứ hai của bạn, xem uxmyths.com/post/931925744/ Kẻ
Cameron Martin

7
Không đồng ý mạnh mẽ về 7 +/- 2 - nguyên tắc trách nhiệm duy nhất là về sự gắn kết ngữ nghĩa, không phải về các con số tùy ý.
JacquesB

1
Quy tắc của ngón tay cái không cần bằng chứng khoa học độc lập. Phương pháp khoa học hiện đại đã có hàng thế kỷ, kiến ​​trúc và kỹ thuật là thiên niên kỷ. Quy tắc ngón tay cái cho các phương thức công khai là "vài" và không có tham số nào là "một vài". Trong các tin tức khác, mặc dù một số bức vẽ của trẻ em cho thấy cánh tay của mọi người không thoát ra khỏi đầu [cần dẫn nguồn].
abuzittin gillifirca

@CameronMartin Tùy thuộc vào thiết lập của bạn, giao diện cho một lớp có thể có hoặc không có sẵn để bạn đọc. Tìm kiếm một giao diện người dùng hầu như không giống như viết mã - nếu tôi phải tham khảo tài liệu mỗi phút, thì ít nhất, tôi sẽ nhân đôi thời gian để thực hiện bất kỳ công việc thực tế nào.
Rõ ràng hơn

6

Nguyên tắc trách nhiệm duy nhất nói rằng mỗi mô-đun phần mềm chỉ nên có một lý do để thay đổi. Trên một bài báo gần đây, chú Bob đã giải thích "lý do để thay đổi",

Tuy nhiên, khi bạn nghĩ về nguyên tắc này, hãy nhớ rằng lý do để thay đổi là con người. Đó là những người yêu cầu thay đổi. Và bạn không muốn nhầm lẫn những người đó hoặc chính mình bằng cách trộn lẫn mã mà nhiều người khác nhau quan tâm vì những lý do khác nhau.

Ông giải thích thêm về khái niệm này với một ví dụ TẠI ĐÂY .


Đó là một bài viết tuyệt vời, được viết bởi chính người đàn ông.
MrDustpan

4

Để trả lời điều này, hãy lùi lại một bước và xem xét ý định của nguyên tắc trách nhiệm duy nhất. Tại sao nó là một nguyên tắc thiết kế được đề nghị ở nơi đầu tiên?

Mục đích của nguyên tắc là "ngăn chặn" cơ sở mã, do đó mã liên quan đến một "trách nhiệm" duy nhất được tách ra trong một đơn vị. Điều này giúp việc tìm và hiểu mã dễ dàng hơn và quan trọng hơn, điều đó có nghĩa là những thay đổi đối với "trách nhiệm" sẽ chỉ ảnh hưởng đến một đơn vị mã.

Điều bạn hoàn toàn không bao giờ muốn trong một hệ thống là khi một cơ hội nhỏ khiến một số phần khác dường như không liên quan đến mã bị lỗi hoặc thay đổi hành vi. SRP giúp cách ly các lỗi và thay đổi.

Vì vậy, những gì nó là một "trách nhiệm" sau đó? Đó là một cái gì đó có thể thay đổi có thể hình dung độc lập với những thay đổi khác. Giả sử bạn có chương trình có thể lưu một số cài đặt vào tệp cấu hình XML và có thể đọc lại chúng từ tệp. Đây có phải là một trách nhiệm duy nhất, hay là "tải" và "lưu" hai trách nhiệm khác nhau? Bất kỳ loại thay đổi nào đối với định dạng hoặc cấu trúc tệp sẽ yêu cầu thay đổi cả tải và lưu logic. Do đó, một trách nhiệm duy nhất cần được đại diện bởi một lớp duy nhất. Bây giờ hãy xem xét một ứng dụng có thể xuất một số dữ liệu ở định dạng CVS, Excel và XML. Trong trường hợp này, thật dễ dàng để tưởng tượng rằng một định dạng có thể thay đổi mà không ảnh hưởng đến định dạng khác. Nếu bạn quyết định thay đổi dấu phân cách ở định dạng CVS, nó sẽ không ảnh hưởng đến đầu ra Excel.


2

OO nói rằng các lớp là một nhóm dữ liệu một chức năng. Định nghĩa này để lại nhiều chỗ cho sự giải thích chủ quan.

Chúng tôi biết rằng các lớp nên được xác định rõ ràng và dễ dàng. Nhưng, để định nghĩa một lớp như vậy, chúng ta phải có một khái niệm rõ ràng về cách một lớp phù hợp với thiết kế tổng thể. Nếu không có các yêu cầu về loại thác nước, một cách nghịch lý, được coi là một mô hình chống ... điều này rất khó đạt được.

Chúng ta có thể thực hiện một thiết kế lớp với một kiến ​​trúc hoạt động trong hầu hết các trường hợp, như MVC. Trong các ứng dụng MVC, chúng tôi chỉ giả sử có dữ liệu, giao diện người dùng và yêu cầu hai người phải giao tiếp.

Với kiến ​​trúc cơ bản, việc xác định các trường hợp quy tắc trách nhiệm đơn lẻ bị phá vỡ sẽ dễ dàng hơn. EG Chuyển một thể hiện của Điều khiển người dùng sang Phương thức.


1

Chỉ để thảo luận, tôi sẽ mở ra một lớp học từ JUCE có tên là AudioSampleBuffer . Bây giờ lớp này tồn tại để giữ một đoạn (hoặc có lẽ là một đoạn khá dài) của âm thanh. Nó biết số lượng kênh, số lượng mẫu (trên mỗi kênh), dường như được cam kết với float float 32 bit thay vì có biểu diễn số hoặc biến đổi số (nhưng đó không phải là vấn đề với tôi). Có các hàm thành viên cho phép bạn lấy numChannels hoặc numSamples và con trỏ tới bất kỳ kênh cụ thể nào. Bạn có thể làm cho AudioSampleBuffer dài hơn hoặc ngắn hơn. Tôi đoán rằng phần đệm trước không đệm trong khi phần sau cắt ngắn.

Có một vài thành viên riêng của lớp này được sử dụng để phân bổ không gian trong đống đặc biệt mà JUCE sử dụng.

Nhưng đây là thứ mà AudioSampleBuffer đang thiếu (và tôi đã có vài cuộc thảo luận với Jules về nó): một thành viên được gọi SampleRate. Làm thế nào nó có thể thiếu nó?

Trách nhiệm duy nhất mà AudioSampleBuffer cần thực hiện là thể hiện đầy đủ âm thanh vật lý mà người ta nghe thấy các mẫu của nó đại diện. Khi bạn nhập AudioSampleBuffer từ thứ gì đó đọc tệp âm thanh hoặc từ luồng, có một tham số bổ sung mà bạn phải nhận và chuyển nó cùng với AudioSampleBuffer cho các phương thức xử lý (giả sử đó là bộ lọc) cần biết tốc độ mẫu hoặc, cuối cùng, đến một phương pháp mà đóng bộ đệm ra được lắng nghe (hoặc suối nó một nơi nào đó khác). Bất cứ điều gì.

Nhưng những gì bạn phải làm là tiếp tục vượt qua SampleRate này, vốn có với âm thanh cụ thể sống trong AudioSampleBuffer, ở khắp mọi nơi. Tôi đã thấy mã trong đó một hằng số 44100.0f được truyền cho một hàm, bởi vì lập trình viên dường như không biết phải làm gì khác.

Đây là một ví dụ về việc không đáp ứng trách nhiệm duy nhất của nó.


1

Một cách cụ thể có thể được thực hiện, dựa trên những gì bạn đã nói - rằng sự gắn kết cao dẫn đến trách nhiệm duy nhất bạn có thể đo lường sự gắn kết. Một lớp gắn kết tối đa có tất cả các trường được sử dụng trong tất cả các phương thức. Mặc dù một lớp gắn kết tối đa không phải lúc nào cũng có thể và cũng không mong muốn có nó vẫn tốt nhất để đạt được điều này. Có mục tiêu thiết kế lớp này, thật dễ dàng để suy luận rằng lớp của bạn không thể có nhiều phương thức hoặc trường (một số nói nhiều nhất là 7).

Một cách khác là từ những điều cơ bản thuần túy của OOP - mô hình sau các đối tượng thực. Nó dễ dàng hơn nhiều để thấy trách nhiệm của các đối tượng thực sự. Tuy nhiên, nếu đối tượng thực quá phức tạp, hãy chia nó thành nhiều đối tượng khác nhau, mỗi đối tượng có trách nhiệm riêng.

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.