When to comment your code

 
01 mei 2012

Het is een goede gewoonte om je code altijd in vorm van commentaar toe te lichten aan collega ontwikkelaars om onduidelijkheid en misverstanden te voorkomen. Echter wordt in het boek ‘Clean Code’, geschreven door Robert C. Martin, juist gezegd zo min mogelijk commentaar te schrijven bij de code, en in plaats daarvan juist je code zodanig te schrijven dat het voor zich spreekt en commentaar overbodig maakt [1]. Wanneer voeg je wel commentaar toe en wanneer niet?

In deze blog ga ik in op de ‘comment rules of Ottinger’. Voor diegene die zich afvragen wie Tim Ottinger is: Tim Ottinger is een van de contributors van het eerder genoemde boek van Robert C. Martin. Ook is hij schrijver van o.a. “Agile in a Flash” (samen met Jeff Langr).

De drie regels van Ottinger

De drie regels van Ottinger kwam ik onlangs tegen toen een collega van mij de volgende link opstuurde: https://twitter.com/#!/tottinge/status/169918277957582849/photo/1 Deze drie regels vatten eigenlijk kort en krachtig samen wanneer je wel en wanneer je niet commentaar moet toevoegen aan je code. Hierbij gaat Ottinger er van uit dat de code zichtbaar is. Toch valt er wel het een en ander over te zeggen. Immers, gelden de regels ook als de code bijvoorbeeld niet zichtbaar is (standaard library of API)? En hoe zit het met abstractie in je code?

comment rule 1: the key rule

“Comments are voor things that cannot be expressed in code”

Hier is niets op aan te merken. Dingen die niet in de code kunnen worden uitgedrukt moeten uiteraard als commentaar gezegd worden, bijvoorbeeld code die onderhouden of gereviewd wordt door een ander, moet voor die persoon zo duidelijk mogelijk zijn. Als er iets onduidelijk is over een operatie binnen de code, moet dat goed gecommuniceerd worden met collega’s.

comment rule 2: the rule of redundancy

“Comments which restate code must be deleted”

Logisch. Een methode getXCoordinate() becommentariëren met “gets the x coordinate” is nogal overbodig aangezien de methode “speaks for itselfs”. Echter, pas op met methodes die lijken voor zich te spreken maar toch iets doen waar additionele commentaar nodig is. Kijk bijvoorbeeld naar de File.createNewFile(String fileName) method van de java.io package. Deze methode lijkt te betekenen, maak nieuwe file aan, maar in feite maakt het een nieuwe bestand met de opgegeven naam aan als, en alleen als, het niet bestaat (zoals in de java API ook duidelijk gemaakt). Als je code iets meer doet dan wat uitgedrukt kan worden in de methode naam, voeg dan wel commentaar toe met additionele info van belang.

comment rule 3: the rule of single truth

“If the comment says what the code could say, then the code must change to make the comment redundant”

Waar, maar ook hier zijn er valkuilen en uitzonderingen. Het is inderdaad zo dat commentaar, dat bij een variabele x uitlegt dat het de openstaande bedrag van een nota voorstelt, het inderdaad ‘comment rule 3’ overtreedt. In dit geval zou je het amountDue (Engels voor openstaand bedrag) kunnen noemen. Echter gaat deze regel niet altijd op in de praktijk.

De opsteller van de comment rules en de schrijvers van het boek ‘Clean Code’ stellen dat commentaar gevaarlijk kan zijn. Ontwikkelaars die de code onderhouden, willen weleens vergeten de commentaar van de code aan te passen als de functionaliteit van de code veranderd. Dit kan leiden tot misverstanden. Immers, code wordt veranderd en verder ontwikkeld en commentaar verouderd daardoor snel. Maar ontwikkelaars zouden hierover onderling goede afspraken moeten maken en een soort ‘protocol’ moeten opstellen dat, als de code veranderd, zodoende ook de bijbehorende commentaar veranderd moet worden. Alle leden binnen een ontwikkelteam zouden zulke dingen toch gewoon kunnen afspreken?

Inderdaad zouden er logische namen voor methodes, classes en variabelen gebruikt moeten worden. Als ontwikkelaars elkaars code zouden moeten onderhouden zouden ze zoveel mogelijk uit de code op moeten maken wat het doet en moet commentaar zoveel mogelijk redundant gemaakt moeten worden.

Echter zijn er naar mijn mening vier gevallen, waarbij er van de commentaar regels afgeweken kan worden:

  • Gevallen waarbij code voor andere ontwikkelaars geschreven worden, zoals frameworks en public API’s
  • Gevallen waarbij code richtlijnen ondermijnt dreigen te worden
  • Gevallen waarbij er sprake is van abstractie
  • Gevallen waar zelf gemaakte exceptions worden geschreven
  • Frameworks and public API’s
    Bij het schrijven van methodes is het gebruikelijk dat er zoveel mogelijk informatie verschaft wordt in methode namen zelf en variabelen. Echter, bij code die andere ontwikkelaars kunnen gebruiken, zoals frameworks (al dan niet open source), is API documentatie (ofwel commentaar bij classes en methodes) juist belangrijk. Code voor frameworks en public API’s zijn ‘onzichtbaar’ voor gebruikers (ontwikkelaars die de code gaan gebruiken), dat wil zeggen dat alleen de public classes, methods en variabelen zichtbaar zijn en voorzien zijn van documentatie, zonder dat de gebruiker de implementatie hoeft te zien. Bij open-source frameworks kan de gebruiker weliswaar wel in de code kijken, mits hij daar behoefte aan heeft, maar over het algemeen worden frameworks van (javadoc) commentaar voorzien, zodat het niet nodig is om de source code in te duiken. Ontwikkelaars zullen namelijk eerder Javadoc documentatie raadplegen als nuttig naslagwerk, dan dat ontwikkelaars in de source code gaan duiken om daaruit iets op te maken.

    Ontwikkelaars die frameworks gebruiken moeten de beschikking hebben over goede (javadoc) commentaar en zijn logische namen voor methodes, classes, variabelen en constants belangrijk. Het is hierbij uit den boze als relevant of zeer belangrijke informatie niet in de commentaar is verwerkt. Kijk naar de createNewFile() voorbeeld. Is het kwalijk te nemen dat de makers het niet createNewFileIfItDoesNotExistYet() genoemd hebben om commentaar overbodig te maken? De hoofdtaak van de methode createNewFile() is een nieuwe bestand aanmaken. De ‘if’ wordt beschouwt als conditie, oftewel additionele informatie ofwel een uitzondering. In dit geval is het wenselijk als een methode naam (of welke statement variabele dan ook) zo kort maar krachtig mogelijk is omdat lange methode namen weleens de leesbaarheid of helderheid van de code kunnen ondermijnen. Additionele info die relevant is voor de gebruiker kan toegevoegd worden als commentaar.

    Code richtlijnen
    Code richtlijnen (zoals checkstyle) zijn bedoeld om code voor iedereen binnen een team makkelijk leesbaar en overzichtelijk te houden conform de standaarden en afspraken die er zijn gemaakt binnen zo’n team. Een van de richtlijnen is de javadoc commentaar bij classes, methodes en global variables. Ook zaken als linelength kun je instellen.

    Over het algemeen beschouw ik het als bevredigend, verhelderend en nuttig als vooral public API’s en source code voor zeer complexe applicaties en frameworks voorzien zijn van Javadoc commentaar. Het kost meer tijd om de source code in te duiken om te achterhalen wat een methode doet en de code te snappen zonder commentaar, dan dat een framework is voorzien met javadoc commentaar. Er zijn daarnaast ook onderzoeken geweest waaruit blijkt dat correcte en up-to-date commentaar ontwikkelaars juist helpen om de code te begrijpen [2] en dat commentaar nog steeds als belangrijk nevenproduct genoemd wordt.[3]

    Ook vind ik dat namen van classes, methodes en variabelen zo kort mogelijk gehouden moeten worden. Maak namen niet onnodig lang, zelfs als commentaar er mee overbodig wordt gemaakt. Onnodig lange namen van code die gebruikt worden door andere ontwikkelaars kunnen algauw leiden tot onoverzichtelijkheid en onleesbaarheid van de code en kunnen conflicteren met code normen en richtlijnen, zoals line length, die de ontwikkelaars zelf hebben opgesteld. Vooral bij code dat geschreven wordt voor public API’s, zoals eerder genoemd, moeten de namen zo kort mogelijk gehouden worden om dezelfde reden. Stel je voor dat de framework een class bevat met het eerder genoemde createNewFileIfItDoesNotExistYet() methode, maar dan met een of meerdere parameters die je mee kunt geven. Dit zou zomaar de leesbaarheid en de overzichtlijkheid van de code kunnen ondermijnen, als het al niet de opgestelde richtlijnen zoals linelength length ondermijnt.

    Abstractie
    Ook methodes die abstract zijn en dus gedefinieerd zouden moeten worden door subclasses vereisen nader uitleg. De reden waarom iets abstract is en gedefinieerd zou moeten worden is altijd relevant. Typische gevallen zijn bijvoorbeeld methodes die aangeroepen worden door schedulers of methodes die aangeroepen worden door listeners. De gebruiker zou in dit geval moeten weten hoe hij een dergelijke methode moet gebruiken en dat hij door een ander object aangeroepen (invoked) kan worden. Het is namelijk zo dat een methode dat overgeerfd is niet meer van naam veranderd kan worden aangezien deze methode abstract is in de superclass.

    Neem bijvoorbeeld een abstracte methode execute() van een abstracte class die Action heet. Je zou kort uit kunnen leggen dat Action een actie representeerd die gescheduled kan worden en dat die gespecificeerd moeten worden in een subclasse. Als je bijvoorbeeld een subclass PatrolAction hebt, lijkt de naam al iets te zeggen (een patrouille actie), maar wat het precies inhoud en de context van de action, moet je kort toelichten in commentaar. Alle logica zit in de execute methode en de execute methode is abstract. De execute() methode is dus niet te hernoemen om commentaar redundant te maken, aangezien de methode abstract is. Uiteraard kun je de logica in de methode dusdanig opstellen, dat je zo min mogelijk commentaar nodig hebt om het duidelijk te maken. Maar de logica is niet altijd zonder tekst en uitleg uit te drukken en is in bepaalde gevallen wat meer opheldering nodig.

    Om het zo kort mogelijk te houden, heb ik details en concretere voorbeelden over het becommentarieren van code bij abstractie buiten beschouwing gelaten in deze post.

    Exceptions
    Andere voorbeelden, waar commentaar niet bepaald overbodig is, zijn exceptions waarbij je altijd moet uitleggen in welke situaties zo’n exception kan optreden. Je kan de exception dusdanig naamgeven, dat je er iets uit op kunt maken, maar als een exception meerdere oorzaken kan hebben, dan is het misschien goed om dat kort toe te lichten in commentaar.

    Conclusie
    Voordat men veronderstelt dat ik het compleet oneens ben met de regels van Ottinger, wil ik hierbij zeggen dat dat niet zo is. In deze blog wil ik alleen aangeven dat de regels niet altijd van toepassing zijn op bepaalde gevallen en je ze dus niet altijd letterlijk kunt overnemen.

    Er moet namelijk ook rekening gehouden worden met andere zaken, zoals leesbaarheid en andere richtlijnen die bij het programmeren thuishoren. Ook zijn er gevallen waar commentaar volkomen legitiem zijn en zelfs onmisbaar. Bij frameworks of public API’s is commentaar gewenst, net zoals bij abstracte classes en methodes en specifiekere implementaties daarvan, en ook bij exceptions. De comment rules zijn dus niet altijd heilig en bovendien is commentaar niet honderd procent te vermijden. Het gevaar loert echter wel wanneer code wordt aangepast, maar de commentaar niet, waardoor hij niet up-to-date is en dus onbedoeld misleidend en onbetrouwbaar. Let dus wel goed op als er commentaar is bij de code.

    Tot slot, mocht de lezer het interessant vinden: het boek ‘Clean Code’ van Robert C. Martin is een aanrader mocht je willen weten waar je, naast commentaar in source code, nog meer op kunt letten om je code ‘clean’ te houden.

    [1] Martin, Robert C., Clean Code: A Handbook of Agile Software Craftmanship, Prentice Hall, 2009.
    [2] Malik, H. et al, Understanding the Rationale for Updating a Function’s Comment, In ICSM, pages 167–176, 2008
    [3] de Souza, S. C. B., Anquetil, N., and de Oliveira, K. M, A
    study of the documentation essential to software
    maintenance
    , In International Conference on Design of
    Communication, pages 68-75, 2005

    Als je hier nieuw bent, wil je je misschien inschrijven voor onze RSS feed.
    Bedankt voor je bezoek!

    Gerelateerde bijdragen

    • Er zijn geen gerelateerde bijdragen gevonden.

    Werken met Roshan Raktoe?
    Kijk dan bij onze mogelijkheden voor starters en/of ervaren IT'ers.


    Categorieën: Development


    Reacties (3)

    • Paul schreef:

      Hey Roshan,

      Leuk artikel en goed om hier weer eens op gewezen te worden. Zelf vindt ik dat voorbeeldcode als documentatie ook er prettig werkt. Unit-tests zijn hier bij uitstek voor geschikt. Op die manier weet je zeker dat de “documentatie” (lees test) overeenkomstig is met de implementatie.

      Geplaatst op 01 mei 2012 om 16:39 Permalink

    • Rachid schreef:

      Gebruik commentaar om te vertellen waarom je iets gedaan hebt, de onwtikkelaar ziet in de meeste gevallen wat je hebt gedaan. En zet vooral geen commentaar bij standaard functies zoals converties of creeren van een instantie. Dit zie ik vaak.

      Geplaatst op 16 augustus 2012 om 12:27 Permalink

    • Rachid schreef:

      het boek ‘Clean Code’ is trouwens heel goed voor starters. Heb er veel van geleerd.

      Geplaatst op 16 augustus 2012 om 12:29 Permalink

    Plaats een reactie

    Jouw emailadres wordt nooit gepubliceerd of gedeeld. Benodigde velden zijn met * gemarkeerd.