Frage

Ich habe diese Art von Funktion oft in beiden Formaten geschrieben und habe mich gefragt, ob ein Format gegenüber einem anderen bevorzugt wird und warum.

public void SomeFunction(bool someCondition)
{
    if (someCondition)
    {
        // Do Something
    }
}

oder

public void SomeFunction(bool someCondition)
{
    if (!someCondition)
        return;

    // Do Something
}

Normalerweise codiere ich mit dem ersten, da mein Gehirn auf diese Weise während des Codierens funktioniert, obwohl ich denke

War es hilfreich?

Lösung

Ich bevorzuge den zweiten Stil. Holen Sie sich zuerst ungültige Fälle aus dem Weg, entweder aus dem Ausnahmen oder der Anhebung von Ausnahmen, geben Sie dort eine leere Zeile hinein und fügen Sie dann den "realen" Körper der Methode hinzu. Ich finde es einfacher zu lesen.

Andere Tipps

Auf jeden Fall letzteres. Ersterer sieht momentan nicht schlecht aus, aber wenn Sie komplexere Code erhalten, kann ich mir nicht vorstellen, dass jemand dies denken würde:

public int SomeFunction(bool cond1, string name, int value, AuthInfo perms)
{
    int retval = SUCCESS;
    if (someCondition)
    {
        if (name != null && name != "")
        {
            if (value != 0)
            {
                if (perms.allow(name)
                {
                    // Do Something
                }
                else
                {
                    reval = PERM_DENY;
                }
            }
            else
            {
                retval = BAD_VALUE;
            }
        }
        else
        {
            retval = BAD_NAME;
        }
    }
    else
    {
        retval = BAD_COND;
    }
    return retval;
}

ist lesbarer als lesbar als

public int SomeFunction(bool cond1, string name, int value, AuthInfo perms)
{
    if (!someCondition)
        return BAD_COND;

    if (name == null || name == "")
        return BAD_NAME;

    if (value == 0)
        return BAD_VALUE;

    if (!perms.allow(name))
        return PERM_DENY;

    // Do something
    return SUCCESS;
}

Ich gebe voll und ganz zu, dass ich den Vorteil einzelner Ausstiegspunkte nie verstanden habe.

Es hängt davon ab, ob - Im Allgemeinen werde ich mich nicht Mühe geben, einen Code zu bewegen, um frühzeitig aus der Funktion auszubrechen - der Compiler wird sich im Allgemeinen darum kümmern. Wenn es jedoch einige grundlegende Parameter an der Spitze gibt, die ich brauche und sonst nicht weitermachen kann, werde ich frühzeitig ausbrechen. Ebenso, wenn eine Bedingung einen Riesen erzeugt if Block in Funktion Ich werde es auch als Ergebnis davon ausbrechen lassen.

Wenn eine Funktion jedoch einige Daten erfordert, wenn sie aufgerufen wird, werde ich normalerweise eine Ausnahme (siehe Beispiel), anstatt nur zurückzukehren.

public int myFunction(string parameterOne, string parameterTwo) {
  // Can't work without a value
  if (string.IsNullOrEmpty(parameterOne)) {
    throw new ArgumentNullException("parameterOne");
  } 
  if (string.IsNullOrEmpty(parameterTwo)) {
    throw new ArgumentNullException("parameterTwo");
  }

  // ...      
  // Do some work
  // ...

  return value;
}

Ich bevorzuge die frühe Rückkehr.

Wenn Sie einen Einstiegspunkt und einen Ausgangspunkt haben, müssen Sie immer den gesamten Code in Ihrem Kopf bis zum Ausgangspunkt verfolgen (Sie wissen nie, ob ein anderer Code -Bellow etwas anderes zum Ergebnis tut, also Sie muss es aufspüren, bis das existiert). Sie tun das keine Mater, die das Endergebnis bestimmt. Dies ist schwer zu folgen.

Mit einem Eintrag und mehreren existieren Sie zurück, wenn Sie Ihr Ergebnis haben, und die Mühe machen nicht, es ganz nach unten zu verfolgen, um zu sehen, dass niemand anderes etwas dazu tut (weil es seit Ihrer Rückkehr nichts anderes gibt). Es ist, als würde sich der Methodekörper in mehr Schritte aufspalten, was jeder Schritt mit der Möglichkeit, das Ergebnis zurückzugeben oder den nächsten Schritt zu vermitteln, sein Glück ausüben.

In der C-Programmierung, bei der Sie manuell aufräumen müssen, gibt es für eine Rückkehr von einer Punkte viel zu sagen. Selbst wenn es momentan nicht nötig ist, etwas aufzuräumen, kann jemand Ihre Funktion bearbeiten, etwas zuweisen und es vor der Rückkehr aufräumen. In diesem Fall wird es ein Albtraum -Job sein, der alle Rückgabeberechnungen durchschaut.

In C ++-Programmierung haben Sie Destruktoren und auch jetzt Teller-Exit-Wachen. All dies muss hier sein, um sicherzustellen, dass der Code in erster Linie ausnahmslos ist. Daher ist der Code vor dem frühen Ausstieg gut bewacht und hat daher keinen logischen Nachteil und ist nur ein Stilproblem.

Ich kenne mich nicht genug über Java, ob "endlich" Blockcode angerufen wird und ob Finalizer die Situation bewältigen können, um sicherzustellen, dass etwas passiert.

C# Ich kann auf jeden Fall nicht antworten.

Mit der D-Sprache können Sie ordnungsgemäß eingebaute Wächter in den Bereichszusammenleuten begleiten und daher gut auf den frühen Ausstieg vorbereitet und sollten daher kein anderes Problem als Stil aufweisen.

Funktionen sollten natürlich in erster Linie nicht so lang sein, und wenn Sie eine große Switch -Anweisung haben, ist Ihr Code wahrscheinlich auch schlecht berücksichtigt.

Frühe Rückkehr für die Gewinn. Sie können hässlich erscheinen, aber viel weniger hässlich als groß als groß if Wrapper, insbesondere wenn mehrere Bedingungen zu überprüfen sind.

Ich benutze beide.

Wenn DoSomething ist 3-5 Codezeilen, dann sieht der Code mit der ersten Formatierungsmethode einfach schön aus.

Aber wenn es viel mehr Zeilen als das hat, bevorzuge ich das zweite Format. Ich mag es nicht, wenn sich die Öffnungs- und Schließklammern nicht auf demselben Bildschirm befinden.

Ein klassischer Grund für ein Einstiegsausgang ist, dass die formale Semantik ansonsten ansonsten unaussprechlich hässlich wird (der gleiche Grund GOTO wurde als schädlich angesehen).

Anders ausgedrückt, es ist einfacher zu argumentieren, wann Ihre Software die Routine verlässt, wenn Sie nur 1 Return haben. Das ist auch ein Argument gegen Ausnahmen.

Normalerweise minimiere ich den Ansatz der frühen Rendite.

Persönlich bevorzuge ich zu Beginn bestehende Bedingungskontrollen. Das ermöglicht es mir, die meisten der häufigsten Fehler oben in der Funktion zu gruppieren, wobei der Rest der Logik folgt.

Es hängt davon ab, ob.

Frühe Rückkehr, wenn es eine offensichtliche Sackgasse gibt, auf die Sie sofort überprüfen sollten, die den Rest der Funktion sinnlos machen würde.*

Setzen Sie RetVal + Single Return, wenn die Funktion komplexer ist und ansonsten mehrere Exit -Punkte haben kann (Lesbarkeitsproblem).

*Dies kann häufig auf ein Designproblem hinweisen. Wenn Sie feststellen, dass viele Ihrer Methoden einen externen/Paramater -Status oder dergleichen überprüfen müssen, bevor Sie den Rest des Codes ausführen, sollte dies wahrscheinlich vom Anrufer behandelt werden.

Verwenden Sie ein if

In Don Knuths Buch über Gotos Ich lese ihn einen Grund dafür, immer die wahrscheinlichste Bedingung in einer IF -Erklärung zu haben. Unter der Annahme, dass dies immer noch eine vernünftige Idee ist (und nicht eine aus reine Überlegung für die Geschwindigkeit der Ära). Ich würde sagen, dass frühe Renditen keine gute Programmierpraxis sind, insbesondere angesichts der Tatsache, dass sie meistens für Fehlerbehandlungen verwendet werden, es sei denn, Ihr Code scheitert eher als nicht :-)

Wenn Sie den obigen Ratschlägen befolgen, müssten Sie diese Rückgabe unten in der Funktion einsetzen, und dann können Sie es genauso gut als Rückgabe dorthin nennen, einfach den Fehlercode einstellen und zwei Zeilen zurückgeben. Dadurch Erreichen des 1 -Eintrags 1 -Ausgangs Ideal.

Delphi spezifisch ...

Ich bin der Meinung, dass dies eine gute Programmierungspraxis für Delphi -Programmierer ist, obwohl ich keinen Beweis habe. Pre-D2009 haben wir keine atomische Möglichkeit, einen Wert zurückzugeben, wir haben exit; und result := foo; Oder wir könnten nur Ausnahmen werfen.

Wenn Sie ersetzen müssten

if (true) {
 return foo;
} 

zum

if true then 
begin
  result := foo; 
  exit; 
end;

Sie werden es vielleicht nur satt haben zu sehen, dass dies oben auf jeder Ihrer Funktionen

if false then 
begin
  result := bar;

   ... 
end
else
   result := foo;

und einfach vermeiden exit insgesamt.

Ich stimme der folgenden Erklärung zu:

Ich persönlich bin ein Fan von Wachklauseln (das zweite Beispiel), da es den Einrückungseinsatz der Funktion verringert. Einige Leute mögen sie nicht, weil es zu mehreren Rückkehrpunkten aus der Funktion führt, aber ich denke, es ist klarer bei ihnen.

Genommen von Diese Frage in Stackoverflow.

Ich benutze heutzutage fast ausschließlich ausschließlich zurück. Ich schreibe das

self = [super init];

if (self != nil)
{
    // your code here
}

return self;

wie

self = [super init];
if (!self)
    return;

// your code here

return self;

Aber es spielt wirklich keine Rolle. Wenn Sie mehr als ein oder zwei Nistbühnen in Ihren Funktionen haben, müssen sie aufgerissen werden.

Ich würde lieber schreiben:

if(someCondition)
{
    SomeFunction();
}

Wie Sie schreibe ich normalerweise den ersten, bevorzuge aber den letzten. Wenn ich viele verschachtelte Überprüfungen habe, rebe ich normalerweise mit der zweiten Methode um.

Ich mag es nicht, wie der Fehlerbehebung vom Scheck weggezogen wird.

if not error A
  if not error B
    if not error C
      // do something
    else handle error C
  else handle error B
else handle error A

Ich bevorzuge das:

if error A
  handle error A; return
if error B
  handle error B; return
if error C
  handle error C; return

// do something

Die Bedingungen an der Oberseite werden als "Voraussetzungen" bezeichnet. Durch Aussagen if(!precond) return;, Sie listen alle Voraussetzungen visuell auf.

Die Verwendung des großen "If-ELSE" -Blocks kann den Einsatzaufwand erhöhen (ich habe das Zitat über 3-Stufe-Einsteiger vergessen).

Ich ziehe es vor, wenn Aussagen klein sind.

Also, wählen Sie zwischen:

if condition:
   line1
   line2
    ...
   line-n

und

if not condition: return

line1
line2
 ...
line-n

Ich würde wählen, was Sie als "frühe Rückkehr" bezeichnet haben.

Wohlgemerkt, ich interessiere mich nicht für frühe Rückkehr oder was auch immer, ich mag es einfach, den Code zu vereinfachen, die Körper von If -Anweisungen zu verkürzen usw.

Verschachtelte IF und für und whilee sind entsetzlich, Vermeiden Sie sie um jeden Preis.

Wie andere sagen, kommt es darauf an. Für kleine Funktionen, die Werte zurückgeben, kann ich frühzeitig zurückgeben. Aber für beträchtliche Funktionen habe ich gerne immer einen Platz in dem Code, in dem ich weiß, dass ich etwas setzen kann, das vor seiner Rückkehr ausgeführt wird.

Ich übe auf Funktionsebene fehlgeschlagen. Es hält Code konsistent und sauber (für mich und diejenigen, mit denen ich gearbeitet habe). Aus diesem Grund kehre ich immer früh zurück.

Für einige oft überprüfte Bedingungen können Sie Aspekte für diese Überprüfungen implementieren, wenn Sie AOP verwenden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
scroll top