779 Stimmen

Sollte eine Funktion nur eine Rückgabeanweisung haben?

Gibt es gute Gründe, warum es besser ist, nur eine Rückgabeanweisung in einer Funktion zu haben?

Oder ist es in Ordnung, aus einer Funktion zurückzukehren, sobald dies logisch korrekt ist, d.h. es kann viele Return-Anweisungen in der Funktion geben?

25 Stimmen

Ich stimme nicht zu, dass die Frage sprachenfeindlich ist. Bei einigen Sprachen ist die Mehrfachrückgabe natürlicher und bequemer als bei anderen. Ich würde mich eher über frühe Rückgaben in einer C-Funktion beschweren als in einer C++-Funktion, die RAII verwendet.

3 Stimmen

Diese Frage ist eng damit verbunden und enthält ausgezeichnete Antworten: programmers.stackexchange.com/questions/118703/

0 Stimmen

Sprachunabhängig? Erklären Sie jemandem, der eine funktionale Sprache verwendet, dass er einen Return pro Funktion verwenden muss :p

62voto

blank Punkte 17444

Wie Kent Beck bei der Erörterung von Schutzklauseln in Muster für die Umsetzung eine Routine mit einem einzigen Eintritts- und Austrittspunkt zu versehen ...

"war es, die Verwirrung zu vermeiden, die entstehen kann wenn man in viele Orte hinein und aus ihnen heraus Orten in derselben Routine. Es machte Sinn, wenn es auf FORTRAN oder Assembler Assembler-Programmen, die mit vielen globalen Daten, bei denen sogar Verständnis, welche Anweisungen ausgeführt wurden ... bei kleinen Methoden und meist lokalen Daten ist es unnötig konservativ."

Ich finde eine Funktion, die mit Schutzklauseln geschrieben wurde, viel einfacher zu verfolgen als einen langen verschachtelten Haufen von if then else Erklärungen.

0 Stimmen

Natürlich ist "ein langer verschachtelter Haufen von if-then-else-Anweisungen" nicht die einzige Alternative zu Schutzklauseln.

0 Stimmen

@AdrianMcCarthy haben Sie eine bessere Alternative? Das wäre nützlicher als Sarkasmus.

0 Stimmen

@kuhaku: Ich bin mir nicht sicher, ob ich das als Sarkasmus bezeichnen würde. Die Antwort legt nahe, dass es sich um eine Entweder-Oder-Situation handelt: entweder Schutzklauseln oder lange verschachtelte Bündel von Wenn-dann-Sechs. Viele (die meisten?) Programmiersprachen bieten neben Schutzklauseln viele andere Möglichkeiten, solche Logik zu berücksichtigen.

61voto

Apocalisp Punkte 34088

In einer Funktion, die keine Nebeneffekte hat, gibt es keinen guten Grund, mehr als eine Rückgabe zu haben, und man sollte sie in einem funktionalen Stil schreiben. Bei einer Methode mit Seiteneffekten sind die Dinge sequenzieller (zeitindiziert), daher schreiben Sie im imperativen Stil und verwenden die Rückgabeanweisung als Befehl zum Beenden der Ausführung.

Mit anderen Worten, bevorzugen Sie, wenn möglich, diesen Stil

return a > 0 ?
  positively(a):
  negatively(a);

hierüber

if (a > 0)
  return positively(a);
else
  return negatively(a);

Wenn Sie mehrere Schichten von verschachtelten Bedingungen schreiben, gibt es wahrscheinlich einen Weg, wie Sie das umstrukturieren können, zum Beispiel mit Prädikatsliste. Wenn Sie feststellen, dass Ihre "ifs" und "els" syntaktisch weit voneinander entfernt sind, sollten Sie diese in kleinere Funktionen aufteilen. Ein bedingter Block, der sich über mehr als einen Bildschirm voll Text erstreckt, ist schwer zu lesen.

Es gibt keine feste Regel, die für alle Sprachen gilt. Eine einzige Return-Anweisung macht Ihren Code noch lange nicht gut. Aber guter Code wird es Ihnen erlauben, Ihre Funktionen auf diese Weise zu schreiben.

6 Stimmen

+1 "Wenn Sie feststellen, dass Ihre ifs und elses syntaktisch weit voneinander entfernt sind, sollten Sie sie in kleinere Funktionen aufteilen."

4 Stimmen

+1, wenn dies ein Problem ist, bedeutet dies in der Regel, dass Sie zu viel in einer einzigen Funktion tun. Es deprimiert mich wirklich, dass dies nicht die meistgewählte Antwort ist

1 Stimmen

Auch Guard-Anweisungen haben keine Nebenwirkungen, aber die meisten Menschen würden sie für nützlich halten. Es kann also Gründe geben, die Ausführung frühzeitig zu beenden, auch wenn keine Nebenwirkungen auftreten. Diese Antwort geht meiner Meinung nach nicht ganz auf das Problem ein.

43voto

Pete Kirkham Punkte 47746

Ich habe es in den Codierungsstandards für C++ gesehen, die ein Überbleibsel von C waren, denn wenn man kein RAII oder ein anderes automatisches Speichermanagement hat, dann muss man bei jeder Rückkehr aufräumen, was entweder Ausschneiden und Einfügen des Aufräumens oder ein goto (logischerweise dasselbe wie 'finally' in verwalteten Sprachen) bedeutet, was beides als schlechte Form gilt. Wenn Sie intelligente Zeiger und Auflistungen in C++ oder einem anderen automatischen Speichersystem verwenden, dann gibt es keinen triftigen Grund dafür, und es geht nur noch um die Lesbarkeit und ist eher eine Ermessensentscheidung.

0 Stimmen

Gut gesagt, obwohl ich glaube, dass es besser ist, die Löschungen zu kopieren, wenn man versucht, hoch optimierten Code zu schreiben (z. B. Software, die komplexe 3D-Netze skinnt!)

1 Stimmen

Was veranlasst Sie, das zu glauben? Wenn Sie einen Compiler mit schlechter Optimierung haben, bei dem ein gewisser Overhead bei der Dereferenzierung der auto_ptr können Sie einfache Zeiger parallel verwenden. Allerdings wäre es merkwürdig, "optimierten" Code mit einem nicht optimierenden Compiler zu schreiben.

0 Stimmen

Dies stellt eine interessante Ausnahme von der Regel dar: Wenn Ihre Programmiersprache nichts enthält, was automatisch am Ende der Methode aufgerufen wird (wie z. B. try ... finally in Java) und Sie müssen Ressourcen pflegen, die Sie mit einem einzigen Return am Ende einer Methode erledigen könnten. Bevor Sie dies tun, sollten Sie ernsthaft in Erwägung ziehen, den Code zu refaktorisieren, um die Situation zu beseitigen.

40voto

Joel Coehoorn Punkte 377088

Ich neige zu der Auffassung, dass Return-Anweisungen in der Mitte der Funktion sind schlecht. Sie können Returns verwenden, um einige Schutzklauseln am Anfang der Funktion zu erstellen, und natürlich dem Compiler mitteilen, was am Ende der Funktion ohne Probleme zurückgegeben werden soll, aber Returns in der Mitte der Funktion kann leicht übersehen werden und erschwert die Interpretation der Funktion.

38voto

Adrian McCarthy Punkte 42872

Gibt es gute Gründe, warum es besser ist, nur eine Rückgabeanweisung in einer Funktion zu haben?

Ja gibt es:

  • Die einzige Ausstiegsstelle ist ein hervorragender Ort, um Ihre Nachbedingungen durchzusetzen.
  • Die Möglichkeit, einen Debugger-Breakpoint auf den einen Return am Ende der Funktion zu setzen, ist oft nützlich.
  • Weniger Rückgaben bedeuten weniger Komplexität. Ein linearer Code ist im Allgemeinen einfacher zu verstehen.
  • Wenn der Versuch, eine Funktion auf einen einzigen Rückgabewert zu vereinfachen, zu Komplexität führt, dann ist das ein Anreiz für eine Umstrukturierung zu kleineren, allgemeineren und leichter zu verstehenden Funktionen.
  • In einer Sprache ohne Destruktoren oder wenn Sie RAII nicht verwenden, reduziert eine einzelne Rückgabe die Anzahl der Stellen, an denen Sie aufräumen müssen.
  • Einige Sprachen erfordern einen einzigen Exit-Point (z.B. Pascal und Eiffel).

Die Frage wird oft als falsche Dichotomie zwischen Mehrfachrückgaben oder tief verschachtelten if-Anweisungen gestellt. Es gibt fast immer eine dritte Lösung, die sehr linear ist (keine tiefe Verschachtelung) und nur einen einzigen Ausgangspunkt hat.

Update : Anscheinend MISRA-Leitlinien fördern die einheitliche Ausreise auch.

Um das klarzustellen: Ich sage nicht, dass es immer Es ist falsch, mehrere Rückgaben zu haben. Aber bei ansonsten gleichwertigen Lösungen gibt es viele gute Gründe, die Lösung mit einer einzigen Rendite vorzuziehen.

2 Stimmen

Ein weiterer guter Grund, der heutzutage wahrscheinlich der beste ist, eine einzelne Rückgabeanweisung zu haben, ist die Protokollierung. Wenn Sie einer Methode eine Protokollierung hinzufügen möchten, können Sie eine einzelne Protokollanweisung platzieren, die vermittelt, was die Methode zurückgibt.

0 Stimmen

Wie verbreitet war die FORTRAN ENTRY-Anweisung? Siehe docs.oracle.com/cd/E19957-01/805-4939/6j4m0vn99/index.html . Und wenn Sie abenteuerlustig sind, können Sie Methoden mit AOP und After-Advice protokollieren

1 Stimmen

+1 Die ersten 2 Punkte haben mich schon überzeugt. Das gilt auch für den vorletzten Absatz. Ich würde dem Logging-Element aus demselben Grund nicht zustimmen, aus dem ich von tief verschachtelten Konditionalen abrate, da sie dazu ermutigen, die Regel der einzigen Verantwortung zu brechen, die der Hauptgrund dafür ist, dass Polymorphismus in die OOPs eingeführt wurde.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X