Allgemeine Umfrage: Kommentare schreiben



  • Hallo Leute
    Ich mache mir derzeit Gedanken darüber wie guter Kommentar aussehen sollte. Wie sieht z.B. ein guter Kommentar für eine Klasse aus, oder für eine Klassenmethode usw. Was für Informationen sollten vorhanden sein?
    Welche Informationen sollten im Kopf einer Sourcedatei drinnstehen?

    Gruss Ishildur



  • Welche Informationen sollten im Kopf einer Sourcedatei drinnstehen?

    die, die notwendig sind. also im allgemeinen nichts. wenn es notwendig ist, einen copyrightvermerk des arbeitgebers reinzumachen, dann halt rein damit. bitte nicht die ganze lizenz, das nervt. eine zeile sollte reichen. in deutschland sind copyrightvermerke unnötig, denn der code ist urheberrechtlich geschützt auch ohne vermerk. autor ist echt selten sinnvoll. datum der letzen änderung? dafür habebn wir ein dateisystem. datum der ersten änderung? wozu? name der datei? ja, das ist ein bringer. hihi. also lass den kopf leer.

    Ishildur schrieb:

    Ich mache mir derzeit Gedanken darüber wie guter Kommentar aussehen sollte.

    der beste kommentar ist einer, der nicht da ist.

    Wie sieht z.B. ein guter Kommentar für eine Klasse aus

    manchmal labere ich. wie hier.

    #ifndef HEAP_HPP
    #define HEAP_HPP
    
    #include "Vector.hpp"
    
    #include "iostream.hpp"
    #include "types.hpp"
    
    //Ein Heap ist ein Binärbaum mit der Bedingung, daß jeder Knoten kleinergleich 
    //seinen beiden Kindern (falls vorhanden) ist. Diese Implementierung als Array 
    //garantiert außerdem, daß der Baum ballanciert ist. 
    //Einfügen eines beliebeigen Elements und Ausfügen des kleinsten haben nur 
    //logarhitmischen Zeitbedarf. Weil die Integritätsbedingung schwächer als beim 
    //normalen Binärbaum ist, ist der Heap auch ein wenig schneller.
    
    template<typename Data,Size size=0,bool onHeap=(size==0||size>4096)>
    class Heap{
    private:
    	Vector<Data,size,onHeap> vector;
    public:
    ...
    

    also als klassenkommentar ne allgemeine beschreibung. sowas fängt aber nur eine von 50 klassen, höchstens.

    , oder für eine Klassenmethode usw.

    es gibt bei mir keine kommentierte methode, soweit ich mich erinnere.

    ne ein paar funktionen mit kommentaren hab ich auf der platte.

    bool isPrime(u32 n){
    	//die kleinsten primzahlen direkt nachschauen
    	if(n<32) return getBit(0xa08a28ac,u32(n));
    
    	//teiler 2 hardcoded
    	if(n%2==0) return false;
    
    	//teiler 3, 5 und 7 mit nur einer multiplikation
    	if(!canBePrimeCheckFactors357WithTableLookup(n)) return false;
    
    	//kleine primzahlen durch wheel factorization erkennen
    	if(n<16384) return isPrimeCheckFactorsAbove7ByWheelFactorization(n);
    
    	//basis, die mit diesen vortests am meisten erkennt
    	if(n<197209) return isSPRP(n,3570734776u);
    
    	//laut unvollstõndiger suche
    	if(n<39371141) return isSPRP(n,3415)&&isSPRP(n,3584);
    
    	return isSPRP(n,2)&&isSPRP(n,7)&&isSPRP(n,61);
    	/*
    	If n < 9,080,191 is a both 31 and 73-SPRP, then n is prime. 
    	If n < 4,759,123,141 is a 2, 7 and 61-SPRP, then n is prime. 
    	If n < 1,000,000,000,000 is a 2, 13, 23, and 1662803-SPRP, then n is prime. 
    	*/
    }
    

    oder

    inline u64 mulModUnguarded(u64 a,u64 b,u64 m){
    	ASSERT(a<m && b<m);
    //TODO: if(b<a) swap(b,a) oder sowas
    	u64 x=0;
    	while(b!=0){
    		while((b%2)==0){
    			b/=2;
    			a=addModUnguarded(a,a,m);
    		}
    		--b;
    		x=addModUnguarded(x,a,m);
    	}
    	return x;
    }
    

    oder

    inline u32 powModUnguarded(u32 a,u32 b,u32 m){
    	ASSERT(a<m);
    //TODO: evtl umdehen nach 
    //http://www3.sympatico.ca/michel.langlois2/archive/prime_cpp.htm
    	u32 x=1;
    	while(b!=0){
    		while((b%2)==0){
    			b/=2;
    			a=mulModUnguarded(a,a,m);
    		}
    		--b;
    		x=mulModUnguarded(x,a,m);
    	}
    	return x;
    }
    

    Was für Informationen sollten vorhanden sein?

    du mußt auf jeden fall erstmal trennen zwischen schule/hochschule und ectem leben. die lehrer/profs verlangen nen riesigen header, damit sie mit den abgegebenen dateien nicht durcheinanderkommen. und sie verlangen viele kommentare, weil sie code nicht flüssig lesen können. und weil der code oft genug falsch ist, dann kann man aus den kommentaren wenigstens ersehen, was das werden sollte. leider erzählen sie dabei den schülern auch, daß es total sinnvoll sei, viele kommetare zu machen und so nen mist. und die schüler glauben es.

    guter code braucht keine kommetare oder so in der richtung.



  • Das ist ganz einfach: Im Idealfall (wenn man genug Zeit zum Dokumentieren hat), steht im Header einer ".h"-Datei (bei C++) bzw. ".java"-Datei (bei Java), welche Klassen enthalten sind, und eine Grobbeschreibung der Klassen. Vor jeder Klassendefinition steht ein Kommentar, der die Klasse genau beschreibt, was sie tut, und wie sie verwendet wird. Jedes Attribut und jede Methode wird einzeln dokumentiert. Auch dort sollte man alles dokumentieren: Wofür das Element eingesetzt wird, wie es funktioniert, was es macht, wovon es abhängig ist, usw.

    Programme, wie "javadoc" z.B. erlauben es, aus dem Programmtext die eingebetteten Kommentare herauszuziehen und z.B. in HTML zu konvertieren. Je umfangreicher und detaillierter die Informationen sind, desto besser.



  • Power Off schrieb:

    Das ist ganz einfach: Im Idealfall (wenn man genug Zeit zum Dokumentieren hat), steht im Header einer ".h"-Datei (bei C++) bzw. ".java"-Datei (bei Java), welche Klassen enthalten sind

    ja. genau eine. und die hat genau den namen der datei ohne .cpp oder .hpp.

    , und eine Grobbeschreibung der Klassen

    außer natürlich, die klasse ist trivial und es ist schon am namen offensichtlich, was sie macht und was sie ist. mach besser kleine klassen und befolge "ein zweck - eine klasse" und hau die kommentare raus.

    Vor jeder Klassendefinition steht ein Kommentar, der die Klasse genau beschreibt, was sie tut, und wie sie verwendet wird.

    außer natürlich, die klasse ist trivial und es ist schon am namen offensichtlich, was sie macht und was sie ist. mach besser kleine klassen und befolge "ein zweck - eine klasse" und hau die kommentare raus.

    Jedes Attribut und jede Methode wird einzeln dokumentiert.

    jaja.

    size_t size;//die größe //rofl
    
    Auch dort sollte man alles dokumentieren: Wofür das Element eingesetzt wird, wie es funktioniert, was es macht, wovon es abhängig ist, usw.
    

    wir leben echt in verschiedenen welten.

    Programme, wie "javadoc" z.B. erlauben es, aus dem Programmtext die eingebetteten Kommentare herauszuziehen und z.B. in HTML zu konvertieren. Je umfangreicher und detaillierter die Informationen sind, desto besser.

    was hat man davon?

    Kommentare



  • Für (öffentliche) Methoden und Klassen würde ich mindestens einen ganzen Satz schreiben. Variablen... naja, selten mehr als 3 Worte.
    Nach oben ist natürlich alles offen.

    Auch für vermeintlich einfache Dinge lohnt sich ein Kommentar. Wenn später in dem automatisch generierten HTML-File "Point" steht, musst du doch nachschlagen was denn ein "Point" genau ist. Wenn "Point - A 2 dimensional Point based on two integers (32 bit)." steht, ist der Fall klar.

    Dass Interfaces nie genug Kommentar haben können, ist wohl klar. 😉

    Vergiss "selbsterklärenden Code", das gibt es einfach nicht. Jeder denkt ein bisschen anders, und was für den einen selbsterklärend ist, findet der andere unverständlich. Besonders schlimm wird das, wenn Leute mit unterschiedlicher Programmiererfahrung zusammenarbeiten müssen.
    Das bedeutet nicht, dass du jede Zeile erklären musst, aber das "grosse Bild" sollte erklärt sein.

    Achja: Syntaxelemente musst du nicht erklären. Syntax versteht man entweder, oder man lernt ihn.

    Und: schreib kein Blabla. Die Kommentare werden von Technikern gelesen. Die Techniker sind nicht an deinem Lebenslauf, oder an faulen Witzen interessiert, sie wollen Informationen 😉



  • nehmt volkard nicht soo ernst, er programmiert eh nur triviale sachen



  • ne also da muss ich volkard schon recht geben. kommentiert wird das was nicht verständlich ist, oder z.b. ein besonderes verfahren. nichts ist nerviger als fremden code weiterzubearbeiten wo (z.b.) bei einer einfachen verketten liste be jeder variable steht wofür sie ist, etc. z.b so:

    // Linked List ist eine verkettete Liste, die Objekte speichert.
    public class LinkedList
    {
       public Object *head(); // gibt das erste element wieder
       ... 
       private int objCount; // anzahl gespeicherter objekte
    };
    

    diese kommentare sind sinnlos, weil jeder weis was gemeint ist. wenn du hingegen speziell kryptisches zeug machst, irgendwelche verXORungen oder sowas, dann soltle mans hinschreiben.
    das argument, dass es in der extrahierten doku dann scheisse aussieht ist auch käse. gerade für die einfachen teile eines softwareteils benutze ich (und sicher die meisten) einfach ein UML diagramm das die zusammenhänge zeigt. in kombination mit eindeutigen klassennamen (ein zweck - eine klasse) ist das idiotensicher.



  • Eine History mit den Veränderungen muss rein!



  • Wer entscheidet nach welchen Kriterien was "jeder weiss", und was "kryptisches Zeug" ist?
    Wie geht deine LinkedList mit "null" um? Was passiert wenn "head" aufgerufen wird, aber die Liste leer ist (hätte es einen Kommentar, müsste ich das nicht fragen 😉 )?

    Woher soll ich wissen, das "public Object *head();" nicht den Kopf entfernt? Es gibt keine Regel die besagt, dass eine Methode namens "head()" nicht den Kopf entfernen soll.
    Die Worte des Autors nachdem der wütende Kunde 12 Stunden nach dem Fehler suchte: "ach, es ist doch offensichtlich, dass head den Kopf entfernt. Wenn Sie ihn nur anschauen wollen, dann nehmen Sie selbstverständlich get!"

    <Wer etwas überspitze Formulierungen findet, darf sie behalten ;)>



  • Dann würde ich eher behead nehmen ^^



  • Veränderungshistorie ist nicht schlecht, aber kann auch gut über versionsmanagment machen. dass die methode head() den kopf liefert, kann man dann schon annehmen, da es gewisse coding-standards und so "ungeschriebene gesetze" (naja, im softwareengeneering schon geschreiben...) dass funktionen das machen was sie versprechen. also eine head() methode nicht die ganze liste löscht. weicht eine selbstverständliche funktion von dem erwartet ab, dann sollte mans kennzeichen. übertriebener kommentiereifer ist ausserdem eine produktivitätsbremse 🙂



  • Ich benutz gerne doxygen. Aber Kommentare versuche ich auf wenige Funktionen zu beschränken. Eigentlich kann man sehen, dass das Design überdacht werden sollte, wenn eine Funktion nicht offensichtlich verständlich ist 🙂

    Wenn man einen Hack oder merkwürdige Optimierungen einbaut, sollte man den Sinn auch kommentieren. Ansonsten sind die meisten Kommentare von mir in der Form //todo: <...>, //debug oder //!!!!!! 😉



  • Entweder alle (Member-)Funktionen dokumentieren oder gar keine!



  • alles oder nichts schrieb:

    Entweder alle (Member-)Funktionen dokumentieren oder gar keine!

    wieso? Macht es Sinn eine Funktion ala begin oder size zu erklären, nur weil man Details über eine Funktion ala send erklärt?



  • Was ein guter Kommentar ist, haengt davon ab, fuer wen er gedacht ist.
    Ich programmier die meiste Zeit nur fuer mich selbst, deshalb versuche ich nur Dinge zu kommentieren, die ich nach 6 Monaten evtl. nicht mehr wissen koennte (weil ich keine separaten Designdokumente aufbewahre) oder weil ich mir dadurch Zeit spare, wenn ich die Klasse spaeter mal wiederverwenden will und mich dann nicht nochmal durch den ganzen Code denken muss. Das kann dann z. B. so aussehen:

    /**
     * collects all recieved KeyPressed-Events in a Queue.
     * Before accessing the collected events, startNewQueue() must be called,
     * then the events collected can be queried by getKeys(). Events recieved
     * whilst querying will be safed in a temporary queue. A call to reset()
     * makes that temporary queue the new mainQueue.
     * The collector should be threadsafe, meaning it's no problem if the GUI
     * thread hands in new key-evens while another thread calls a public
     * method.
     *
     * So typically the queue should be used like this:
     *
     * while (we need to collect the keys)
     * 	startNewQueue()
     * 	getKeys()
     * 	...       // process the collected keys
     * 	getKeys() // if needed, we can call getKeys() again, receiving the same
     *            // collection again
     * 	reset()
     * 
     *
     * @author Thomas Unterthiner
     *
     */
    class KeyCollector extends KeyAdapter
    {
    	private Collection<KeyEvent> actualQueue;
    	private Collection<KeyEvent> tmpQueue;
    
    	public KeyCollector()
    	{
    		actualQueue = new LinkedList<KeyEvent>();
    		tmpQueue = null;
    	}
    
    	public void keyPressed(KeyEvent e)
    	{
    		addKey(e);
    	}
    
    	private synchronized void addKey(KeyEvent e)
    	{
    		if (tmpQueue == null)
    			actualQueue.add(e);
    		else
    			tmpQueue.add(e);
    	}
    
    	/**
    	 * Returns the keys collected so far
    	 * 
    	 * @return all the KeyEvents collected since the last call of
    	 *         reset()
    	 */
    	public Collection getKeys()
    	{
    		return actualQueue;
    	}
    
    	public synchronized void reset()
    	{
    		actualQueue = tmpQueue;
    		tmpQueue = null;
    	}
    
    	public synchronized void startNewQueue()
    	{
    		if (tmpQueue != null)
    			throw new IllegalStateException();
    
    		tmpQueue = new LinkedList<KeyEvent>();
    	}
    }
    

    gleiches gilt auch fuer Methoden. Wobei ich's mir oft spare, Methoden zu kommentieren, die eh offensichtlich sind.
    Ab & an stecken in den Methodenkommentaren aber auch Designentscheidungen und Ablaufserklaerungen, weil ich oft die Kommentare schreib noch bevor ich ueberhaupt die Methode selbst ausprogrammiere, und dann quasi im Kommentar fuer mich selbst "plane" was die Methode eigentlich tun soll:

    /**
    	 * reads the formulas for generating the colors out of a file.
    	 * The colors will then be generated and the "colors" field be filled.
    	 * The file must already be positioned at the right position.
    	 * NOTE: the "colors" field must already have been created.
    	 * 
    	 * @param f a valid, opened and right-positioned File
    	 * 
    	 */
    	private void readFormulas(BufferedReader f) throws IOException
    	{
    		// ....
    

    Wuerd ich jetzt allerdings mit mehreren Leuten zusammenarbeiten bzw. wissen, dass andere meine Kommentare auch lesen muessen, dann wuerden sie wohl anders aussehen.



  • ernst´ schrieb:

    nehmt volkard nicht soo ernst, er programmiert eh nur triviale sachen

    stimmt schon. eigentlich schreibe ich nur triviale sachen.
    manchmal braucht's leider mehrere anläufe, bis sie trivial sind.



  • Blue-Tiger schrieb:

    Ich programmier die meiste Zeit nur fuer mich selbst, deshalb versuche ich nur Dinge zu kommentieren, die ich nach 6 Monaten evtl. nicht mehr wissen koennte (weil ich keine separaten Designdokumente aufbewahre) oder weil ich mir dadurch Zeit spare, wenn ich die Klasse spaeter mal wiederverwenden will und mich dann nicht nochmal durch den ganzen Code denken muss.

    kannst stattdessen auch den code verbessern und nur das allernötigste kommentieren. ich meinen c++-code ab 1997 heute noch eigentlich flüssig lesen. meinen perl- und php-code allerdings nicht. da mach ich immernoch zu große funktionen und so schlimme sachen.



  • Ich sehe das eigentlich ähnlich, Code sollte selbsterklärend sein. Wenn Kunden verlangen, dass ich den Code besonders kommentiere, dann mache ich das natürlich, aber wenn ich z.B. folgende Klasse habe:

    class Widget {
    public:
        Widget();
    
        int  getX();
        void setX(int _x);
        int  getY();
        void setY(int _y);
    
        ...
    };
    

    Was nützt mir das, wenn ich an jede Methode dranschreibe, dass diese entsprechend x bzw. y setzt bzw. zurückliefert?
    Warum sollte ich an den Konstruktor schreiben, dass dieser mir ein Objekt vom Typen Widget konstruiert?

    Wenn ich eine Methode/Funktion gekoppelt mit Rückgabewert, Namen und Parameter sehe, dann sollte klar sein, was da passiert. In den doch eher seltenen Fällen, wo das nicht der Fall ist, danns schreibt man eben einen kurzen Kommentar dazu und gut ist.
    Evtl. kann man noch bestimmte Parameter erklären, wenn diese nicht ganz klar sind, aber dann muss wirklich gut sein.

    Anders würde es bei einer Funktion aussehen, die normalerweise einen zu langen oder evtl. mißverständlichen Namen hätte, wobei meine Namenswahl hier wahrscheinlich auch nicht gerade glücklich ist:

    // converts a std-html formatted color in reverse order (eg. for windows)
    int RGB2BGR(int _color);
    

    Da schreibt man dann kurz was dran und dann ist gut.

    Zu der Sache mit dem "Point": Eigentlich dürfte es fast egal sein, ob ein Punkt nun 2 oder 3 Koordinaten hat, um das Programm zu verstehen und wenn man mehr damit machen will bzw. auf die Koordinaten zugreifen will/muss, dann guckt man sich kurz das Struct (oder die Klasse) an und weiß Bescheid. Dann sieht man dann auch wahrscheinlich, dass es noch einen "Point3D" oder soetwas gibt. 🙂

    Ansonsten bin ich aber ein Fan von Copyright-Informationen und Hinweisen auf den Ersteller im Head, das stört den Code aber nicht wirklich, der fängt halt nur etwas weiter unten in der Datei an, aber der Kommentar ist ja nicht mitten im Code, sondern nur einmal oben drüber.



  • Blue-Tiger schrieb:

    Was ein guter Kommentar ist, haengt davon ab, fuer wen er gedacht ist.
    Ich programmier die meiste Zeit nur fuer mich selbst, deshalb versuche ich nur Dinge zu kommentieren, die ich nach 6 Monaten evtl. nicht mehr wissen koennte [...]

    Wieso schreibst Du die Kommentare dann nicht auf deutsch? :p



  • Apollon schrieb:

    Blue-Tiger schrieb:

    Was ein guter Kommentar ist, haengt davon ab, fuer wen er gedacht ist.
    Ich programmier die meiste Zeit nur fuer mich selbst, deshalb versuche ich nur Dinge zu kommentieren, die ich nach 6 Monaten evtl. nicht mehr wissen koennte [...]

    Wieso schreibst Du die Kommentare dann nicht auf deutsch? :p

    hmm... gute Frage.... 😕 wohl Gewohnheit 😃


Anmelden zum Antworten