Pochodzenie „metoda powinna zwrócić wartość lub mieć skutki uboczne, ale nie jedno i drugie”


12

Przeczytałem kiedyś, że metoda powinna albo mieć wartość zwracaną (i być referencyjnie przezroczysta), albo mieć skutki uboczne, ale nie jedno i drugie. Nie mogę znaleźć żadnych odniesień do tej reguły, ale chcę dowiedzieć się więcej na jej temat.

Jakie jest pochodzenie tej porady? Z jakiej osoby lub społeczności powstało?

Dodatkowy kredyt: Jaka jest domniemana korzyść wynikająca z zastosowania tej porady?


1
@gnat Tak, chodzi przede wszystkim o historię. Obawiałem się, że dodatkowa część kredytu była zbyt subiektywna, by stać sama, i że historia ma większą szansę na uniknięcie zamknięcia. Dodam tag.
— Wayne Conrad

niektóre odpowiedzi, które się na nim nakładają, sprawiły, że zastanawiałem się, czy pytasz o zasiłek, o który wystąpił autor tej porady, czy o listę wszystkich świadczeń, o które w ogóle można się ubiegać?
— komara

@gnat Pytam o korzyść zgłoszoną przez autora (ponownie, obawiając się zamknięcia), ale na pewno nie mam nic przeciwko przyczynom nakładania się - odpowiadają na pytanie, które naprawdę chciałem zadać. Gdybym usunął z mojego pytania „twierdził”, stawiając stosowe odpowiedzi na temat, czy przesuwałoby to pytanie zbyt głęboko w subiektywne?
— Wayne Conrad,

„powody nakładania” prawdopodobnie spowodują, że pytanie zostanie zamknięte jako zbyt ogólne . Jeśli wolisz, aby „pozostać na otwartej stronie”, myślę, że bezpieczniej byłoby zawęzić go do korzyści, o które wnioskował autor
— gnat

Jedną z korzyści jest to, że jeśli płacisz według objętości kodu, to daje dodatkowe. „doSomething; GetResultOfSomething; HandleErrorsFromSomething;”
— uі

Odpowiedzi:


13

Według Grega Younga pomysł ten wywodzi się z Bertrand Meyer : rozdzielenie poleceń i zapytań .

Stwierdza, że ​​każda metoda powinna być albo komendą wykonującą akcję, albo zapytaniem zwracającym dane do programu wywołującego, ale nie jednym i drugim. Innymi słowy, zadanie pytania nie powinno zmienić odpowiedzi . 1 Bardziej formalnie, metody powinny zwracać wartość tylko wtedy, gdy są referencyjnie przejrzyste, a zatem nie wywołują skutków ubocznych.

1: Eiffel: język slajdu inżynierii oprogramowania 43-48

W projektowaniu opartym na domenie jest to podobne do rozdzielania / segregacji poleceń i zapytań (CQRS), jak nazwał to Greg Young.

Greg Young wpadł na pomysł CQS od Bertrand, aby nazwać CQRS, jak wspomniał Martin Fowler w tym artykule CQRS

Korzyści

  • Część Read (Query) można skalować / modyfikować inaczej niż część Write (command). Rozdzielenie tych dwóch zapobiegnie wzajemnemu przeszkadzaniu, gdy kluczowa jest optymalizacja / wydajność.

Przeczytaj artykuł w linku Martina Fowlera, aby uzyskać więcej.


1
Oczywiście w wielu sytuacjach generowanie użytecznego wyniku i dokonywanie modyfikacji w tym samym czasie nie jest droższe niż robienie trudniejszego z nich osobno.
— Deduplicator

1
@Deduplicator Przykładem stereotypu jest InterlockedCompareExchange?
— uі

1
Ta rada oczywiście nie ma zastosowania, gdy zwracana jest pewna informacja o tym, co zostało zrobione w poleceniu, jednak metoda usuwania wierszy z zestawu danych może zasadniczo zmienić stan zestawu danych, usuwając wskazane wiersze zgodnie z podanymi kryteriami, i następnie zwróć liczbę usuniętych wierszy lub nawet listę ze wspomnianymi wierszami.
— T. Sar

4

Nie wiem, skąd pochodzi, ale jest to dobra rada i dość prosta do zrozumienia.

Każdy rozsądnie zaprojektowany program zostanie podzielony na różne części, połączone i skomponowane na różne sposoby. Im trudniej jest zrozumieć, co robi konkretna część, tym trudniej jest upewnić się, że Twój program zareaguje w przewidywalny sposób.

Izolowanie części, które wywołują skutki uboczne, ułatwia reszcie racjonalizację, testowanie i debugowanie. Zmniejszenie liczby efektów ubocznych w każdej części, która generuje efekt uboczny, ułatwi pracę z tą częścią w ten sam sposób.

Jeśli rozłożysz go jeszcze bardziej, wartość zwrotna jest efektem. Skutki uboczne są efektem. Funkcja powinna dawać tylko 1 efekt (jeśli to możliwe), ponieważ im większa liczba danych wejściowych i efektów, tym większa trudność w uzasadnieniu tego, co faktycznie robi.


to nawet nie próbuje odpowiedzieć na zadane pytanie, patrz Jak odpowiedzieć
— gnat

@gnat moje pytanie przyszedł w dwóch częściach: Pytanie główne ( „kto”), a dodatkowy kredyt ( "dlaczego) nie ten adres dodatkową część kredytowej.?
— Wayne Conrada

według mojej lektury („ domniemana korzyść”) oczekuje się, że część zostanie zaproponowana przez autora cytatu. Wydaje się, że pytanie nie wymaga podania listy wszystkich możliwych korzyści
— komara

2
@gnat Zrozumiałem pytanie jako próbę zrozumienia tej rady, zarówno jej przyczyny, jak i kontekstu, w którym została podana. Nie sądzę, aby niewłaściwe było zajmowanie się tylko częścią pytania.
— Morgen,

1

Dodatkowy kredyt: Jaka jest pierwotnie deklarowana korzyść wynikająca z zastosowania tej porady?

Jedną z korzyści oddzielenia wartości zwrotu od skutków ubocznych jest to, że usuwa potencjalny problem, który może być spowodowany oceną zwarcia .

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
}

czy jest to korzyść wnioskowana przez autora porady ?
— komara

@gnat Mam mieszane historyczne i praktyczne, obawiam się.
— Nick Alexeev

1
komentarz i kod nie są zgodne, BarWithSideEffects nie jest wywoływane, jeśli FooWithSideEffects zwraca false
— jk.
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.