• [^] # Re: Code auto-documenté

    Posté par . En réponse au journal To comment or not to comment. That is the question.. Évalué à 2.

    Deuxième partie de ma réponse, en réaction à ce point :

    Ensuite, honnêtement, je trouve ça plus lourd. Et surtout, il manque réellement des commentaires.
    En fait, en lisant ton code, on ne sait toujours pas pourquoi on teste l'état du document, pourquoi un lance une erreur mais pas dans le cas de deps.js.

    J'ai justement essayé de ne pas perdre le contenu des commentaires, ce qui m'a demandé un peu d'imagination. Mais, c'est vrai, le contenu est maintenant dilué et parfois implicite.

    // If the user tries to require a new symbol after document
    // load, something has gone terribly wrong. Doing a
    // document.write would wipe out the page.
    
    

    Pour ce premier commentaire, c'est vrai qu'on ne précise plus qu'écrire un commentaire pourrait effacer la page. On précise juste qu'il y a des cas où l'on ne devrait pas écrire :

    if (shouldNotWrite(source, loadedFromBaseJS)) return false
    
    

    Si on lit shouldNotWrite, on sait pourquoi on ne devrait pas écrire :

    if (doc.readyState != 'complete') return false
    
    

    Bon, là, on atteint une double négation (… faut que je réfléchisse à un meilleur nom, donc ;-)), mais une fois ce problème logique surmonté, on comprend que la condition pour écrire est que le document n'aie pas finit d'être chargé. Est-il nécessaire de préciser pourquoi il ne faut pas écrire dans un document déjà « scellé » ? (je viens d'y penser, je pourrais englober le test dans une fonction au nom plus évocateur, justement : documentSealed())

    Le contenu du second commentaire est, lui, plus implicite.

    // Certain test frameworks load base.js multiple times,
    // which tries to write deps.js each time. If that happens,
    // just fail silently. These frameworks wipe the page
    // between each load of base.js, so this is OK.
    
    

    Donc, on échoue silencieusement si la page a déjà été effacée ? Sinon, on déclenche une erreur ? Et pourquoi la page aurait déjà été effacée ? Parce que « base.js » a déjà été chargé ?

    Tout les éléments sont dans le code, mais éparpillés et implicites :

    Si notre code est une dépendance, dans ce contexte précis, il a été appelé par « base.js » (Ou bien il y a une erreur dans le code ? Je me fie au code et aux commentaires pour faire cette assomption.).

    var loadedFromBaseJs = isDependency(source)
    
    

    À quoi sert loadedFromBaseJS ? Et bien il est passé comme paramètre pageWiped. Donc, si le code est une dépendance, il a été chargé à partir de « base.js », et cette information est importante pour nous pour savoir si la page a été effacée.

    Pourquoi veut on savoir si la page a été effacée ?

    if (!pageWiped) throw Error(errorText(source))
    
    

    D'accord. Si la page n'a pas été effacée, on n'a pas affaire a une opération anodine. Rien que d'avoir essayé est mauvais, on plante.

    Tout les éléments sont donc dans le code. Plus que le comment, le pourquoi est là aussi. Seulement, il faut inférer le pourquoi. Le commentaire a l'avantage de prémacher le travail. Il a aussi l'inconvénient, parfois, de mettre notre cerveau sur off, ce qui peut s'avérer gênant si le commentaire et le code ne sont pas synchronisés.

    Bonus : mise à jour de la partie impliquant shouldNotWrite :

    goog.writeScriptTag_ = function (source) {
     if (!goog.inHtmlDocument_()) return false
     var loadedFromBaseJs = isDependency(source)
     if (!writePossible(source, loadedFromBaseJS)) return false
     doc.write(tag(source))
     return true
    }
    var writePossible = function (source, pageWiped) {
     if (!documentSealed()) return true
     if (!pageWiped) throw Error(errorText(source))
     return false
    }
    var documentSealed = function () {
     return doc.readyState == 'complete';
    }
    
    

    Maintenant, j'avais même commencé à mettre des bout de code « inutiles », juste « sémantiques » quand j'ai commencé à refactoriser. Un truc du genre :

    pageWiped = loadedFromBaseJS = isDependency(source)
    
    

    Là, l'idée n'est plus de virer les commentaires, mais bien de ne parler qu'un seul langage : javascript.

    Quand on dit qu'un code bien écrit se passe de commentaires, c'est un peu comme dire qu'un texte bien écrit en anglais peut se passer de commentaires en français. On veut ne parler qu'un seul langage, et y placer toute l'information dont on dispose. Un commentaire en javascript, « it's an english citation in a french text ».

    Après, j'essaye de montrer des exemples, je défend le point de vue des « sans commentaire », mais je suis un extrémiste : cela se voit dans les règles que je me suis fixé pour le style (voir mon commentaire précédent). Je suis juste un extrémiste dans les deux sens : je n'ai pas traduit la page de wikipédia sur la programmation littéraire pour rien. Je me fais aussi avocat des commentaires plus longs que le code !

    Il se trouve que les deux techniques de programmations qui m'ont le plus marquées sont celle de la programmation lettrée, et celle de Forth. L'une prône des commentaires très détaillés, l'autre un code qui est sa propre définition (Littéralement. En Forth, on « définit des mots » plutôt que d'écrire des fonctions.). C'est de Forth que je tiens mon habitude des fonctions très courtes (une fonction qui tient sur une ligne de 64 caractères, un module de 16 lignes, je trouve ça magique).