Allgemeine Umfrage: Kommentare schreiben



  • 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 😃



  • englisch sollte man nur benutzen wenn man englisch kann 😃



  • nö, besser schlechtes englisch als spanisch oder griechisch (oder deutsch, wenn ich nicht deutsch wäre)



  • Kommentare "oberhalb" von Klassen und Funktionen dokumentieren den Vertrag - was (d.h. das was auch bei Implementationsänderungen erhalten bleiben muß)

    (1) Für Klassen wird dokumentiert welche Rolle sie spielen, Interaktion mit anderen Klassen usw.
    (2) Für Funktionen und Methoden und ihre Parameter wird Funktionalität, sowie nicht offensichtliche / von Coding Standards abweichende Randbedingungen und Fehlerbehandlung dokumentiert.

    Kommentare innerhalb von Funktionen machen den Ablauf verständlich:

    (3) von der Standardlösung abweichende Konstrukte (z.B. die kleinen täglichen Tricks, Optimierungen, nicht offensichtliche notwendige Ausnahmenmbehandlung)
    (4) nicht offensichtliche Variablennamen
    (5) bei längeren Funktionsrümpfen bzw. komplex verschachtelten Blöcken (leicht hervorgehoben) die Grobstruktur

    Was "notwendig" und was "trivial" ist, ergibt sich letztendlich aus den Anforderungen des Projekts und den Fähigkeiten der beteiligten Entwickler. Konzepte die nachschlagbar sind würde ich grundsätzlich nicht beschreiben (aber als suchbaren Begriff hervorheben).



  • volkard schrieb:

    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.

    Das geht solange gut, wie die Anzahl der Klassen sich in einem überschaubaren Rahmen hält. Was noch als "überschaubar" gilt, hängt von den jeweiligen Gegebenheiten ab. Natürlich ist es prinzipiell gut, Klassen in jeweils eine eigenes Modul zu machen.

    Wenn man jedoch z.B. viele Klassen hat, die alle derselben Gruppe zuzuordnen sind, sollte man durchaus überlegen, ob man sie nicht doch in dasselbe Modul verfrachtet, damit deren Zweck leichter erkennbar ist.

    Außerdem vermeidet das unter Umständen eine Explosion von Dateien, durch die niemand mehr durchblickt. Das fängt meistens so an, daß Überlegungen angestellt werden, die vielen Klassen in mehrere Verzeichnisse aufzuteilen. Wenn die Klassen nun keine Black-Boxes sind, und Referenzen auf andere Klassen haben, oder generell abhängig von anderen Klassen sind, die durch die Verzeichnisschieberei in ganz andere Gefilde verfrachtet wurden, fängt es an, unübersichtlich zu werden.

    volkard schrieb:

    Power Off schrieb:

    , 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.

    Warum sollte man eine Klasse nicht dokumentieren? Gerade bei abstrakten oder viel genutzten Basisklassen sollte man durchaus deren Zweck dokumentieren, auch wenn der Code für den Programmierer noch so simpel aussieht. Jemand, der sich z.B. neu in das Projekt einarbeiten muß, wird es unter Umständen schwer haben, zu begreifen, wofür die Klasse wirklich verwendet wird. Eine Einführung in die Verwendung der Klasse sollte daher in der Dokumentation stehen, sowie eine Liste aller bekannten Ableitungen, so daß sich Projektbeteiligte einen Überblick über die Verwendung der Klasse verschaffen können.

    Stell Dir vor, Microsoft hätte z.B. so gehandelt, und einfach gar keine WinAPI Dokumentation gemacht ("guck doch ins Header-File, da steht alles drin -- und nee, Kommentare gibt's keine, ist ja alles offensichtlich!").

    volkard schrieb:

    Power Off schrieb:

    Jedes Attribut und jede Methode wird einzeln dokumentiert.

    jaja.

    size_t size;//die größe //rofl
    

    Glaub mir, wenn ich bei Dir Leiter der Qualitätssicherung wäre, wäre ich Dein schlimmster Alptraum! 😉

    "size_t size; // die größe" ist kein adäquater Kommentar. Das ist überhaupt kein Kommentar, sondern stellt nur das Offensichtliche fest. Das ist genauo was wie "i++; // erhöht i um 1"

    Besser wäre z.B. "size_t size; // Kantenlänge des Würfelraumschiffes in Kilometern" bzw. "i++; // Erhöht den Timer für die Selbstzerstörungssequenz um 1 Sekunde"

    Wenigstens einen Satz zu einem Attribut oder einer Methode oder einer Anweisung sollte man schon schreiben.

    Es gibt immer Leute, die den Code, den jemand anders geschrieben hat, verstehen müssen. Sonst wandert der Code unter Umständen bei einem Wechsel des Teams mehr oder weniger unbesehen im Mülleimer.

    volkard schrieb:

    Power Off schrieb:

    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.

    Da magst Du vollkommen Recht haben. Aber gib doch zu: Auch Du liest gelegentlich die Dokumentation irgendeiner Library, die Du verwendest. Stell Dir vor, es gäbe keine Doku. Was würdest Du dann machen? Richtig, alles selber schreiben.

    Das führt uns zum Hauptproblem fehlender Dokumentation: Code wird innerhalb eines Projektes mehrfach neu geschrieben, weil keine ausreichende Dokumentation für den bestehenden Code vorhanden ist.

    volkard schrieb:

    Power Off schrieb:

    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?

    Dokumentation, die jeder Lesen kann, der zumindest der Bedienung eines Webbrowsers mächtig ist.

    Solche Dokumentation kann z.B. anderen Entwicklern, oder auch Entscheidern, die über die Qualität oder die Verwendung des Codes urteilen müssen, helfen, eine Entscheidung zu treffen.

    Gute Dokumentation = höhere Rate von Code-Reuse, sowie geringere Fehlerquote, und damit niedrigere Entwicklungskosten.

    Stichwort: Einmal entwickeln, mehrfach verwenden, anstatt einmal entwickeln und dann ab in die Rundablage.

    Viele Firmen gehen Pleite, weil sie die Ressourcen, das Software-Fundament, das ihre Entwickler geschaffen haben, nicht in ausreichendem Maß wiederverwenden können, und daher die Neuentwicklung von Code durchführen, der eigentlich hätte wiederverwendet werden können. Kosten steigen, die Schulden der Firma auch, Angestellte werden entlassen, und schließlich macht die Firma dicht, bloß weil die Entwickler zu faul waren, ihren Code anständig zu dokumentieren.

    Ähnliches gilt für Open-Source-Projekte: Wenn potentielle Mitentwickler Schwierigkeiten haben, den Code zu verstehen, machen sie nicht (mehr) mit, und das Projekt kann im Sande verlaufen.

    Wenn aber z.B. ein Entwicklungsleiter sagt, "Schreibt keine Kommentare, das kostet bloß Zeit", dann ist er wirklich selber schuld.



  • Die Wahrheit liegt wie immer in der Mitte. Volkard hat zwar vom Prinzip her Recht, nämlich dass auch ohne Dokumentation immer klar sein soll, was welcher Code macht. Das geht aber nicht so weit, dass man nicht einen kurzen und prägnanten Satz über neue Methoden platzieren kann. Der kostet auch dem Enwickler nicht viel Zeit und hilft, seine Gedanken zu ordnen.

    Dein Pingeligkeit auf der anderen Seite ist ebenfalls völlig unangebracht.

    Auch dort sollte man alles dokumentieren: Wofür das Element eingesetzt wird, wie es funktioniert, was es macht, wovon es abhängig ist, usw.

    Jedes Attribut und jede Methode wird einzeln dokumentiert.

    Tragen nur dazu bei, schlechten Code mit komplizierten Beziehungen und unklarer Bedienung zu belassen, anstatt ihn noch verständlicher zu machen, nach dem Motto "also mit den 2 Seiten Doku wird wohl jeder kapieren, was das macht". Völlig sinnlose Zeitverschwendung, einen Preis kriegst du dafür nicht. Technische Daten sind interessant, ist die Sortierfunktion stable, was hat sie im worst- best- und average case für Laufzeiten? Dinge, die man in einem Satz sagen kann und wenn sie die Parameter sort(T[], Comparer<T>) muss ich nicht dazu schreiben, was wofür verwendet wird.

    Der Grad der benötigten Dokumentation hängt von der Öffentlichkeit ab. Eine Lib, die ich in 10 Projekten verwende, werde ich besonders sorgfältig dokumentieren, eine private Methode in einer 20fach privat genesteten Klasse ist mir egal.


Anmelden zum Antworten