Programmierrichtlinen (Uni-Paderborn)



  • Ne, das ist schlechter Stil @life. Passt scho, was in der Richtlinie steht.



  • life: Die Java Coding Conventions von Sun sehen so eine Art Mittelweg zwischen den beiden von dir gezeigten Varianten vor:

    http://java.sun.com/docs/codeconv/html/CodeConventions.doc5.html#2991

    One declaration per line is recommended

    Try to initialize local variables where they're declared. The only reason not to initialize a variable where it's declared is if the initial value depends on some computation occurring first.

    ...aber wie in der Richtline eurer Uni:

    Put declarations only at the beginning of blocks.

    Ich muss sagen, dass ich mich auch nicht unbedingt an diese letzte Regel halte. Ich bin dafür, dass Variablen so lokal wie möglich gehalten werden. Sie sollen einen möglichst kleinen Gültigkeitsbereich haben. Wenn ich mal ne ganz lange Methode mit 20 Zeilen habe und eine Variable erst am Schluss benötige, halte ich es für Unsinn, diese Variable ganz am Anfang zu deklarieren. ...abgesehen davon sollte man natürlich eher kürzere Methoden anstreben.

    PS: Im Zweifelsfall kannst du ja einfach Extrablöcke einfügen. 😃 Dann ist jeder zufrieden, auch wenn der Code dann scheiße aussieht:

    public static void main (String [] args) {
       int tag = 9;
       int monat = 11;
       int jahr = 1989;
    
       System.out.println("Datum des Mauerfalls:");
       System.out.println(tag,monat,jahr);
    
       {
          double preis = 3.29;
    
          System.out.println("Preis einer Flasche Sekt am Tag des Mauerfalls in DM:");
          System.out.println(preis);
          {
             double neuerpreis = 2 * preis;
    
             System.out.println("Preis einer Flasche Sekt heute in EUR:");
             System.out.println(neuerpreis);
          }
       }
    }
    


  • Gregor schrieb:

    PS: Im Zweifelsfall kannst du ja einfach Extrablöcke einfügen. 😃 Dann ist jeder zufrieden, auch wenn der Code dann scheiße aussieht:

    Das hat ich mir auch schon überlegt 😃



  • Ich deklariere normalerweise alle Variablen am Anfang des Blockes. Erstens gehts ja in C nicht anders und zweitens finde ich es ehrlich gesagt auch übersichtlicher, als wenn man die Variablen quer durch die Funktion definiert. Hat man einen grossen Block und überfliegt diesen, dann wundert man sich öfters wo denn jetzt Variable Xy auf einmal herkommt und was das sein soll. Wenn alles am Anfang deklariert ist, kann man schneller nachgucken. Lediglich bei so Kleinigkeiten wie for Schleifen etc. sehe ich es als nützlich an.



  • Gregorianer schrieb:

    Wenn alles am Anfang deklariert ist, kann man schneller nachgucken.

    wenn es direkt beim gebraucht definiert ist muss man aber garnicht nachgucken 💡



  • life schrieb:

    Gregorianer schrieb:

    Wenn alles am Anfang deklariert ist, kann man schneller nachgucken.

    wenn es direkt beim gebraucht definiert ist muss man aber garnicht nachgucken 💡

    Und es spart Codezeilen, wenn man dort definiert, wo auch gebraucht wird. In Java hat es wohl anders als in C++ keinen Overhead, wenn man alles am Anfang definiert. Man arbeitet ja nur mit Zeigern.



  • Ponto schrieb:

    life schrieb:

    Gregorianer schrieb:

    Wenn alles am Anfang deklariert ist, kann man schneller nachgucken.

    wenn es direkt beim gebraucht definiert ist muss man aber garnicht nachgucken 💡

    Und es spart Codezeilen, wenn man dort definiert, wo auch gebraucht wird. In Java hat es wohl anders als in C++ keinen Overhead, wenn man alles am Anfang definiert. Man arbeitet ja nur mit Zeigern.

    hats in C++ auch nicht. Die Compiler sind da schon intelligent genug 😉



  • otze schrieb:

    hats in C++ auch nicht. Die Compiler sind da schon intelligent genug 😉

    Das glaube ich nicht:

    class Obj {
    public:
       Obj() { sock.open("127.0.0.1"); }
       ~Obj() { sock.close(); }
       void write(char const * str) { sock.write(str); }
    private:
       SocketObj sock;
    };
    
    void func(int value) {
      Obj ob;
    
      if (value > 10) return;
    
      ob.write(value);
    }
    


  • Der Grund dafür das man Variablen in C++ nicht alle blockweise definiert ist
    doch ganz einfach und logisch nachvollziehbar.
    Man verbindet bei Objekten sehr häufig die Definition mit der Initialisierung.
    Da die Initailisierung sehr teuer werden kann "erstellt" man die Variablen
    natürlich erst dann wenn sie wirklich benötigt werden.
    Das ganze hat also wirklich mehr als nur formale Aspekte.



  • otze schrieb:

    Ponto schrieb:

    life schrieb:

    Gregorianer schrieb:

    Wenn alles am Anfang deklariert ist, kann man schneller nachgucken.

    wenn es direkt beim gebraucht definiert ist muss man aber garnicht nachgucken 💡

    Und es spart Codezeilen, wenn man dort definiert, wo auch gebraucht wird. In Java hat es wohl anders als in C++ keinen Overhead, wenn man alles am Anfang definiert. Man arbeitet ja nur mit Zeigern.

    hats in C++ auch nicht. Die Compiler sind da schon intelligent genug 😉

    Dann ist dein Compiler kaputt. Er sollte schon das machen, was du ihm sagst.

    {
       Foo foo;  // Default-C'tor
       ...
       foo = bar;  // Zuweisung
    }
    
    {
       ...
       Foo foo (bar);  // spezieller C'tor
    }
    

    Das gilt zwar für Java nicht. Dennoch wird bei mir alles da definiert, wo ich es brauche. Nach oben Springen 'ne Definition einfügen, wieder nach unten und weiterschreiben, wider nach oben, ... was für 'ne Arbeitsweise.



  • Helium schrieb:

    Dennoch wird bei mir alles da definiert, wo ich es brauche. Nach oben Springen 'ne Definition einfügen, wieder nach unten und weiterschreiben, wider nach oben, ... was für 'ne Arbeitsweise.

    Man hat ja gewöhnlich einen Plan der Funktion im Kopf und schreibst sie dann eben kochrezeptartig hin: Oben die Zutaten und unten, was damit passiert.



  • Daniel E. schrieb:

    Man hat ja gewöhnlich einen Plan der Funktion im Kopf und schreibst sie dann eben kochrezeptartig hin: Oben die Zutaten und unten, was damit passiert.

    Ist bei mir nicht so. Bei mir ergibt sich oft erst beim Schreiben eines konkreten Codesegments, was ich dazu eigentlich noch für Hilfsvariablen und so brauche.



  • Ponto: Was soll der Compiler denn deiner Meinung nach sonst machen? Ist doch klar, dass er den Konstruktoraufruf nicht einfach ignorieren kann. Das "Problem" hat man in Java auch, wenn man sich eine Instanz erstellt lange bevor sie gebraucht wird.



  • Walli schrieb:

    Ponto: Was soll der Compiler denn deiner Meinung nach sonst machen? Ist doch klar, dass er den Konstruktoraufruf nicht einfach ignorieren kann. Das "Problem" hat man in Java auch, wenn man sich eine Instanz erstellt lange bevor sie gebraucht wird.

    In Java ist es aber üblich ständig mit Zeigern zu arbeiten:

    Obj ob;
    
    ... ganz viel Code ...
    
    ob = new Obj();
    

    Da kostet es halt nichts vorher das ob anzulegen. Sowas kann man in C++ mit Zeigern ja genauso machen und dann gehe ich davon aus, dass der Compiler mir da nicht sofort Stackspeicher für alloziert, wenn es nicht notwendig ist.

    In C++ ist es aber eher unüblich mit Zeigern zu arbeiten und die Objekte werden direkt erstellt. Wenn man dann alle Variablen direkt definiert hat man das gleiche Problem, wie wenn man unter Java sofort instanziert.



  • Ja, aber da vergleichst du ja trotzdem Äpfel mit Birnen. Ich sehe nicht wo C++ da einen unnötigen Overhead haben sollte. In C++ ist es hier nicht üblich wie in Java mit Zeigern zu arbeiten, aber die Objekte zu früh zu instanziieren ist ja auch nicht üblich. Ich vermute die Compiler sind schon intelligent genug die Instanziierungen zur rechten Zeit zu machen, aber nur, wenn dadurch der Programmablauf nicht verändert wird. Ich denke bei PODs und builtins sollte es hier kein Problem geben.



  • Ich denke auch, dass man Variable moeglichst lokal halten soll. Meint ihr, man sollte soweit gehen, dazu extra Bloecke aufzumachen, damit temporaete Variablen wieder aus dem Scope verschwinden?

    ...
    int result;
    {
      int tmp = ...
      int tmp2 = ...
      result = tmp * (tmp + tmp2);
    }
    ...
    


  • Nur, wenn es einen Destruktor-Aufruf zur Folge hat, sonst kannst es dir schenken. Komisch, hier gibt es irgendwie ständig die Idee, extra-Blöcke einzufügen, anstatt die Funktion weiter aufzuteilen. 😕 Die Frage nach der Stelle, wo die Variable definiert wird, stellt sich doch gar nicht, wenn die Funktion nur 4 Zeilen lang ist. Also ist die Richtlinie sowieso nicht praxisrelevant.

    void foo() {
        {
            ...
        }
        {
            ...
        }
        {
            ...
        }
        {
            ...
        }
    }
    

    Oder zieht ihr so etwas tatsächlich einem

    void foo() {
        tuedies();
        tuedas();
        ...
        tuejenes();
    }
    

    vor? Nicht wirklich, oder?



  • Unterfunktionsaufrufe schliesst mein Codefetzen doch nicht aus. Aber Du hast recht, dass ist ein manuelles Inlinen einer Funktion. Aber wenn die Funktion so speziell ist, muss es sich nicht unbedingt lohnen, das ganze auseinanderzureissen, der Uebersichtlichkeit wegen.



  • Ich finde nicht, dass es was mit speziell-sein zu tun hat. Ich kann ne Funktion immer aufteilen, und irgendwann ist die Grenze des Sinnvollen erreicht. Beispielsweise wäre es nicht mehr sinnvoll, eine Funktion zu schreiben, die mir eine int-Variable initialisiert. Amsonsten lassen sich schon wirklich fast alle Arbeitsschritte weiter sinnvoll aufteilen. Damit wird die Frage, ob Variablen an den Anfang eines Blocks gehören, komplett bedeutungslos und sehr lokal sind die Variablen auch.
    Habe ich bedeutungslos gesagt? Ja stimmt auch, aber sie wird auch beantwortet. Ja, sie gehören an den Anfang des Blocks. Die Funktion ist zwei Zeilen lang, eine legt ne Variable an, die andere macht was damit. Vertauschen kann ich es nicht. Hach, wenn man nur alle Streitfragen so eindeutig lösen könnte.



  • komisch, dass dein Beispiel oben schon mehr als 2 codezeilen pro funktion enthält


Anmelden zum Antworten