Eure Programmierkonventionen ?



  • Hi !

    Was für Regeln/Konventionen habt ihr für eure Programm festgelegt ?
    Ich meine, benutzt ihr die Ungarischen Namenskonventionen, was eigenes (was ?)..

    Hier die Sachen die ich eigentlich bei jedem Programm beachte :

    • classes fangen mit einem C an, Anfangsbuchstaben werden GROß geschrieben --class CTestClass
    • Variablen folgen dem gleichen Muster wie Klassen, nur ohne C
      --int FooBar;
    • Membervariablen haben ein m_ vorgestellt
      --int m_FooBar;
    • In längeren Funktionen haben lokale Variablen ein l_ vorgestellt
      --int l_FooBar2;
    • Funktionen folgen dem gleichen Muster wie Variablen
    • Zu jeder Funktion kommt folgender Kommentarblock :
    //Purpose : Does nothing
    //Return Value : Success or not ?
    //Remark : May run very slow on a 286
    int FooBar ();
    
    • Kommentare und Variablen werden in Englisch geschrieben (wer sich einmal durch Spanischen Code wühlen musste weiß warum 🙂
    • Laufvariablen (for (..)) heißen l,c,i (ich benutze tatsächlich nur die 3, manchmal aber auch x,y,z in Zeichenroutinen
    • Globale Variablen/Funktionen sind PFUI !!
    • In jede .h Datei gehört ein
    #ifndef.. #define.. #endif
    

    Block

    • STL rulz und wird sooft wie möglich verwendet
    • Wenn möglich mit Referenzen Arbeiten, Pointer nur im Notfall 😉
    • In einem (größerem) Projekt sollte mindestens 10-15% des Codes aus Kommentaren bestehen

    So, mehr fällt mir im mom auch nicht ein, wie macht ihr's ? 🕶



  • In einem (größerem) Projekt sollte mindestens 10-15% des Codes aus Kommentaren bestehen

    Das ist bei mir der Fall. Allerdings sind das alles automatisch erzeugte Kommentare. Wenn man sich den Code anguckt, dann sieht man also fast keine Kommentare. Wenn man ernsthaft kommentiert, dann sollte es IMHO zu mindestens 30% Kommentaren kommen. Das bezieht sich auf Zeilen. Kommentare in einer Zeile, in der schon Code steht, sind IMHO Mist.



  • Meine Konventionen :

    • Klassen werden groß geschrieben, aber ohne "C". Alle Anfangsbuchstaben innerhalnb des Klassennamens werden groß geschrieben.
    • Variablennamen werden klein geschrieben, innerhalb des Variablennamens werden neue Anfangsbuchstaben aber groß geschrieben.
    • Membervariablen haben bei mir in C++ ein "m_" vorgestellt. In Java markiere ich sie nicht besonders.
    • Methoden haben die gleiche Groß- und Kleinschreibung, wie Variablen.
    • Konstanten bestehen nur aus Großbuchstaben, Wörter in den Konstantennamen werden durch "_" getrennt.
    • Methodennamen enthalten Verben, Klassennamen enthalten Substantive.
    • Kommentare mache ich meistens nicht, wenn doch, dann gehört folgendes da rein:
      -- Eine allgemeins Beschreibung der Methode
      -- Eine Beschreibung jedes einzelnen Parameters
      -- Eine Beschreibung des Rückgabewertes
      -- Der zulässige Wertebereich der Parameter und der Wertebereich des Rückgabewertes
      -- Besonderheiten (z.B. geworfene Exceptions,...)
      Auch Klassen können Kommentare kriegen, in denen Allgemeines über die Klasse steht.
    • Alles in Englisch!
    • in jede Headerdatei gehört : #ifndef.. #define.. #endif
    • Einrückung beträgt 3 Leerzeichen. Tabulatoren sind doof.
    • Variablennamen haben sprechende Namen, die durchaus etwas länger sein können.

    [ Dieser Beitrag wurde am 28.11.2002 um 17:54 Uhr von Gregor editiert. ]

    [ Dieser Beitrag wurde am 28.11.2002 um 18:52 Uhr von Gregor editiert. ]



  • classes fangen mit einem C an, Anfangsbuchstaben werden GROß geschrieben
    class CTestClass

    ungarisch notation ist unter C++ nicht nötig, von der MFC wird das C blos als einer art Namespace benutzt, also blos weg mit den C

    Variablen folgen dem gleichen Muster wie Klassen, nur ohne C
    int FooBar;

    ich schreibe mit ein kleinen anfangsbuschstaben,

    Membervariablen haben ein m_ vorgestellt
    int m_FooBar;

    habe ich auch gemacht, bin jetzt auf den fooBar_ zug aufgesprungen und wenn volkard recht hat mache ich irgen wan fooBar

    In längeren Funktionen haben lokale Variablen ein l_ vorgestellt
    int l_FooBar2;

    ich schreibe keine langen Funktionen 🙂 und
    http://fara.cs.uni-potsdam.de/~kaufmann/?page=GenCppFaqs&faq=Declare#Answ

    Kommentare und Variablen werden in Englisch geschrieben (wer sich einmal durch Spanischen Code wühlen musste weiß warum 🙂

    schreibe zu zeit deutsch mit etwas englisch, aber nur aus faulheit bei mein nähsten Projekt fange ich dan komplet mit en an

    Laufvariablen (for (..)) heißen l,c,i (ich benutze tatsächlich nur die 3, manchmal aber auch x,y,z in Zeichenroutinen

    Globale Variablen/Funktionen sind PFUI !!

    Funktionen auch? ich finde nicht alles läst sich in eine Klasse packen

    In jede .h Datei gehört ein

    #ifndef.. #define.. #endif
    

    Block

    ohne wäre ein Fehler

    STL rulz und wird sooft wie möglich verwendet

    jup wenn du noch nicht so viele erfahrungen hast dan mit gewalt STL überall reinzwingen um welche zu sammeln, später darfs du dan entscheiden wo stl der schlechtere weg ist

    Wenn möglich mit Referenzen Arbeiten, Pointer nur im Notfall 😉

    jup erspart mich vom if(pointer)

    In einem (größerem) Projekt sollte mindestens 10-15% des Codes aus Kommentaren bestehen

    offt kommt es mir vor als ob mache erwarten das man in den komentaren gleichen noch ein anfänger tut schreibt,
    einige nutzen komentare auch als wieder gut machung wenn sie keine vernünftigen Funktions oder variablen namen finden können oder wollen
    naja habe noch nie sonderlich viel komentiert oder viel code lesen müssen der komentiert bzw. unkomentiert ist, deswegen kann ich den nutzen/kosten efekt noch nicht abschätzen



  • Klassen (eigentlich alle Typen) beginnen mit Großbuchstabe.
    Funktionen, Variablen usw. alles klein.

    Lange Funktionen das man lokale da mit 'nem l_ oder so kennzeichnen müsste gibt es nicht 🙂
    Globale Variablen sowieso nicht.

    Globale Hilfs-Funktionen oder so die ich in libs verfrachtet hab beginnen mit Großbuchstabe.

    Was mich mal interessieren würde ist, ob die Mehrheit get/set-Methoden alle mit get/set kennzeichnet.
    Einerseits find ich getBlub() schlecht zu schreiben und zu lesen so das ich's am liebsten nur blub() nennen würde, andererseits gibts dann Namenskonflikte und ich müsste die member mit m_ oder sowas kennzeichnen. Das gefällt mir genauso wenig.

    Da kann ich mich irgendwie garnicht entscheiden 😕



  • Original erstellt von Headhunter:
    Was für Regeln/Konventionen habt ihr für eure Programm festgelegt?

    Ich versuche mittlerweile, mich an den Mozilla Coding Guide zu halten - zumindest hinsichtlich Code-Formatierung und Namenskonventionen.



  • ich hab mir mal folgende konvention ausgedacht und benutze sie seit kurzem konsequent. hab versucht so kleine präfixe wie möglich zu finden die trotzdem aussagekräftig sind.

    Datentyp/Präfix/Beispiel
    ----------------------------------------------------------------------------

    char -> c -> cBuchstabe
    unsigned char -> uc -> ucMeineZahl
    int -> i -> iZahl
    unsigned int -> ui -> uiGrosseZahl
    short int -> w -> wMittelgrosseZahl
    unsigned short int -> uw -> uwVorzeichenloseMittelgrosseZahl
    float -> f -> fGleitkommazahl
    double -> d -> dGrosseGleitkommazahl
    long double -> l -> lSehrGrosseGleitkommazahl
    struct xyz -> st -> stHauptstruktur
    size_t (jeder Systemdatentyp)-> sd -> sdDatentyp
    Objekt abc -> o -> oAutos
    string -> s -> sMeinName
    bool -> b -> bAussage
    enum -> e -> eFarben
    Konstante -> k -> kBias

    Bei jedem Zeiger-Datentyp hänge ich ein "p" pro Zeigerinstanz an
    das bestehende Präfix.

    Beispiel:

    int *ipZahl;
    int **ippZahl;

    😉

    [ Dieser Beitrag wurde am 28.11.2002 um 18:31 Uhr von tenim editiert. ]



  • Original erstellt von Gregor:

    • **Kommentare mache ich meistens nicht, wenn doch, dann gehört folgendes da rein:
      -- Eine allgemeins Beschreibung der Methode
      -- Eine Beschreibung jedes einzelnen Parameters
      -- Eine Beschreibung des Rückgabewertes
      -- Der zulässige Wertebereich der Parameter und der Wertebereich des Rückgabewertes
      -- Besonderheiten (z.B. geworfene Exceptions,...)
      **

    Interessant. Schau Dir mal folgende Funktion an:

    Success isProcessFinished(const AutomaticProcess& automaticProcess,
                              FieldValues& fieldValues,
                              unsigned startStep,
                              unsigned endStep) throw ExProcessError
    {
       assert(startStep <= endStep);
       assert(startStep < automaticProcess.getCount());
       assert(endStep < automaticProcess.getCount());
       assert(!automaticProcess.isEmpty());
    
       ...
    
       return result;
    }
    

    Inwiefern würde diese Funktion durch Deinen Kommentarkopf nun noch aufgewertet? Bei so einer Funktion kann der Kommentarkopf alles nur schlechter machen... vor allem wenn er dann irgendwann vom tatsächlichen Kopf auseinanderdriftet - und das tun sie immer! Spätestens in der Testphase wo der Zeitdruck zunimmt.

    Ich sehe also die grundsätzliche Notwendigkeit jeden Krempel des Funktionskopfes auch noch mal zu kommentieren nicht unbedingt. Vielleicht nett was die Funktion grundsätzlich tut... aber z.B. zulässige Wertebereiche, ganz heißes Eisen, das wird doch nie nachgepflegt.

    Auf der einen Seite predigen wir immer "nehmt Konstanten", aber gleichzeitig schreiben die Leute dann sowas:

    /* ...
       param zwischen 0 und 31
    */
    void anyFunc(unsigned param)
    {
       if ( (param >= 1) && 
            (param <= 31) )
       ...
    }
    

    Würde die erste 0 im Code vorkommen sagt jeder "Konstante dafür anlegen, damit man nur eine Stelle ändern muß". Lustigerweise gilt das für Kommentare aber irgendwie nicht...



  • Also ich verusche mich möglichst immer da dran zu halten:
    http://www.cuj.com/link/subject21.htm?topic=link



  • @ Marc++us : OK! Es gibt Stellen, an denen Kommentare überflüssig sind. Wenn die Parameternamen aussagekräftig genug sind, dann reicht das oft. Wenn eine Methode allgemeiner gehalten (bzw. abstrakter) gehalten ist, dann reicht es IMHO meistens nicht. Meistens kommentiere ich ja auch nicht (Hast du meinen ersten Satz überlesen?).

    Natürlich kann ich als Code-Fremder mit deinem Code so nichts anfangen. Mir ist z.B. nicht klar, warum kein bool zurückgegeben wird. Auch die Parameter sagen mir natürlich recht wenig. Was mich interessieren würde, wäre, wann z.B. die Exception eworfen wird.

    Hier jetzt mal eine Klasse aus meinem aktuellen Java-Projekt. Denkst du nicht, dass die ein paar Kommentare nötig hätte?

    [java]
    package image.pixelConverter;

    import image.*;

    public class HueConverter implements PixelConverter
    {
    public HueConverter ()
    {
    }

    public float convert (int rgbValue)
    {
    double red = ((double)(((int)rgbValue >> 16) & 0x000000ff))/255.0;
    double green = ((double)(((int)rgbValue >> 😎 & 0x000000ff))/255.0;
    double blue = ((double)(rgbValue & 0x000000ff))/255.0;
    if ((red == green) && (red == blue)) return -1.0f;
    double hue = Math.acos (((red - 0.5*(green+blue))/
    Math.sqrt((red-green)(red-green)+(red-blue)(green-blue))));
    if (blue > green) hue = 2.0 * Math.PI - hue;
    return (float) hue;
    }

    public short convertNormalized (int rgbValue)
    {
    return (short)Math.round(convert (rgbValue) * 127.5 / Math.PI);
    }
    }[/code]



  • Kommentare im Code -> JA, in Form von Überschriften. Ich würde das nicht über den Funktionskopf schreiben.

    [java]
    public float convert (int rgbValue)
    {
    // RGB-Anteile ausmaskieren und auf 1 normieren
    double red = ((double)(((int)rgbValue >> 16) & 0x000000ff))/255.0;
    double green = ((double)(((int)rgbValue >> 😎 & 0x000000ff))/255.0;
    double blue = ((double)(rgbValue & 0x000000ff))/255.0;

    // Grauwerte erkennen
    if ((red == green) && (red == blue)) return -1.0f;

    // Farbwert aus spektralem Farbrad ermitteln
    double hue = Math.acos (((red - 0.5*(green+blue))/
    Math.sqrt((red-green)(red-green)+(red-blue)(green-blue))));
    if (blue > green) hue = 2.0 * Math.PI - hue;
    return (float) hue;
    }
    }[/code]

    Sorry - couldn't resist. 😉

    Aber die Forderung nach der Auskommentierung der Köpfe ist falsch. Das führt oft dazu, daß die Funktionsköpfe die einzigen Programmteile - umrahmt von vielen ****** und ------ - sind, die kommentiert wurden. Im Code dagegen sind keine Kommentare zu finden. Dabei sind sprechende Funktionsköpfe noch leichter zu finden als sprechende Algorithmen.



  • Naja! Vielleicht gibt es da auch Unterschiede zwischen Java und C++. Wenn ich in Java eine Methode benutzen möchte, dann gucke ich mir normalerweise die Javadoc-Dokumentation dazu an, nicht den Quellcode (es sei denn, es kommt sehr auf Performance an). Wenn es dann keine Kommentare über dem Methodenkopf gibt, dann fehlt mir in diesem Fall z.B. folgendes :

    1. rgbValue : Wie stecken da r,g,b eigentlich drin? Kann letztendlich auf alle möglichen Arten angeordnet sein. Kann auch sein, dass mit einem 16-Bit RGB-Wert gerechnet wird.

    2. Grauwerte : Was passiert mit denen überhaupt. Ohne Kommentare weiß man nicht, dass dann -1 zurückgegeben wird.

    3. Wertebereich des Rückgabewertes : Kann ohne Kommentare alles mögliche sein. Könnte auch auf einen Wert zwischen 0 und 1 normalisiert sein, oder auf einen Wert zwischen 0 und 255.



  • ...
    Und schon haben wir einen wunderschönen Flamewar 🙄



  • Original erstellt von Headhunter:
    ...
    Und schon haben wir einen wunderschönen Flamewar 🙄

    Aha? Meinst du mich und Marc++us? Gib mal ein Beispiel für geflame. Ich sehe keins.

    ...oder darf ich das Wort "Java" nicht mehr benutzen? Ich habe da ja noch nichtmal irgendeine Wertung abgegeben!



  • ich mach es eigentlich aehnlich wie Dimah 🙂

    aber:

    membervariablen nicht extra kennzeichne.

    als Laufvariablen nehme, wie es sich eingebuergert hat: i,j,k

    und pointer <-> referenzen: jedes zu seiner Zeit 😉

    meine Kommentare sind englisch und ich wuerde sagen ziemlich aehnlich wie Marc++us es vormacht 😉 ausserdem dokumentiere ich gerne mit doxygen.



  • Tabulatoren sind doof.

    Sicher das du das ernst meinst? Dann hast du nämlich keine Ahnung. Leerzeichen sind doof. :p



  • Also bei der Funktion isProcessFinished könnte man noch die Preconditions und wenn's gibt auch die Postconditions kommentieren 😕



  • Original erstellt von <Falsch>:
    Sicher das du das ernst meinst? Dann hast du nämlich keine Ahnung. Leerzeichen sind doof. :p

    Hast du dir schonmal Code mit Tabulatoren im Windows-Editor angeguckt? ...oder in einem anderen einfachen Editor? Ich möchte nicht für alles gleich ne IDE starten, trotzdem möchte ich, dass der Code überall lesbar ist (auch für Leute, die keine IDE haben, wo man die Tab-Größe einstellen kann).

    [ Dieser Beitrag wurde am 28.11.2002 um 21:38 Uhr von Gregor editiert. ]



  • Mein Testprojekt:

    //header
    
    #include <vector>
    
    namespace david {
    
    template <typename T, typename U, typename V, typenamw W, int INGROSZ>
    class Foo {
    //typedefs, classes, types halt
        typedef std::vector<std::vector<T> > NetterTyp;
    
    //Variablen
        int einSehrAussageKraeftigerNameDadurchLerntManSchnellSchreiben;
    
    //get/set    
        int getEinSehrAussageKraeftigerNameDadurchLerntManSchnellSchreiben () const;
        void setEinSehrAussageKraeftigerNameDadurchLerntManSchnellSchreiben (int ein SehrAussageKraeftigerNameDadurchLerntManVielSchreiben);
    
    //funktionen
        T start ();
        T stop ();
    
        T startSmoking ();
        T stopSmoking ();
    
        T doSmoking ();
        T resumeSmoking ();
        T pauseSmoking ();
    
        bool isSmoking () const;
        bool invertBool ();   //returns last value of Bool
    
        void run (); //nur void (void) mit run Präfix!
    
    /*
        Anmerkung: Ich nehme immer nur
        start, stop, do, resume, pause, end, is, invert, exec, run
        als Präfix für Memberfunktionen (oder als einziger Name, bei einer Klasse 
        "Applikation" z.B. ist ja dann logisch Application::run()
    */
    public:
    
        Foo (int einSehrAussageKraeftigerNameDadurchLerntManSchnellSchreiben = 0);
    };
    
    }
    //unit
    #include "header"
    /*namespace david {
       using namespace std;
    }*/ //Maybe...
    using namespace david;
    Foo::Foo (int einSehrAussageKraeftigerNameDadurchLerntManSchnellSchreibenAberWennDerNameZuLangIstKuerzeIchIhnNatuerlichAufJedenFallMitEinemUnterstrichDanach_) :
    einSehrAussageKraeftigerNameDadurchLerntManSchnellSchreiben(einSehrAussageKraeftigerNameDadurchLerntManSchnellSchreibenAberWennDerNameZuLangIstKuerzeIchIhnNatuerlichAufJedenFallMit EinemUnterStrichDanach_)
    {}
    
    //M$ VC++: #define for if(1)for
    
    template <typename T, ... >
    T
    Foo<T>::startSmoking () {
       for (int i = 0; i < 1000; ++i) {
         for (int j = 0; j < 1000; ++j) {
           for (int k = 0; k < 1000; ++k) {
              Sleep(10); //ahh Smoking...
           }
         }
       }
       stopSmoking ();
    }
    
    template ...
    T
    Foo::stopSmoking () {
       while (true) {
          cout << "No!" << endl;
          resumeSmoking ();
       }
    }
    
    T
    Foo::resumeSmoking () {
        if (getEinAussageKraeftigerNameDadurchLerntManSchnellSchreiben() != INGROSZ) 
          cout << "Damned!" << endl;
          startSmoking ();
          return;
        pauseSmoking ();
        resumeSmoking ();
    }
    
    T
    Foo::pauseSmoking () {
        while (getEinAussageKraeftigerNameDadurchLerntManSchnellSchreiben() < INGROSZ) {
           cout << "I need more cigarettes!!!" << endl;
           setEinAussageKraeftigerNameDadurchLerntManSchnellSchreiben(getEinAussageKraeftigerNameDadurchLerntManSchnellSchreiben()+1);
        }
    }
    
    void
    Foo::run () { //Der Haupt Treiber
       start ();
       startSmoking ();
       stop ();
    }
    
    T
    Foo::start () {
       cout << "Welcome! Smoke?" << endl;
       string input;
       getString (input, isSetTo<string> ("Yes"), "Ungueltig! Nochmal eingeben: "); //eigene Nette kleine (template)Funktion
    }
    
    //main
    #include "header"
    
    int main () {
       Foo smokingApp;
       smokingApp.run ();
     //no need for return...
    }
    

    [ Dieser Beitrag wurde am 28.11.2002 um 21:06 Uhr von Noesis editiert. ]

    [ Dieser Beitrag wurde am 28.11.2002 um 21:07 Uhr von Noesis editiert. ]

    [ Dieser Beitrag wurde am 28.11.2002 um 21:08 Uhr von Noesis editiert. ]



  • wenn du das wirklich mit leerzeichen machst, hast du aber viel zu tun. 🙄


Anmelden zum Antworten