web-dev-qa-db-ger.com

Ist es ein guter Stil, in Ruby explizit zurückzukehren?

Ich komme aus einem Python Hintergrund, wo es immer einen "richtigen Weg" (einen "pythonischen" Weg) gibt, wenn es um Stil geht, und frage mich, ob es den gleichen für Ruby gibt Ich habe meine eigenen Stilrichtlinien verwendet, aber ich denke darüber nach, meinen Quellcode freizugeben.

Ist es "Die Ruby Way", um return in Methoden explizit einzutippen? Ich habe es mit und ohne gesehen, aber gibt es einen richtigen Weg, dies zu tun? gibt es vielleicht ein Recht Zeit, es zu tun? Zum Beispiel:

def some_func(arg1, arg2, etc)
  # Do some stuff...
  return value # <-- Is the 'return' needed here?
end
147
Sasha Chedygov

Alte (und "beantwortete") Frage, aber ich werfe meine zwei Cent als Antwort ein.

TL; DR - Sie müssen nicht, aber es kann Ihren Code in einigen Fällen viel klarer machen.

Obwohl die Verwendung eines expliziten Rückgabewerts möglicherweise "die Ruby) - Methode" ist, ist dies für Programmierer verwirrend, die mit unbekanntem Code arbeiten oder mit dieser Ruby-Funktion nicht vertraut sind.

Es ist ein etwas ausgeklügeltes Beispiel, aber das Imaging hat eine kleine Funktion wie diese, die der übergebenen Zahl eine hinzuaddiert und sie einer Instanzvariablen zuweist.

def plus_one_to_y(x)
    @y = x + 1
end

Sollte dies eine Funktion sein, die einen Wert zurückgibt, oder nicht? Es ist wirklich schwer zu sagen, was der Entwickler gemeint hat, da er sowohl die Instanzvariable als auch den zugewiesenen Wert zurückgibt.

Angenommen, viel später kommt ein anderer Programmierer (der vielleicht nicht so vertraut ist, wie Ruby gibt basierend auf der zuletzt ausgeführten Codezeile zurück) und möchte einige print-Anweisungen für die Protokollierung einfügen, und die Funktion wird Dies...

def plus_one_to_y(x)
    @y = x + 1
    puts "In plus_one_to_y"
end

Jetzt ist die Funktion kaputt wenn irgendetwas einen zurückgegebenen Wert erwartet. Wenn nichts einen zurückgegebenen Wert erwartet, ist dies in Ordnung. Wenn irgendwo weiter unten in der Codekette ein Aufruf von this einen zurückgegebenen Wert erwartet, wird dies eindeutig scheitern, da nicht das zurückgegeben wird, was erwartet wird.

Die eigentliche Frage lautet nun: Hat irgendetwas wirklich einen Rückgabewert erwartet? Hat das etwas kaputt gemacht oder nicht? Wird es in Zukunft etwas kaputt machen? Wer weiß! Nur eine vollständige Codeüberprüfung aller Anrufe wird Sie darüber informieren.

Zumindest für mich besteht der Best-Practice-Ansatz darin, entweder sehr deutlich zu machen, dass Sie etwas zurückgeben, wenn es wichtig ist, oder gar nichts zurückzugeben, wenn dies nicht der Fall ist.

Im Fall unserer kleinen Demo-Funktion würde es also so geschrieben werden, wenn wir davon ausgehen, dass es einen Wert zurückgibt ...

def plus_one_to_y(x)
    @y = x + 1
    puts "In plus_one_to_y"
    return @y
end

Und jedem Programmierer wäre klar, dass er einen Wert zurückgibt, und es ist viel schwieriger für ihn, ihn zu brechen, ohne es zu merken.

Alternativ könnte man es so schreiben und die return-Anweisung weglassen ...

def plus_one_to_y(x)
    @y = x + 1
    puts "In plus_one_to_y"
    @y
end

Aber warum die Mühe machen, die Wiederkehr des Wortes wegzulassen? Warum nicht einfach dort hineinstecken und 100% klar machen, was passiert? Dies hat buchstäblich keinen Einfluss auf die Leistungsfähigkeit Ihres Codes.

216
Tim Holt

Nein. Guter Ruby -Stil würde im Allgemeinen nur explizite Rückgaben für frühe Rückgabe. Ruby ist wichtig für Code-Minimalismus/implizit Zauber.

Das heißt, wenn eine explizite Rückgabe die Dinge klarer oder leichter lesbar macht, schadet es nichts.

66
Ben Hughes

Ich persönlich benutze das Schlüsselwort return, um zu unterscheiden, was ich funktionale Methoden nenne, dh Methoden, die hauptsächlich aufgrund ihres Rückgabewerts ausgeführt werden, und prozedurale Methoden in erster Linie wegen ihrer Nebenwirkungen ausgeführt. Daher erhalten Methoden, bei denen der Rückgabewert wichtig ist, ein zusätzliches Schlüsselwort return, um die Aufmerksamkeit auf den Rückgabewert zu lenken.

Ich benutze die gleiche Unterscheidung, wenn aufrufend Methoden: funktionale Methoden erhalten Klammern, prozedurale Methoden nicht.

Und last but not least verwende ich diese Unterscheidung auch bei Blöcken: Funktionsblöcke erhalten geschweifte Klammern, Prozedurblöcke (d. H. Blöcke, die etwas "tun") erhalten do/end.

Ich versuche jedoch, nicht religiös zu sein: Bei Blöcken haben geschweifte Klammern und do/end unterschiedliche Priorität, und anstatt explizite Klammern zur Disambiguierung eines Ausdrucks hinzuzufügen, wechsle ich einfach zu anderer Stil. Das gleiche gilt für den Methodenaufruf: Wenn das Hinzufügen von Klammern um die Parameterliste den Code lesbarer macht, mache ich das, auch wenn die betreffende Methode prozeduraler Natur ist.

31
Jörg W Mittag

Eigentlich ist es wichtig zu unterscheiden zwischen:

  1. Funktionen - Methoden, die für ihren Rückgabewert ausgeführt werden
  2. Prozeduren - Methoden, die wegen ihrer Nebenwirkungen ausgeführt werden

Ruby kennt keine systemeigene Methode, um diese zu unterscheiden. Dadurch sind Sie anfällig für das Schreiben einer Prozedur side_effect() und eines anderen Entwicklers, der beschließt, den impliziten Rückgabewert Ihrer Prozedur zu missbrauchen (im Grunde genommen als unreine Funktion zu behandeln).

Um dies zu beheben, nehmen Sie ein Blatt aus Scala und Haskells Buch und lassen Sie Ihre Prozeduren explizit nil (aka Unit oder () in anderen Sprachen).

Wenn Sie dies befolgen, wird die Verwendung der expliziten return -Syntax oder nicht nur eine Frage des persönlichen Stils.

Weitere Unterscheidung zwischen Funktionen und Prozeduren:

  1. Kopieren Sie Jörg W Mittag's nette Idee, Funktionsblöcke mit geschweiften Klammern und Verfahrensblöcke mit do/end Zu schreiben.
  2. Verwenden Sie beim Aufrufen von Prozeduren (), Während Sie beim Aufrufen von Funktionen dies nicht tun

Beachten Sie, dass Jörg W Mittag tatsächlich das Gegenteil befürwortet hat - Vermeiden von () Für Prozeduren -, aber das ist nicht ratsam, weil Sie möchten, dass nebenwirkende Methodenaufrufe klar von Variablen unterschieden werden können, insbesondere wenn arity 0 ist. Scala Style Guide zum Methodenaufruf für Details.

13
Alex Dean

Der Styleguide besagt, dass Sie return nicht in Ihrer letzten Anweisung verwenden sollten. Sie können es weiterhin verwenden falls es nicht das letzte ist . Dies ist eine der Konventionen, die von der Community strikt befolgt werden. Dies gilt auch, wenn Sie vorhaben, mit anderen Ruby-Anwendern zusammenzuarbeiten.


Das Hauptargument für die Verwendung von explizitem returns ist jedoch, dass es für Leute, die aus anderen Sprachen stammen, verwirrend ist.

  • Erstens ist dies nicht nur Ruby vorbehalten. Zum Beispiel hat Perl auch implizite Renditen.
  • Zweitens kommt die Mehrheit der Personen, für die dies gilt, aus ALGOL-Sprachen. Die meisten davon sind viel "untergeordneter" als Ruby, daher müssen Sie mehr Code schreiben, um etwas zu erledigen.

Eine übliche Heuristik für die Methodenlänge (ohne Getter/Setter) in Java) ist ein Bildschirm . In diesem Fall Sie Möglicherweise wird die Methodendefinition nicht angezeigt und/oder Sie haben bereits vergessen, von wo Sie zurückgekehrt sind.

Andererseits ist es in Ruby am besten, sich an Methoden zu halten weniger als 10 Zeilen lang . Angesichts dessen würde man sich fragen, warum er ~ 10% schreiben muss weitere Aussagen, wenn sie eindeutig impliziert sind.


Da Ruby keine ungültigen Methoden hat und alles so viel prägnanter ist, fügen Sie nur Overhead für keine hinzu der Vorteile, wenn Sie mit expliziten returns gehen.

7
ndnenkov

Ich stimme Ben Hughes zu und stimme Tim Holt nicht zu, da in der Frage die endgültige Vorgehensweise von Python genannt wird und gefragt wird, ob Ruby einen ähnlichen Standard hat.

Tut es.

Dies ist ein so bekanntes Merkmal der Sprache, dass von jedem, der erwartet, ein Problem in Ruby zu debuggen, vernünftigerweise erwartet werden sollte, dass er davon weiß.

4
Devon Parsons

Es ist eine Frage des Stils, den Sie am meisten bevorzugen. Sie müssen das Schlüsselwort return verwenden, wenn Sie irgendwo in der Mitte einer Methode zurückkehren möchten.

1
Praveen Angyan

Wie Ben gesagt hat. Die Tatsache, dass 'der Rückgabewert einer Ruby) - Methode der Rückgabewert der letzten Anweisung im Funktionskörper ist', führt dazu, dass das return-Schlüsselwort in den meisten Ruby Methoden.

def some_func_which_returns_a_list( x, y, z)
  return nil if failed_some_early_check


  # function code 

  @list     # returns the list
end
0
Gishu