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

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

    if (shouldNotWrite(scriptSource, loadedFromBaseJS))
     return false
    
    

    Ça, de toute façon, c'est interdit. Pour la raison que tu cites. S'il y a retour à la ligne, il faut les accolades. Dans le même genre, si il y a des accolades sur le if, on en met sur le else. En général, je vote pour une règle stricte : pas d'accolade du tout (et donc conditions sur une ligne), ou toujours des accolades (et quand je dis toujours, ça veut dire même quand ça pourrait tenir sur une ligne). Et comme je l'ai dit, à moins que tout le monde soit d'accord avec ce style très particulier, j'irai sur plus traditionnel (accolades, point virgules…).

    Après, sur le côté closure. Par exemple, le doc = goog.global.document est assez particulier, surtout que je n'en vois pas du tout l'intérêt. En plus, il est utilisé avant sa déclaration (ok, c'est pas forcément un problème, mais quand même).

    J'ai gardé cette partie du code d'origine, parce que j'avais déjà la closure (pour pas polluer la bibliothèque autour). Je l'ai placé après (comme le reste des définitions) pour rester cohérent avec le commentaire. À la base, j'avais :

    /* --- (function (goog) { */
    /**
     * The default implementation of the import function.
     * Writes a script tag to import the script.
     *
     * @param {string} src The script source.
     * @return {boolean} True if the script was imported,
     * false otherwise.
     * @private
     *
     */
    /* +++ */ (function (goog) {
     goog.writeScriptTag_ = function (source) {
     if (!goog.inHtmlDocument_()) return false
     var loadedFromBaseJs = isDependency(source)
     if (shouldNotWrite(source, loadedFromBaseJS)) return false
     doc.write(tag(source))
     return true
    
    

    J'aurais peut-être pu remettre le code dans l'ordre « traditionnel » après avoir passé la closure au dessus du commentaire… Il ne faut pas s'arrêter sur la closure qui est ici un détail.

    Avoir des limites genre pas plus de 5 lignes, j'en vois pas vraiment l'intérêt. A part mettre chaque instruction ou condition dans une méthode qui lui est propre, mais ça revient à découper pour découper là. D'ailleurs je trouve étrange de limiter la taille des lignes et en même temps vouloir tout mettre sur une ligne…

    Les fonctions de cinq lignes, ce n'est pas une règle absolue (comme j'ai dit, je fais à vue d'œil), c'est juste que quand chaque action a un nom qui indique le but de l'action, on se retrouve avec des fonctions aussi courtes. La limite sur la taille de la ligne, elle, par contre, est une vrai limite. Elle est couplée à une autre limite : ne pas utiliser d'abréviations. Enfin, mise en parallèle avec le choix fait ici de ne pas utiliser d'accolades (donc, boucles, ifs, etc. sur une seule ligne), ça oblige vraiment à réfléchir. Oui, on découpe pour découper, mais au passage, on réfléchit au but du morceau de code qu'on est en train de découper. On doit lui chercher un nom, significatif, court…

    Certains langages s'y prêtent mieux que d'autre. Dans un langage objet, le résultat est souvent qu'on se rend compte qu'une partie de notre logique devrait être placée dans une nouvelle classe. En Forth, les fonctions peuvent tenir sur une ligne parce que le passage d'arguments est implicite, et elles doivent tenir sur une ligne parce que sinon on n'arrive plus à suivre l'état de la pile. Dans un langage comme le C, c'est plus difficile, parce qu'on doit passer tout les paramètres, on ne peut pas avoir plusieurs fonctions du même nom (en orienté objet, on peut tant que la méthode appartient à un objet différent)…

    Pour reprendre ton exemple :

    for(myIntVectorIterator = myIntVector.begin(); myIntVectorIterator != myIntVector.end(); myIntVectorIterator++) if (*myIntVectorIterator % 2) {
     cout<<*myIntVectorIterator<<" ";
     //Should output 1 3 5
    }
    
    

    Ce code ne passe pas selon mes règles. C'est un exemple, très abstrait, je ne peux donc pas proposer de solution, mais face à un code de ce genre, je réfléchis énormément pour raccourcir la ligne de 144 caractères. Je suppose que je mettrais justement le if/else dans une autre fonction, avec un nom qui indique ce que fait cette condition. myIntVectorIterator est un nom très long, est-ce qu'il n'y en a pas un plus court qui ait un sens dans le contexte actuel ?…

    Le but de cette règle est de forcer le développeur à penser jusqu'au bout à ce qu'il est en train de faire. Si un mauvais développeur vient toucher au code, on le verra tout de suite parce qu'il sera incapable de suivre les règles (ici, mauvais est très subjectif, peut-être que je suis un mauvais développeur, après tout ;-)). Ce qui rejoint ceci :

    Et les conventions de code, si elles doivent permettre d'avoir un code élégant, doivent aussi s'assurer que tout fonctionnera au mieux, en prenant si possible en compte les erreurs humaines.

    En ce sens je suis totalement d'accord avec toi. Et mes règles ne sont pas fun non plus ;-). Les tiennes sont sûrement plus éprouvées, par contre, parce qu'elles sont suivies par la majorité de l'industrie. Mis à part dans mes propres projets, et dans quelque codes en Forth, je n'ai jamais rencontré un style aux choix aussi radicaux que le mien. Ah si, en smalltalk aussi (les méthodes sont souvent très courtes).

    À noter qu'en smalltalk, il y a deux types de commentaires : les commentaires inline (assez rare), et les commentaires de la classe/de la méthode, présentés à part. Ceux-ci sont courants, et sont censés être précis.

    Le code que j'ai présenté ne contient aucun commentaire, parce que c'est le sujet du journal. Si le sujet du journal avait été l'inutilité d'un code très découpé, j'aurais sûrement fait comme en smalltalk : indiqué ce que fait chaque fonction, pourquoi elle existe… Mais il n'y aurait pas eu plus de commentaire inline.

    Je distingue la documentation et le commentaire. Un commentaire n'a pas de sens sans le code qu'il accompagne. La documentation en a. Aussi, je distingue deux types de documentation : la documentation interne au module, et la documentation externe. La documentation externe est accompagnée du prototype des fonctions, d'exemple sur comment les utiliser, etc. La documentation interne décrit le contexte d'exécution, les pièges à éviter… Mais dans les deux cas, il devrait être possible de présenter cette documentation de manière bien distincte du code (comme en smalltalk, la documentation et le code sont dans un onglet différent). Une fois le contexte connu, le code devrait pouvoir être lu sans avoir à être annoté. L'intérêt pour moi d'avoir une documentation à part est qu'elle peut être mieux rédigée, couvrir une plus grande portion de code, offrir une vue d'ensemble de ce qu'on cherche à faire… Alors qu'un commentaire est très localisé. Par contre, cela demande un travail supplémentaire (tout comme la factorisation à outrance demande un travail de réflexion et de nommage supplémentaire).

    Après, quand je parle de documentation à part, je n'érige pas ça comme une règle : l'idée de la javadoc, à savoir, la documentation de la fonction à côté de la fonction, est pertinente à mon avis, puisqu'elle permet de vérifier plus rapidement la validité du code, synchroniser la documentation aux code… De la même manière, on peut envisager de mettre la documentation interne avec le code. Mais le commentaire traditionnel n'est pour moi pas la place de cette documentation. Au début du fichier, pour comprendre à quoi on touche avant même de plonger dans le code, est la place appropriée pour cette documentation. Ou bien, comme en programmation lettrée, avec le code – mais le code est alors une illustration de la documentation. Quoi qu'il en soit, on ne commente pas le code, on documente notre problème. Le code reste une information à part et auto-suffisante quand le problème est maîtrisé.

    Mais je suppose que, d'une certaine manière, je t'accorde là un point, puisqu'au final, il y a une documentation. Le débat porte juste sur la place de celle-ci, et la lisibilité du code selon la place occupée par la documentation.

    (Je suis rentré dans le débat pour montrer un exemple de code sans commentaire en essayant de garder le sens de ceux-ci, comme un défi. Après, je parle de mes goûts, mais comme vous pouvez le voir, mes goûts ne bannissent pas les commentaires, ils les déplacent… ;-))