Mã lặp lại so với phương pháp đa trách nhiệm


11

Tôi cố gắng tuân theo Nguyên tắc Trách nhiệm duy nhất (SRP) và cũng để bỏ qua các Lặp lại mã. Tuy nhiên, thường có những nơi có sự lặp lại mã không gì khác hơn là các khối mã yêu cầu có khả năng trích xuất chúng thành ít nhất là phương thức có tên đầy đủ:

DoAction1();
DoAction2();

if (value)
    DoAction3();

DoAction4();

Cách tốt nhất để trích xuất mã đó vào một phương thức và làm thế nào để đặt tên cho nó?


1
Tại sao chúng chống lại việc được trích xuất thành một phương pháp có ý nghĩa khác nhau?
Chandranshu

Tất cả các hành động làm một cái gì đó không liên quan. Tôi sẽ phải viết : void MethodThatDoAction1ThenAction2AndAction3IfValueAndThenAction4(). Tôi thà thấy ý nghĩa hơn trong : CodeBlock1().
yBee

4
Vậy thì đó chỉ là một câu hỏi về cách đặt tên đúng cho phương pháp trích xuất, phải không? Tôi e rằng không có giải pháp chung và bạn sẽ phải làm điều này trong từng trường hợp. Nếu bạn đang lặp lại cùng một đoạn mã chính xác này ở hơn 1 địa điểm, chắc chắn sẽ có ý nghĩa đối với hành động của bạn và bạn cần phải tìm kiếm (có thể thảo luận) để tìm ra ý nghĩa đó và đặt tên cho nó.
Chandranshu

1
Nếu đó là bất kỳ sự an ủi nào, người chiến thắng Mùa xuân cho các tên lớp dài AbstractInterruptibleBatchPreparedStatementSetterchỉ nhỏ hơn một chút so với phương pháp của bạn.
Chandranshu

1
@Chandranshu Tôi tin rằng (các) bình luận của bạn sẽ hoạt động tốt như một câu trả lời cho câu hỏi này.
Simon Forsberg

Câu trả lời:


13

Tôi nghĩ đó chỉ là một câu hỏi về cách đặt tên đúng cho phương pháp trích xuất. Tôi e rằng không có giải pháp chung và bạn sẽ phải làm điều này trong từng trường hợp. Nếu bạn đang lặp lại cùng một đoạn mã chính xác này ở hơn 1 địa điểm, chắc chắn sẽ có ý nghĩa đối với hành động của bạn và bạn cần phải tìm kiếm (có thể thảo luận) để tìm ra ý nghĩa đó và đặt tên cho nó.

Nếu đó là bất kỳ sự an ủi nào, người chiến thắng mùa xuân cho các tên lớp dài là AbstractInterruptibleBatchPreparedStatementSetter49 ký tự.


11

Trên thực tế, bạn đang phải chịu đựng nhiệm vụ khó khăn hàng đầu của một lập trình viên - Đặt tên cho mọi thứ . Xin lỗi vì một câu trả lời thiếu chín chắn như vậy nhưng tôi không thể cưỡng lại. Bạn có thể thấy rằng nhiều người mắc phải điều này , thậm chí trên internet bạn có thể tìm thấy loại bài luận này .

Bây giờ nếu mã lặp đi lặp lại của bạn là tất cả cùng nhau dẫn đến một công việc và các phương thức đó không được sử dụng bởi các phương thức khác thì chúng chỉ đơn giản là phương thức Trợ giúp và sau đó phương thức kết quả có thể được đặt tên là doXXXhoặc makeXXX... Tôi nghĩ rằng bạn có được điểm.

Như Chandranshu đã nói "Nếu bạn đang lặp lại ý nghĩa [...] này và đặt tên cho nó." là đến điểm và thích hợp.

nhập mô tả hình ảnh ở đây

Hình ảnh lịch sự: CodeChef Trang Facebook Ảnh


2

Tôi nghĩ rằng bạn đang thực hiện nguyên tắc lặp lại mã quá xa. Hãy nghĩ về điểm tránh Mã lặp lại. Vấn đề là giảm số lượng mã phải được kiểm tra khi có sự thay đổi trong logic và tăng mức độ hiểu bằng cách bao gồm các khối có mục đích rõ ràng tương tự.

Nhược điểm của việc bao thanh toán để tránh Lặp lại là nếu một trong các khối được chia sẻ phải thay đổi, bây giờ bạn cần kế thừa thậm chí phức tạp hơn hoặc một số chuyển đổi giữa thực hiện tiêu chuẩn và không chuẩn.

Vì vậy, cẩn thận cân nhắc khả năng logic cho ngay cả một trong những khối này thay đổi mà không có các khối khác chống lại lợi ích hiểu được bằng cách bao gồm tính phổ biến này. Nếu một triển khai có thể tách ra khỏi các thực thi khác, bạn rất có thể tốt hơn là chỉ cần lặp lại mã.

Trong khi duy trì mã lặp lại này, vì nó trở nên phức tạp hơn và miền vấn đề của bạn trở nên rõ ràng hơn, sau đó bạn có thể thấy nó phù hợp hơn với yếu tố lặp lại, bây giờ phức tạp hơn, nhưng cũng được xác định rõ hơn.

Tôi thường cố gắng duy trì cùng một trình soạn thảo văn bản trong một thời gian cho đến khi tôi có thể xem liệu thứ gì đó có vẻ lặp đi lặp lại có đáng để bao thanh toán hay không. Tôi chỉ giữ lại sự lặp lại, nhưng tôi để mắt đến tương lai của khối đó bằng cách giữ cho nó dễ hiểu về mặt văn bản để phù hợp sau này.

Rất nhiều thời gian, cùng một tính năng và bao thanh toán có thể, bắt đầu tiêu tan, như các quy tắc kinh doanh thực tế, thất thường, và phụ thuộc cao, thường là logic tùy tiện; như xử lý các vấn đề kỳ lạ của một số triển khai cơ sở dữ liệu phổ biến (ANSI_NULLS hoặc một số thứ như vậy xuất hiện trong tâm trí) được thêm vào; buộc những gì có vẻ như là một logic thuần túy thành một mớ hỗn độn, cố gắng đưa ra logic quyết định hợp lý, có thể phòng thủ khi đối mặt với sự lộn xộn của tình trạng của ngành công nghiệp.

Dường như với tôi rằng nếu mọi người cố gắng tìm ra yếu tố bạn đang cố gắng, chúng tôi sẽ có toàn bộ thư viện các cấu trúc vô giá trị như Do1Then2 If2False Do1 IfTrueDo2.

Điều phức tạp hơn và rõ ràng hơn là khối sẽ không thay đổi để đảm bảo bao thanh toán.

Đó là phần mềm . Bạn có thể quay lại và chỉnh sửa một vài khối giống nhau ngay bây giờ. Sẽ mất 5 phút. Và bạn có thể tiết kiệm hàng giờ lãng phí bao thanh toán, và sau đó hàng giờ lãng phí thừa kế và chuyển đổi phát triển, bằng cách bỏ nó và đảm bảo bạn có một bàn phím chống RSI tốt.


Tôi thích phần trích ra bản chất của sự lặp lại mã: để giảm số lượng mã phải kiểm tra khi có sự thay đổi trong logic
yBee

1

Nếu bạn thực sự tuân theo Nguyên tắc Trách nhiệm Đơn lẻ, thì khối mã này phải có một số mục đích cụ thể, phải không? Nếu không, các phương thức này sẽ được trong các lớp riêng biệt.

Vì vậy, mục đích của khối mã này là gì? Xác định điều đó và bạn nên có thể đưa ra một cái tên.

Nếu bạn vẫn không thể tìm ra tên cho điều này, thì có lẽ các phương thức này hoàn toàn không thuộc về nhau. Tức là lớp / khối mã này có nhiều hơn một trách nhiệm. Trong trường hợp đó, tái cấu trúc để phân chia các nhiệm vụ có thể tiết lộ tên tiết lộ mục đích tốt hơn.


1

Tôi đã có một tình huống có thể tương tự như của bạn:

Có một lớp xác định chức năng của đối tượng mà nó đại diện:

class Functionality
{
protected:
void functionA();
void functionB();
...
void functionZ();
}

Sau đó, có một lớp xác định quy trình công việc cho các hoạt động cấp cao mà đối tượng thực hiện:

class Workflows: private Functionality
{
    void WorkflowA()
    {
        functionA();

        if (m_bValue) {
            functionB();
        }

        functionC();
    }
    ...
    void WorkflowB();
}

Nếu bạn đang ở trong một tình huống tương tự, thì hãy xác định những gì các lớp của bạn đại diện (trong trường hợp này là chức năng / quy trình công việc) và sau đó đặt tên cho các phương thức cho phù hợp.

Tuyên bố từ chối trách nhiệm: Các tên lớp được sử dụng trong ví dụ này rất không chính xác, nhưng các tên phương thức đưa ra một đầu mối. Thận trọng khuyên.

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.