Ich komme aus einem Python-Hintergrund, in dem es immer einen "richtigen Weg" (einen "pythonischen" Weg) gibt, wenn es um Stil geht, und frage mich, ob es für Ruby dasselbe gibt. Ich habe meine eigenen Stilrichtlinien verwendet, denke aber darüber nach, meinen Quellcode freizugeben, und ich möchte, dass er sich an eventuell vorhandene ungeschriebene Regeln hält.
Ist es "The Ruby Way", return
Methoden explizit einzugeben? Ich habe es mit und ohne gesehen, aber gibt es einen richtigen Weg, es zu tun? Gibt es vielleicht einen richtigen Zeitpunkt dafür? Beispielsweise:
def some_func(arg1, arg2, etc)
# Do some stuff...
return value # <-- Is the 'return' needed here?
end
ruby
coding-style
return-value
Sasha Chedygov
quelle
quelle
Antworten:
Alte (und "beantwortete") Frage, aber ich werde meine zwei Cent als Antwort einwerfen.
TL; DR - Sie müssen nicht, aber es kann Ihren Code in einigen Fällen viel klarer machen.
Obwohl die Verwendung einer expliziten Rückgabe möglicherweise "der Ruby-Weg" ist, ist dies für Programmierer, die mit unbekanntem Code arbeiten oder mit dieser Funktion von Ruby nicht vertraut sind, verwirrend.
Es ist ein etwas ausgeklügeltes Beispiel, aber stellen Sie sich vor, Sie hätten eine kleine Funktion wie diese, die der übergebenen Zahl eine hinzufügt und sie einer Instanzvariablen zuweist.
War dies eine Funktion, die einen Wert zurückgab, oder nicht? Es ist wirklich schwer zu sagen, was der Entwickler gemeint hat, da beide die Instanzvariable zuweisen UND auch den zugewiesenen Wert zurückgeben.
Angenommen, viel später kommt ein anderer Programmierer (der vielleicht nicht so vertraut damit ist, wie Ruby basierend auf der zuletzt ausgeführten Codezeile zurückgibt) und möchte einige print-Anweisungen für die Protokollierung eingeben, und die Funktion wird zu dieser ...
Jetzt ist die Funktion unterbrochen, wenn etwas 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 einen zurückgegebenen Wert erwartet, wird dies eindeutig fehlschlagen, da er nicht das zurückerhält, was er erwartet.
Die eigentliche Frage lautet nun: Hat irgendetwas wirklich einen zurückgegebenen Wert 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 informiert Sie.
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 überhaupt nichts zurückzugeben, wenn dies nicht der Fall ist.
Im Fall unserer kleinen Demofunktion würde sie also so geschrieben sein, vorausgesetzt, wir wollten, dass sie einen Wert zurückgibt ...
Und es wäre jedem Programmierer sehr klar, dass es einen Wert zurückgibt, und es ist für sie viel schwieriger, ihn zu brechen, ohne es zu merken.
Alternativ könnte man es so schreiben und die return-Anweisung weglassen ...
Aber warum sollte man sich die Mühe machen, das Wort Rückkehr wegzulassen? Warum nicht einfach dort hineinstecken und 100% klar machen, was passiert? Dies hat buchstäblich keinen Einfluss auf die Leistungsfähigkeit Ihres Codes.
quelle
return
dem Code eine semantische Bedeutung hinzufügt, warum nicht? Es ist kaum sehr ausführlich - wir sprechen nicht 5 Zeilen gegen 3, nur noch ein Wort. Ich würde es vorziehen,return
zumindest in Funktionen (möglicherweise nicht in Blöcken) zu sehen, um auszudrücken, was der Code tatsächlich tut. Manchmal müssen Sie die Mid-Funktion zurückgeben - lassen Sie das letztereturn
Schlüsselwort in der letzten Zeile nicht aus, nur weil Sie können. Ich bevorzuge überhaupt keine Ausführlichkeit, aber ich bevorzuge Konsistenz.side_effect()
und ein anderer Entwickler beschließt, den impliziten Rückgabewert Ihrer Prozedur (ab) zu verwenden. Um dies zu beheben, können Sie Ihre Prozeduren explizit vornehmenreturn nil
.Nein. Ein guter Ruby-Stil verwendet im Allgemeinen nur explizite Rückgaben für eine frühzeitige Rückgabe . Ruby legt großen Wert auf Code-Minimalismus / implizite Magie.
Das heißt, wenn eine explizite Rückgabe die Dinge klarer oder leichter lesbar machen würde, würde dies nichts schaden.
quelle
return
bereits eine bedeutende semantische Bedeutung als EARLY EXIT für die Funktion.return
in der letzten Zeile als EARLY EXIT verwechseln ?Ich persönlich benutze das
return
Schlüsselwort, um zwischen funktionalen Methoden zu unterscheiden , dh Methoden, die hauptsächlich wegen ihres Rückgabewerts ausgeführt werden, und prozeduralen Methoden , die hauptsächlich wegen ihrer Nebenwirkungen ausgeführt werden. Bei Methoden, bei denen der Rückgabewert wichtig ist, erhalten Sie ein zusätzlichesreturn
Schlüsselwort, um auf den Rückgabewert aufmerksam zu machen.Ich benutze die gleiche Unterscheidung beim Aufrufen von Methoden: Funktionsmethoden erhalten Klammern, prozedurale Methoden nicht.
Und zu guter Letzt verwende ich diese Unterscheidung auch bei Blöcken: Funktionsblöcke erhalten geschweifte Klammern, prozedurale Blöcke (dh Blöcke, die etwas "tun") erhalten
do
/end
.Ich versuche jedoch, nicht religiös zu sein: Mit Blöcken, geschweiften Klammern und
do
/ oderend
unterschiedlicher Priorität, und anstatt explizite Klammern hinzuzufügen, um einen Ausdruck eindeutig zu machen, wechsle ich einfach zum anderen Stil. Gleiches gilt für den Methodenaufruf: Wenn das Hinzufügen von Klammern um die Parameterliste den Code lesbarer macht, mache ich das auch dann, wenn die betreffende Methode prozeduraler Natur ist.quelle
Eigentlich ist es wichtig zu unterscheiden zwischen:
Ruby hat keine native Methode, um diese zu unterscheiden. Dies macht Sie anfällig für das Schreiben einer Prozedur
side_effect()
und einen anderen Entwickler, 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 Verfahren explizit zurückgeben
nil
(auch bekannt alsUnit
oder()
in anderen Sprachen).Wenn Sie dies befolgen, wird die Verwendung einer expliziten
return
Syntax oder nicht nur eine Frage des persönlichen Stils.Weitere Unterscheidung zwischen Funktionen und Verfahren:
do/end
()
, während dies beim Aufrufen von Funktionen nicht der Fall istBeachten Sie, dass Jörg W Mittag tatsächlich den umgekehrten Fall befürwortet hat -
()
s für Prozeduren zu vermeiden -, aber dies ist nicht ratsam, da Sie möchten, dass nebeneffektive Methodenaufrufe klar von Variablen unterschieden werden können, insbesondere wenn arity 0 ist. Siehe den Scala-Styleguide zum Methodenaufruf für Einzelheiten.quelle
function_a
undfunction_a
zum Aufrufen geschrieben wurde (und nur durch Aufrufen arbeiten kann)procedure_b
, ist das dannfunction_a
wirklich eine Funktion? Es gibt einen Wert zurück, der Ihre Anforderungen an Funktionen erfüllt, hat jedoch einen Nebeneffekt und erfüllt die Anforderungen von Prozeduren.function_a
könnte einen Baum vonprocedure_...
Anrufen enthalten, ebenso wieprocedure_a
einen Baum vonfunction_...
Anrufen. Wie Scala, aber anders als Haskell kann in Ruby nicht garantiert werden, dass eine Funktion keine Nebenwirkungen hat.Der Styleguide besagt, dass Sie
return
Ihre letzte Anweisung nicht verwenden sollten. Sie können es weiterhin verwenden, wenn es nicht das letzte ist . Dies ist eine der Konventionen, die die Community strikt befolgt. Dies sollten Sie auch tun, wenn Sie vorhaben, mit anderen Personen zusammenzuarbeiten, die Ruby verwenden.Abgesehen davon ist das Hauptargument für die Verwendung von expliziten
return
s, dass es für Leute aus anderen Sprachen verwirrend ist.Eine gängige Heuristik für die Methodenlänge (ohne Getter / Setter) in Java ist ein Bildschirm . In diesem Fall wird die Methodendefinition möglicherweise nicht angezeigt und / oder Sie haben bereits vergessen, von wo Sie zurückgekehrt sind.
Auf der anderen Seite ist es in Ruby am besten, sich an Methoden zu halten, die weniger als 10 Zeilen lang sind . Angesichts dessen würde man sich fragen, warum er ~ 10% mehr Aussagen schreiben muss, wenn sie eindeutig impliziert sind.
Da Ruby keine ungültigen Methoden hat und alles so viel präziser ist, fügen Sie nur Overhead für keinen der Vorteile hinzu, wenn Sie explizite
return
s verwenden.quelle
Ich stimme Ben Hughes zu und stimme Tim Holt nicht zu, da in der Frage die endgültige Vorgehensweise von Python erwähnt wird und gefragt wird, ob Ruby einen ähnlichen Standard hat.
Es tut.
Dies ist ein so bekanntes Merkmal der Sprache, dass jeder, von dem erwartet wird, dass er ein Problem in Ruby debuggt, vernünftigerweise davon erfahren sollte.
quelle
return
Schlüsselwort zu verwenden, wenn dies nicht erforderlich ist.Es ist eine Frage des Stils, den Sie größtenteils bevorzugen. Sie müssen das Schlüsselwort return verwenden, wenn Sie von irgendwo in der Mitte einer Methode zurückkehren möchten.
quelle
Wie Ben sagte. Die Tatsache, dass 'der Rückgabewert einer Ruby-Methode der Rückgabewert der letzten Anweisung im Funktionskörper ist', führt dazu, dass das Schlüsselwort return in den meisten Ruby-Methoden selten verwendet wird.
quelle
if failed_check then nil else @list end
? Das ist wirklich funktional .