Nguồn gốc của một phương thức nên trả về một giá trị hoặc có tác dụng phụ, nhưng không phải cả hai


12

Tôi đã đọc một lần rằng một phương thức nên có giá trị trả về (và được minh bạch tham chiếu) hoặc có (các) hiệu ứng phụ, nhưng không phải cả hai. Tôi không thể tìm thấy bất kỳ tài liệu tham khảo nào cho quy tắc này, nhưng muốn tìm hiểu thêm về nó.

Nguồn gốc của lời khuyên này là gì? Trong số những người hoặc cộng đồng đã làm nó phát sinh?

Tín dụng bổ sung: lợi ích được yêu cầu của việc làm theo lời khuyên này là gì?


1
@gnat Vâng, chủ yếu là về lịch sử. Tôi sợ rằng phần tín dụng phụ quá chủ quan để tự đứng vững và lịch sử đó có cơ hội tốt hơn để thoát khỏi sự đóng cửa. Tôi sẽ thêm thẻ.
Wayne Conrad

một số câu trả lời khiến tôi băn khoăn liệu bạn có hỏi về lợi ích đã được một tác giả của lời khuyên này yêu cầu hoặc cho một danh sách tất cả các lợi ích có thể yêu cầu không?
gnat

@gnat Tôi hỏi về lợi ích mà tác giả đã yêu cầu (một lần nữa, vì sợ đóng cửa), nhưng tôi chắc chắn không bận tâm đến những lý do chồng chất - họ đang trả lời câu hỏi tôi thực sự muốn hỏi. Nếu tôi loại bỏ "yêu cầu" khỏi câu hỏi của mình, đưa ra các câu trả lời theo chủ đề, liệu điều đó có đẩy câu hỏi đi quá xa vào chủ quan không?
Wayne Conrad

"Lý do chồng chất" có khả năng đẩy câu hỏi được đóng lại vì quá rộng . Nếu bạn thích nó "ở lại bên mở", tôi nghĩ sẽ an toàn hơn nếu thu hẹp nó xuống để hưởng lợi mà tác giả đã tuyên bố
gnat

Một lợi ích là nếu bạn được trả theo khối lượng mã, điều này sẽ tạo thêm. "doS Something; GetResultOfS Something; HandleErrorsFromS Something;"

Câu trả lời:


13

Theo Greg Young, ý tưởng này bắt nguồn từ Bertrand Meyer : Phân tách truy vấn lệnh .

Nó tuyên bố rằng mọi phương thức nên là một lệnh thực hiện một hành động hoặc một truy vấn trả về dữ liệu cho người gọi, nhưng không phải cả hai. Nói cách khác, Đặt câu hỏi không nên thay đổi câu trả lời . 1 Chính thức hơn, các phương thức chỉ trả về một giá trị nếu chúng trong suốt được tham chiếu và do đó không có tác dụng phụ.

1: Eiffel: một ngôn ngữ cho slide kỹ thuật phần mềm 43-48

Trong Thiết kế hướng tên miền, điều này tương tự như Phân tách / Phân tách đọc-truy vấn đọc lệnh (CQRS), như được đặt tên bởi Greg Young.

Greg Young đã lấy ý tưởng về CQS từ Bertrand để đặt tên cho CQRS như được đề cập bởi Martin Fowler trong bài viết về CQRS này

Những lợi ích

  • Phần Đọc (Truy vấn) có thể được thu nhỏ / điều chỉnh khác với phần Viết (lệnh). Việc tách hai cái sẽ ngăn không cho nhau cản trở nhau khi tối ưu hóa / hiệu suất là chìa khóa.

Đọc bài viết trong liên kết Martin Fowler để biết thêm.


1
Đương nhiên, trong nhiều tình huống tạo ra một kết quả hữu ích và thực hiện một số sửa đổi cùng một lúc không tốn kém hơn so với việc làm riêng hai công việc khó hơn.
Ded

1
@Ded repeatator Một ví dụ sáo rỗng là InterlockedCompareExchange?

1
Tuy nhiên, lời khuyên này rõ ràng không áp dụng khi trả về là một số thông tin về những gì đã được thực hiện trong lệnh - tuy nhiên - một phương pháp để loại bỏ các hàng khỏi bộ dữ liệu có thể thay đổi khá nhiều trạng thái của bộ dữ liệu, loại bỏ các hàng được chỉ định theo một tiêu chí nhất định và sau đó trả về số lượng hàng bị xóa hoặc thậm chí một danh sách với các hàng đã nói.
T. Sar - Tái lập Monica

4

Tôi không biết nó đến từ đâu, nhưng đó là lời khuyên tốt và khá dễ hiểu.

Bất kỳ chương trình được thiết kế hoàn toàn sẽ được chia thành nhiều phần khác nhau, được kết hợp và sáng tác theo nhiều cách khác nhau. Càng khó để lý giải về bất kỳ phần cụ thể nào, thì càng khó để đảm bảo rằng chương trình của bạn sẽ phản ứng theo cách có thể dự đoán được.

Cô lập các bộ phận tạo ra tác dụng phụ làm cho phần còn lại dễ dàng lý luận, kiểm tra và gỡ lỗi. Giảm số lượng tác dụng phụ trong mỗi phần tạo ra hiệu ứng phụ sẽ giúp phần đó dễ dàng hoạt động hơn theo cách tương tự.

Nếu bạn phân tách nó hơn nữa, giá trị trả về là một hiệu ứng. Tác dụng phụ là một hiệu ứng. Một hàm chỉ nên tạo ra 1 hiệu ứng (nếu có thể) bởi vì số lượng đầu vào và hiệu ứng của hàm càng nhiều thì càng khó khăn trong việc suy luận về những gì nó thực sự làm.


điều này thậm chí không cố gắng giải quyết câu hỏi đã hỏi, xem Cách trả lời
gnat

@gnat Câu hỏi của tôi có hai phần: Câu hỏi chính ("ai") và tín dụng phụ ("tại sao). Đây không phải là phần tín dụng bổ sung phải không?
Wayne Conrad

theo cách đọc của tôi (" lợi ích được yêu cầu "), tại sao phần dự kiến ​​sẽ là một trong những đề xuất của tác giả của trích dẫn. Câu hỏi dường như không yêu cầu danh sách tất cả các lợi ích có thể có
gnat

2
@gnat Tôi hiểu câu hỏi là một nỗ lực để hiểu lời khuyên này, cả lý do đằng sau nó cũng như bối cảnh mà nó được đưa ra. Tôi không tin rằng việc giải quyết một phần câu hỏi là không phù hợp.
Morgen

1

Tín dụng bổ sung: lợi ích được tuyên bố ban đầu của việc làm theo lời khuyên này là gì?

Một trong những lợi ích của việc tách giá trị trả về khỏi các tác dụng phụ là nó loại bỏ một vấn đề tiềm ẩn có thể gây ra do đánh giá ngắn mạch .

bool FooWithSideEffect() {
    // do query
    // do side effect
    return resultOfQuery;
}

bool BarWithSideEffect() {
    // do query
    // do side effect
    return resultOfQuery;
}

void BadShortCircuitEvaluation()
{
    // the programmer's intent is to have side effects of both functions
    if (FooWithSideEffect() && BarWithSideEffect() ) {
        // do something
    }

    // in case FooWithSideEffect() returns true, 
    // then BarWithSideEffect() is not called at all
    // because of short-circuit evaluation
}

Đây có phải là một lợi ích được tuyên bố bởi tác giả của lời khuyên ?
gnat

@gnat Mình có hỗn hợp lịch sử và thực tế, mình sợ.
Nick Alexeev

1
Nhận xét và mã không khớp, BarWithSideEffects không được gọi nếu FooWithSideEffects trả về false
jk.
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.