Ursprung von "Eine Methode sollte einen Wert zurückgeben oder Nebenwirkungen haben, aber nicht beides"


12

Ich habe einmal gelesen, dass eine Methode entweder einen Rückgabewert haben sollte (und referenziell transparent sein sollte) oder Nebenwirkungen haben sollte, aber nicht beides. Ich kann keine Verweise auf diese Regel finden, möchte aber mehr darüber erfahren.

Woher stammt dieser Rat? Aus welcher Person oder Gemeinschaft ist es entstanden?

Zusätzliche Gutschrift: Welche Vorteile ergeben sich aus der Befolgung dieses Hinweises?


1
@gnat Ja, es geht in erster Linie um Geschichte. Ich befürchtete, dass der zusätzliche Kreditanteil zu subjektiv war, um für sich allein zu stehen, und dass die Geschichte eine bessere Chance hatte, der Schließung zu entgehen. Ich werde den Tag hinzufügen.
Wayne Conrad

Einige der Antworten, die sich häufen, haben mich gefragt, ob Sie nach den Vorteilen fragen, die von einem Autor dieses Ratschlags in Anspruch genommen wurden, oder nach einer Liste aller Vorteile, die überhaupt in Anspruch genommen werden können.
gnat

@gnat Ich frage nach dem Vorteil, den der Autor in Anspruch genommen hat (wieder aus Angst vor Schließung), aber die häufigen Gründe stören mich nicht - sie beantworten die Frage, die ich eigentlich stellen wollte . Wenn ich das "Behauptete" aus meiner Frage entfernen und die Antworten thematisch zusammenfassen würde, würde dies die Frage zu weit in den subjektiven Bereich treiben?
Wayne Conrad

"Pile-On-Gründe" dürften dazu führen, dass die Frage als zu umfassend abgeschlossen wird . Wenn Sie es vorziehen, "auf der offenen Seite zu bleiben", halte ich es für sicherer, sie einzugrenzen, um den vom Autor behaupteten Nutzen zu
erzielen

Ein Vorteil ist, dass Sie bei einer Zahlung nach Codevolumen zusätzliche Kosten verursachen. "doSomething; GetResultOfSomething; HandleErrorsFromSomething;"
Du bist

Antworten:


13

Laut Greg Young stammt diese Idee von Bertrand Meyer : Trennung von Befehlen und Abfragen .

Jede Methode sollte entweder ein Befehl sein, der eine Aktion ausführt, oder eine Abfrage, die Daten an den Aufrufer zurückgibt, jedoch nicht beide. Mit anderen Worten, das Stellen einer Frage sollte die Antwort nicht ändern . 1 Formal sollten Methoden nur dann einen Wert zurückgeben, wenn sie referenziell transparent sind und daher keine Nebenwirkungen aufweisen.

1: Eiffel: eine Sprache für die Softwareentwicklung Folie 43-48

Im domänengetriebenen Design ähnelt dies der von Greg Young genannten Trennung / Segregation (Command-Query-Read Separation / Segregation, CQRS).

Greg Young übernahm die Idee von CQS von Bertrand, um CQRS zu benennen, wie dies von Martin Fowler in diesem CQRS-Artikel erwähnt wurde

Leistungen

  • Der Read (Query) -Teil kann anders skaliert / angepasst werden als der Write (Command) -Teil. Eine Trennung der beiden würde verhindern, dass sich beide gegenseitig im Weg stehen, wenn Optimierung / Leistung entscheidend sind.

Lesen Sie den Artikel im Martin Fowler Link für mehr.


1
Natürlich in vielen Situation ein brauchbares Ergebnis zu erzeugen und eine gewisse Modifikation tun zugleich ist nicht teurer als die je härter der beiden separat zu tun.
Deduplizierer

1
@Deduplicator Ein Klischeebeispiel für InterlockedCompareExchange?
Du bist

1
Dieser Ratschlag gilt natürlich nicht, wenn die Rückgabe Informationen darüber enthält, was im Befehl ausgeführt wurde. Eine Methode zum Entfernen von Zeilen aus einem Dataset kann den Status des Datasets so gut wie ändern, indem die angegebenen Zeilen gemäß einem bestimmten Kriterium entfernt werden Geben Sie dann die Anzahl der entfernten Zeilen oder sogar eine Liste mit diesen Zeilen zurück.
T. Sar - Reinstate Monica

4

Ich weiß nicht, woher es kommt, aber es ist ein guter Rat und ziemlich einfach zu verstehen.

Jedes sorgfältig gestaltete Programm wird in verschiedene Teile zerlegt, kombiniert und auf verschiedene Arten komponiert. Je schwieriger es ist zu überlegen, was ein bestimmtes Teil tut, desto schwieriger wird es, sicherzustellen, dass Ihr Programm auf vorhersehbare Weise reagiert.

Das Isolieren der Teile, die Nebenwirkungen hervorrufen, erleichtert das Überlegen, Testen und Debuggen des Rests. Wenn Sie die Anzahl der Nebenwirkungen in jedem Teil reduzieren, die Nebenwirkungen hervorrufen, können Sie mit diesem Teil auf die gleiche Weise leichter arbeiten.

Wenn Sie es noch weiter zerlegen, ist ein Rückgabewert ein Effekt. Nebenwirkungen sind ein Effekt. Eine Funktion sollte nur einen Effekt erzeugen (wenn möglich), da es umso schwieriger ist, zu überlegen, was sie tatsächlich tut, je mehr Eingänge und Effekte eine Funktion hat.


versuchen , diese doen ' T sogar die Frage Adresse gefragt, sehen wie man Antwort
gnat

@gnat Meine Frage bestand aus zwei Teilen: der Hauptfrage ("wer") und dem zusätzlichen Guthaben ("warum"). Wird hier nicht das zusätzliche Guthaben angesprochen?
Wayne Conrad

Nach meiner Lesung (" behauptete Leistung") wird erwartet, dass der Warum-Teil vom Autor des Zitats vorgeschlagen wird. Die Frage scheint nicht nach einer Liste aller möglichen Vorteile zu fragen
Mücke

2
@gnat Ich verstand die Frage als Versuch, diesen Rat zu verstehen, sowohl den Grund dafür als auch den Kontext, in dem er gegeben wurde. Ich glaube nicht, dass es unangemessen war, nur einen Teil der Frage anzusprechen.
Morgen

1

Zusätzliche Gutschrift: Was ist der ursprünglich geltend gemachte Vorteil, wenn Sie diesen Rat befolgen?

Einer der Vorteile der Trennung von Rückgabewert und Nebenwirkungen besteht darin, dass ein potenzielles Problem behoben wird, das durch die Kurzschlussbewertung verursacht werden kann .

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
}

Ist dies ein Vorteil, den der Autor des Gutachtens beansprucht ?
gnat

@gnat Ich fürchte, ich habe historisch und praktisch verwechselt.
Nick Alexeev

1
Der Kommentar und der Code stimmen nicht überein. BarWithSideEffects wird nicht aufgerufen, wenn FooWithSideEffects false
jk
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.