Was ist schönerer Code - return Wert alleinstehend oder mit Berechnung?



  • Beispiel:

    return ist mit endwert alleinstehend, endwert ist ja schon berechnet:

    // Vorheriger Bereich der Funktion
      ... 
      endwert +=  x + (y - (bla % 10 - ext)/3); 
      return endwert;
    }
    

    oder so, endwert wird in der Zeile von return noch berechnet:

    // Vorheriger Bereich der Funktion
      ... 
      return (endwert += x + (y - (bla % 10 - ext)/3));
    }
    

    das x + (y - (bla % 10 - ext)/3) wäre ein Beispiel, dass ich mir gerade so aus der Luft gegriffen habe.
    Es kann auch kürzer oder auch komplexer sein, wie ihr wollt.


  • Mod

    Wenn das endwert wirklich verändert werden soll, dann auf jeden Fall das Erste. Soll das wirklich += sein?

    Wenn da nur + stünde, dann vermutlich auch das Erste, weil da anscheinend schon eine große Rechnung voran geht und man das logische Ende der Rechnung sehen möchte.

    Faustregeln, wie ich es mag:
    -Je kürzer die Funktion insgesamt, desto eher Variante 2
    -Je einfacher der Ausdruck, desto eher Variante 2. Das += ist dabei ein Element, das auf jeden Fall zu viel Komplexität in den Ausdruck bringt. return endwert / 2 wäre aber voll in Ordnung, selbst wenn Regel 1 eine sehr lange Funktion sieht. Aber auf jeden Fall keine Nebeneffekte im Ausdruck!
    -Je stärker die Rechnung zu der logischen Bedeutung der Variablen gehört, desto eher Variante 1, so dass die Logik auch Beachtung findet. Gekünstelte Beispiele:

    double durchschnitt(double a, double b)
    {
      double durchschnitt = a + b;
      durchschnitt /= 2;    // logische Bedeutung der Variablen
      return durchschnitt;  
    }
    

    Oder

    double durchschnitt(double a, double b)
    {
      double summe = a + b;   // logische Bedeutung der Variablen
      return summe / 2;       // Kurze Rechnung ist ok
    }
    

    Oder

    double durchschnitt(double a, double b)
    {
      return (a + b) / 2;     // Da insgesamt kurz genug.
    }
    

    Hier finde ich alle 3 Varianten ungefähr gleich gut, je nachdem, welchen Aspekt man betonen will. Am wenigsten mag ich die erste Variante, da es eher

    double durchschnitt(double a, double b)
    {
      double summe = a + b;
      durchschnitt =  summe / 2; 
      return durchschnitt;  
    }
    

    heißen sollte. Aber das ist, weil das Beispiel insgesamt zu einfach ist. Manchmal hat man eben den Fall, dass man mehrere Schritte braucht, um einen Objekt den richtigen Endwert zuzuweisen.



  • Ich finde folgende Varianten gut:

    double durchschnitt(double a, double b) 
    { 
        return (a + b) / 2;                   // Kurz und dadurch schnell zu lesen
    }
    
    double durchschnitt(double a, double b) 
    {
        double const result = (a + b) / 2;    // Besser debugbar
        return result;
    }
    
    double durchschnitt(double a, double b) 
    {
        double const sum = a + b;             // Benannte Zwischenergebnisse sind zugleich Dokumentation und helfen beim Verstehen des Codes
        double const result = sum / 2;
        return result;
    }
    

    Was ich gar nicht mag ist Variablen zu ändern wenn man nicht muss (SeppJ's durchschnitt /= 2 Variante).
    SSA ist nicht nur für Code-Generatoren gut 🙂



  • hustbaer schrieb:

    SSA

    WTF?



  • volkard schrieb:

    hustbaer schrieb:

    SSA

    WTF?

    http://en.wikipedia.org/wiki/Static_single_assignment_form



  • Version eins, wegen dem +=, ansonsten Version zwei.

    Ich schreibe nie += oder = in einem Verschachtelten Ausdruck oder in einem if, das sind manchmal böse Stolperfallen nicht nur weil es für die meisten unerwartet kommt, sondern auch weil eine Zuweisung wichtig genug ist dass sie explizit geschehen sollte.

    Letzenendes gibt es aber keinen Ersatz für Aufmerksamkeit. Man muss halt sorgfältig lesen, das erspart einem niemand. Aus dem Grund sind prinzipiell die meisten Stile gleichwertig.



  • hustbaer schrieb:

    double durchschnitt(double a, double b) 
    {
        double const result = (a + b) / 2;    // Besser debugbar
        return result;
    }
    

    Wird Zeit, dass jemand den Debuggern mal beibringt, zwischen Wertberechnung und tatsächlichem return noch eine Unterbrechung zuzulassen.



  • hustbaer schrieb:

    Was ich gar nicht mag ist Variablen zu ändern wenn man nicht muss (SeppJ's durchschnitt /= 2 Variante).
    SSA ist nicht nur für Code-Generatoren gut 🙂

    In den Fällen, wo man nicht muss, kriegt die Variable einfach eine neue Version (problematisch wird es ja erst, wenn die Variable nicht aliasfrei ist, und man im folgenden nicht statisch bestimmen kann, auf welche Version zugegriffen wird). Ich sehe nicht, wie SSA da Schwierigkeiten bekommt.



  • ich finde die return += variante am besten, wuerde aber die unnoetigen klammern weglassen.



  • camper schrieb:

    Wird Zeit, dass jemand den Debuggern mal beibringt, zwischen Wertberechnung und tatsächlichem return noch eine Unterbrechung zuzulassen.

    Nun ja, bei VS wird einem angezeigt welchen Wert die Funktion zurückgegeben hat... solche Umwege sind da also streng genommen unnötig.^^



  • cooky451 schrieb:

    camper schrieb:

    Wird Zeit, dass jemand den Debuggern mal beibringt, zwischen Wertberechnung und tatsächlichem return noch eine Unterbrechung zuzulassen.

    Nun ja, bei VS wird einem angezeigt welchen Wert die Funktion zurückgegeben hat... solche Umwege sind da also streng genommen unnötig.^^

    Wenn der Wert aber falsch ist, bekomme ich so nicht mehr heraus, warum.



  • camper schrieb:

    Ich sehe nicht, wie SSA da Schwierigkeiten bekommt.

    Das SSA vom Compiler/Code-Generator bekommt gar keine Schwierigkeiten.

    Ich meinte: das was SSA ausmacht ist auch sehr angenehm beim Lesen von Code. Also wenn man seinen C++ Code so schreibt dass man alles "const" macht, weil man immer nur initialisiert und den Wert dann nie ändert.

    Natürlich muss man es damit nicht übertreiben. Also ich schreib' jetzt deswegen nicht alles um nur damit ich Schleifen oder so vermeide.

    Nur bevor ich

    int x = ...;
    x += 123;
    x = blah(x);
    ...
    

    schreibe, geb ich lieber jedem Zwischenergebnis einen neuen Namen.
    Weil's beim Code Lesen dadurch viel einfacher zu sehen ist was abgeht.



  • cooky451 schrieb:

    camper schrieb:

    Wird Zeit, dass jemand den Debuggern mal beibringt, zwischen Wertberechnung und tatsächlichem return noch eine Unterbrechung zuzulassen.

    Nun ja, bei VS wird einem angezeigt welchen Wert die Funktion zurückgegeben hat... solche Umwege sind da also streng genommen unnötig.^^

    Kann man das irgendwo abdrehen? Weil ich bekomm' das irgendwie nimmer angezeigt. Ich kann mich erinnern es schon gesehen zu haben, aber hab' das in den letzten Jahren öfter mal vergeblich gesucht.



  • hustbaer schrieb:

    Kann man das irgendwo abdrehen? Weil ich bekomm' das irgendwie nimmer angezeigt. Ich kann mich erinnern es schon gesehen zu haben, aber hab' das in den letzten Jahren öfter mal vergeblich gesucht.

    Ob und wie man es ein- / ausschalten kann weiss ich nicht. Jedoch ist der Rückgabewert nur in Lokal und in Auto zu sehen, nicht in "Überwachen" (solltest du permanent das offen haben) und nur wenn man durch die Funktion durchsteppt (wenn man die Anweisung mit dem Funktionsaufruf mit dem Prozedurschritt F10 überspringt wird bei mir auch nichts angezeigt; wenn ich nach dem Return-Statement einen Schritt mache, dann hingegen schon).



  • Hm.
    Gerade probiert, und funktioniert.
    Komisch.
    Ich hab in gesagten Fällen nämlich ganz sicher in "Autos" geguckt, daran kann ich mich noch gut erinnern. Weil's halt irgendwie logisch ist dass es in "Autos" angezeigt wird - sonst passt's ja nicht wirklich wo rein.


  • Mod

    Kellerautomat schrieb:

    ich finde die return += variante am besten, wuerde aber die unnoetigen klammern weglassen.

    *Schauder*

    Wer Nebeneffekte in Ausdrücken versteckt, der macht auch ... keine Ahnung, such dir was aus, dass du nicht leiden kannst 🙂

    Ich vermeide sogar Inkremente in Ausdrücken (außer als alleinstehender Ausdruck natürlich), außer es geht um irgendwelche Angebereien, wer das kürzeste strcpy schreiben kann.



  • SeppJ schrieb:

    Ich vermeide sogar Inkremente in Ausdrücken (außer als alleinstehender Ausdruck natürlich), außer es geht um irgendwelche Angebereien, wer das kürzeste strcpy schreiben kann.

    Und außer in *out++= (in C) hoffe ich mal.



  • SeppJ schrieb:

    Wenn das endwert wirklich verändert werden soll, dann auf jeden Fall das Erste. Soll das wirklich += sein?

    Ja, das += habe ich für das Beispiel eingebaut, weil man ja auch ansonsten einfach:

    // Vorheriger Bereich der Funktion
      ...
      return (x + (y - (bla % 10 - ext)/3));
    }
    

    hätte schreiben können.

    Also musste ich dafür sorgen, dass am Ende im Prinzip der Wert einer Variable zurückgegeben werden soll und die Notwendigkeit der Variable bringt man eben dadurch zum Ausdruck, in dem man sie mit der Berechnung verrechnet.

    Oder hättest du eine Berechnung erst in eine Variable gespeichert, um sie erst dann zurückzuliefern?
    Also so:

    // Vorheriger Bereich der Funktion
      ...
      double endwert = (x + (y - (bla % 10 - ext)/3));
      return endwert;
    }
    

    Anstatt += wäre natürlich auch:

    endwert = endwert +  x + (y - (bla % 10 - ext)/3);
    

    gegangen, aber das war mir dann zu viel Schreibarbeit. 😉


  • Mod

    volkard schrieb:

    SeppJ schrieb:

    Ich vermeide sogar Inkremente in Ausdrücken (außer als alleinstehender Ausdruck natürlich), außer es geht um irgendwelche Angebereien, wer das kürzeste strcpy schreiben kann.

    Und außer in *out++= (in C) hoffe ich mal.

    Ja, das ist halt so ein typischer strcpy-Hack. Wobei ein durch ein Gleichheitszeichen abgetrennter Ausdruck schon fast als Alleinstehend zählen kann. Da ist es in Ordnung, so etwas auf einer Seite stehen zu haben*.

    *: Und dann wird sich natürlich prompt irgendjemand finden, der *out++ = *out + 1 schreibt und mich zitiert, dass ich so etwas gutgeheißen hätte 🙄

    --------------------
    @Syntaktischer Zucker: Ich weiß nicht, ob du wirklich verstanden hast, wieso sich alle an dem += stören: Es geht da drum, dass durch das += im return eben die wichtige Information untergeht, dass das die Variable endwert selber noch verändert wird. Dies ist eine sehr wichtige Information (sonst würde man es ja nicht tun) und zudem sehr ungewöhnlich (wann hat man schon nicht-lokale Variablen zur Speicherung eines Ergebnisses?). Da sollte man unbedingt Wert darauf legen, dass dieser Vorgang auch gut sichtbar ist und den nicht in einer Rechnung verstecken.



  • hustbaer schrieb:

    Nur bevor ich

    int x = ...;
    x += 123;
    x = blah(x);
    ...
    

    schreibe, geb ich lieber jedem Zwischenergebnis einen neuen Namen.
    Weil's beim Code Lesen dadurch viel einfacher zu sehen ist was abgeht.

    Dann steigt aber auch der Speicherverbrauch.
    Und die Performance leidet ebenfalls darunter.

    Bei Variablen, die im Prinzip zum rechnen gleich weiterbenutzt werden, kann der Compiler z.B. dafür sorgen, das die in einem Register bleiben und das ist eben schneller, als wenn man den Wert wieder aus einer Speicheradresse holen müsste.
    Selbst mit 2nd Level Cache sind die Register schneller und seit AMD64 gibt's ja genug davon.


Anmelden zum Antworten