Les deux boucles ne sont pas identiques (y'a un M qui se tranforme en M-N) mais c'est clair que la plus grande difficulté est de comprendre à quoi correspond mt, mti, kk et toutes ces variables nommées comme au début du C. Dans le temps on avait des limites de caractères et on manquait d'optimisation, mais aujourd'hui on n'a plus ces limites et on a des optimisations qui permettent de revoir la structure à la compilation (e.g. remplacer l'appel d'une fonction par son code pour aller plus vite) ce qui permet de se concentrer sur la sémantique du code.
Je me rappelle encore de ce code que j'ai repris (je bosse dans la recherche logicielle) où c'était un gros bloc monolithique censé tester plusieurs algos, avec des variables globales de partout, des fonctions de plusieurs centaines de lignes, des variables et boucles qui se répètent, etc. Après un bon moment à essayer de refactor ce code en renommant les variables, en factorisant dans des fonctions, etc. j'ai finalement abandonné pour reprendre les algos écrits sur papier. Ça s'est traduit comment ? J'ai simplement copié-collé l'algo dans le code (c'était du pseudocode, donc forcément ça compile pas), puis les structures pseudocode je les ai remplacé par les structures propres au langage (if, else, for, ...), les variables ont été initialisées comme décrit dans le papier et les fonctions utilisées (décrite ailleurs dans le papier) ont eu droit au même traitement récursivement (copie pseudocode + adaptation au langage). Résultat : un code source au plus proche du papier donc commentaires inutiles à moins de devoir réécrire le papier dans le code, ce qui n'est pas le but. La fonction implémentant l'algo peut avoir une documentation qui décrit l'algo ou qui renvoit au papier.
Je fais pareil avec des algos pris sur wikipedia et sur le net en général : je copie-colle l'algo et je l'adapte au langage, avec une doc qui dit où se trouve la description de l'algo. Si l'algo est pas clair, je renomme à la fin les variables de manière plus explicite, voir je factorise dans des fonctions aux noms explicites. Si tu as besoin de commentaires, c'est que tu as besoin de comprendre l'algo, auquel cas direction le papier ou la page web concernée. Les commentaires dans le code ne sont pas là pour donner des cours, quand tu lis une fonction, tu es censé déjà savoir ce qu'elle fait, de par son nom ou sa doc, le code est seulement là pour te dire comment c'est fait, pas pourquoi.
En fait, le commentaire comme tu l'as mis, je le considère plus comme de la doc que comme du commentaire à proprement parler. Avec une syntaxe tel que javadoc, ça permet d'avoir une meilleur visibilité lors de l'utilisation de la fonction et permet aussi la génération d'une partie de la documentation.
Et là, c'est un "commentaire" qui est complémentaire au code et son contenu ne peut pas être deviné grâce au code.
Je ne prône pas l’absence total de commentaire. Après peut-être que la différence que je fais entre commentaires et documentations n'est pas la même pour tout le monde.
Si on considère les documentations à la javadoc comme des commentaires, oui ceux ci sont obligatoire.
@koala01 : Des, fois il n'ai pas pertinent de (trop) diviser un traitement. Si tout les traitements font partie de la même unité logique et qu'il ne sont pas susceptible d'être réutiliser ailleurs.
Pour le code de pseudocode, pourquoi tu fais des test sur le contenu de tes constantes?
D'après ce que je lis mti vaut toujours 625.
Donc tes test (mti >= N) et (mti == N+1) donneront toujours le même résultat. Soit les test sont superflues et peuvent donc être supprimer, soit l'utilisation de variables à la places des constantes serait à préféré.
Après, il est vrai que les noms pourrait être plus explicite.
Après, je comprends pas en quoi "TEMPERING_SHIFT_L(y)" est plus parlant que "y >> 18"
ceci dit les algo n'utilisent pas toujours des variables très explicites
MD5 :
en math on utilise facilement x, y, z, w ou l'alphabet grecque
Après, x,y et z peuvent ne pas avoir besoin d'être renommer si on travail sur des coordonnées cartésiennes. C'est au contraire, le choix le plus judicieux.
De même les lettres grecque ont leur signification en mathématique et le nom de la lettre pourra être le choix le plus approprié (exemple : Pi)
Heuu... Ce site a été créé il y a près de dix ans
A l'époque, on se trainait encore des navigateurs comme IE4 dont le support de la norme laissait vraiment à désirer
Donc, oui, je mettais effectivement en garde contre le fait que certains navigateurs pouvaient ne pas afficher ce site correctement
j'ai, justement, fait énormément de revue de code, dont sur des projets importants, dont le code s'étalait sur plusieurs années, avec tout ce que cela peut impliquer en terme de correction de bug et / ou adaptation.et je me permets juste un petit copier/coller de cette source dont je grasse certains passages
Mais que c'est-il passé depuis que tu as rédigé cet article ? quelle formation as-tu suivi ? Quelle vérité s'est imposée à toi ?
Alors, oui, j'ai effectivement trouvé des "normes de codages" à l'époque qui préconisaient que les commentaires s'étalent sur à peu près 30% du code, mais tu remarqueras que, sans abonder dans leur sens, je mettais déjà un gros bémol sur ce point particulier
Ensuite, si j'avais du mettre quelque chose en évidence dans la phrase
cela aurait plutot étéA vrai dire, c'est même une chose dont l'abus ne nuise nullement, bien qu'il soit utile de veiller à les utiliser à bon escient…
Je n'ai, sommes toutes, fait que durcir ma position sur ce que l'on peut considérer comme le fait de les utiliser à bon escientbien qu'il soit utile de veiller à les utiliser à bon escient…
D'ailleurs, lorsque tu regardes attentivement le conseil que je donne et que tu as si gentiment mis en rouge, tu constateras que cela correspond, en à peine plus souple, à ce que je disais dans ma première intervention, à savoir : ce que l'on peut parfaitement trouver dans le cartouche
Je devrais peut etre prendre le temps de faire une sérieuse mise à jour de ce site
J'ai effectivement poussé le bouchon un peu loin dans ce cas particuliers.
Mais, je persistes à estimer que le fait de renommer "intelligemment" les variables apporterait énormément de lisibilité
Oh que oui, sur des projets de plusieurs milliers de fichiers et donc de plusieurs centaines de milliers de lignes
Et j'ai meme du me résoudre à refaire entièrement certaines parties (tout en gardant le comportement d'origine, bien sur, autrement ca aurait été trop simple) parce qu'il était purement et simplement devenu impossible de faire évoluer les choses dans la direction qui m'était imposée.
En plus, comme il y avait eu un certain turn over, certaines parties du code contenaient des commentaires qui, au fil des modifications, ne correspondaient plus à la réalité.
Je me suis donc heurté aux deux problèmes de manière distincte, et je peux t'assurer que ce sont toujours les commentaires non à mis jour qui m'ont posé le plus de problème
Dans les 30% ils comptent la doc qu'on fait générer par l'ide ? (Jamais pu supporter ces chiffrages... Selon la complexité du code et le contexte, la nécessité de commenter un passage varie énormément)
T'as bien de la chance, moi on me répond en général "Non, ça marche encore (nonobstant les 2 prestas qui sont en full maintenance), et de toute maniere on n'a pas le budget"Et j'ai meme du me résoudre à refaire entièrement certaines parties (tout en gardant le comportement d'origine, bien sur, autrement ca aurait été trop simple) parce qu'il était purement et simplement devenu impossible de faire évoluer les choses dans la direction qui m'était imposée.
Ben moi, c'est surtout l'absence totale de commentaires (et des années d'évo a l'arrache) qui m'ont posé probleme. Heureusement la je fais du neuf, comme ça c'est mon code qui va embeter la TMA dans 10 ansJe me suis donc heurté aux deux problèmes de manière distincte, et je peux t'assurer que ce sont toujours les commentaires non à mis jour qui m'ont posé le plus de problème
Je suis au moins aussi allergique que toi aux valeurs arbitraires, surtout en ce qui concerne les commentaires (ou le nombre de lignes maximal par fonction, mais ca, c'est le débat d'à coté )
sans douteT'as bien de la chance, moi on me répond en général "Non, ça marche encore (nonobstant les 2 prestas qui sont en full maintenance), et de toute maniere on n'a pas le budget"
Mais bon, j'avais un allié de choix auprès du responsable technique du projet (qui lui, était là depuis le début) et qui était tout aussi perdu dans le code que j'ai du "virer"
Permission ou pas, je peux t'assurer que si je me trouves face à une fonction véritablement trop complexe, je commence par la refactorer, en la scindant en fonctions plus "malléables", surtout si c'est pour de la correction de bugBen moi, c'est surtout l'absence totale de commentaires (et des années d'évo a l'arrache) qui m'ont posé probleme. Heureusement la je fais du neuf, comme ça c'est mon code qui va embeter la TMA dans 10 ans
Cela limite grandement le besoin de commentaires
Hum disons que sur ma mission précédente, on s'est retrouvé face a un bug qui nous a laissé sur le derrière (et qu'on n'a jamais pu corriger) en voulant... virer une ligne de sortie log. Suite à ça, on n'a jamais retravaillé la moindre ligne de code du projet sans avoir calé 2 jours de tests derrière. Alors une refactorisation...
M'enfin on dérive
Tu as déformé mes propos, car je ne prétend pas être "aussi fort que cela".
J'ai travaillé sur des projets que l'on peut clairement qualifier d'importants.
Sur ces projets, il m'est meme arrivé de devoir carrément jeter une partie du code qu'il n'était plus question de faire évoluer.
Cette partie était, par chance, limitée à quelques fichiers tout au plus, mais correspondait malgré tout à plusieurs centaines de lignes de code.
Pour d'autres parties, j'ai carrément du suivre David Weelers qui nous dit que tout problème en informatique peut etre résolu en ajoutant un niveau d'indirection supplémentaire afin de permettre l'évolution des parties concernées.
Il n'a jamais été question de "tout casser" et de "tout reprendre à zéro" (quoi que cela aurait peut être été franchement pas mal à mon avis ), mais de "casser le stricte minimum" (enfin, non, de jeter avant de refaire, car il était hors de question de "casser" ) afin de faire quelque chose de plus adapté à la nouvelle situation car plus "évolutif" que ce qui était prévu à la base.
Et je ne compte pas les bugs issus d'assertion (de la part des développeurs précédents et qui étaient vraies lorsqu'ils les ont faites) qui n'étaient plus vérifiées ou d'utilisation aberrantes de la part des utilisateurs (oui, oui, certains bug prenaient réellement naissance entre la chaise et le clavier du coté de l'utilisateur )
Je peux donc t'assurer que j'ai une expérience qui dépasse la simple théorie plus que concluante en terme de revue de code et de ré-factorisation
Bah, dans un code où x, y et z correspondent à une sémantique donnée (de coordonnées, par exemple), cela ne me pose aucun problème, pas plus que le fait une variable PI, EPSILON, BETA ou autre.
Mais nous sommes alors dans un domaine donné, dans lequel ces noms ont une signification particulière.
Mais si tu décide de définir un symbole ZORGLUB à une valeur de 3.1415926 et de l'utiliser en lieu et place d'un symbole bien mieux nommé PI, il ne faudra pas t'étonner de devoir recourir aux commentaires
Des variable n, m, et autres sont très bien lorsqu'il s'agit de présenter une formule mathématique, mais il est fortement conseillé de choisir des termes bien plus explicites dans le code.
Plutot que d'appeler tes variables Q, N et D, pourquoi ne pas les appeler quotient, numerateur et diviseur Après tout, c'est ce que tes variables représentent non
Effectivement. Mais, au final, ce n'est qu'un autre moyen d'écrire des commentaires: utiliser les possibilités de la syntaxe/grammaire du langage en lieu et place de la syntaxe/grammaire d'un texte littéral.
Personnellement, je dépense moins d'énergie à rédiger une explication en langage humain qu'en langage de programmation.
Code delphi : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 // Compute Q and R such that N = Q*D + R using the long division algorithm. // Long division shifts gradually from the left to the right end of the Numerator, // subtracting the largest possible multiple of the Denominator at each stage; // When used with a binary radix, the possible multiple at each stage is 0 or 1. if D == 0 then throw DivisionByZeroException end Q := 0 R := 0 for i = 31...0 do // N is a 32bit integer R := R << 1 R(0) := N(i) if R >= D then R = R - D Q(i) := 1 end end
Question d'habitude je suppose... et de facilité offerte par le langage . Il est clair qu'écrire du code expressif en C++11 est indéniablement plus simple et faisable qu'en C. Pour ma part avec l'habitude ça ne me prend pas plus de temps de faire un code expressif, je pense qu'en écrire un moins expressif me demanderait de la réflexion .
Je suis tout à fait d'accord : commentaires et code sont deux façons de dire la même chose (toujours sans parler de documentation). Mais c'est précisément ce qui fait que quand on change l'un il faut généralement changer l'autre, ce qui est rarement fait. Le fait de faire un peu plus d'effort pour arriver à avoir un code n'ayant pas besoin de commentaires est donc aussi un bon moyen de s'éviter du travail supplémentaire le jour où on revient dessus : c'est un investissement {^_^}.
Avant, j'étais de ton avis, puis, je me suis heurté à des fonctions (dont je n'étais pas l'auteur original) quelque peu plus complexe qu'une simple division (meme si c'est l'exemple qui m'est venu à l'esprit ) qui avaient été corrigées, sans doute à de maintes occasions et pour lesquelles les commentaires n'avaient pas été mis à jour.
C'est généralement dans ce genre d'occasion que je ressentais (et que je ressent d'ailleurs toujours) un grand moment de solitude car:
A priori, il n'y a pas de raison de douter de la justesse d'un commentaire, sinon, pourquoi en mettrait on un
On commence donc (du moins c'est mon cas) par estimer que le comportement du code est bien celui qui est décrit par le commentaire, et l'on cherche la solution "ailleurs".
Jusqu'à ce que, à l'instar de Sherlock Holmes on en vienne à se dire que, Lorsque l'on a écarté l’impossible, ce qui reste, aussi improbable soit-il, ne peut être que la vérité.
On revient alors sur cette portion de code que l'on avait écartée au début.
Et on se trouve face à un autre problème, qui est du au fait que l'on a deux sources d'informations, a priori, aussi crédibles l'une que l'autre, qui nous disent deux choses parfois totalement différentes : les commentaires qui nous indique "comment ca devrait se faire" d'une part et le code qui nous indique "comment c'est fait" d'autre part.
C'est généralement à ce moment là que l'on ressent cet oppressant moment de solitude car, faut il modifier le code afin qu'il respecte les commentaires originaux, au risque de provoquer des régressions sur des bugs corrigés, ou modifier le commentaire pour qu'il corresponde à ce qui est réellement fait (après avoir corrigé l'erreur qui a nécessité que l'on revienne sur ce code bien sur)
La logique voudrait que l'on modifie le commentaire, évidemment, de manière à prendre en compte le scénario qui pose problème tout en évitant de recréer des bugs corrigés pour lesquels on en peut qu'espérer qu'un test unitaire reproduise le scénario
Mais c'est aussi oublier qu'un peu vite que, si le code a déjà été modifié pour prendre en compte certains scénarios qui sont apparus au fil de l'utilisation, il reste encore de grandes chances pour que de nouveaux scénarios continuent à apparaitre dans le futur.
Et si les commentaires n'ont pas été mis à jour avant, il n'y a strictement rien qui nous incite à penser qu'ils le seront à la prochaine modification du code. Bien au contraire!
Au final, je ne crois pas que l'on use "beaucoup plus d'énergie" à faire en sorte que le code soit auto-commenté grâce à des noms clairement explicite (d'autant plus que nous profiterons sans doute énormément de l'auto complétion pour les différents symboles ), mais on s'économisera surement quelques cheveux blancs en évitant de se retrouver avec deux sources d'informations devant être systématiquement mises à jour de manière simultanée
sauf que le code "autodocumenté" peut tout aussi être incohérent
je préfère avoir ceci, qui à défaut d'être propre reste compréhensible
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 function factoriel(int facteur) { return facteur + facteur; }
car je persiste à dire qu'un code toujours propre ça n'existe pas, même avec du SOLID on fini par avoir des couches et des surcouches qu finissent par rendre l'ensemble complexe à comprendre, même avec un code correctement nommé.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14 /* nous ne calculeront jamais au delà de 10! function factoriel(int i) { /* uint res = 1; for(uint j = 2;j<i;j++) { res *= j; } return res; */ return i * i; // on obtient de meilleur résultats en se basant sur un carré // todo: refactoriser le nom de la fonction ou revenir sur un factoriel }
Sauf que ce qui est important, c'est la complexité d'une couche donnée, pas de toutes les couches. Un gros programme est toujours complexe, qu'il soit propre ou non. Si tu prend en charge un ERP dans sa totalité, ou même un seul pan de cet ERP (e.g. logistique), tu auras beau faire ce que tu veux, ce sera complexe. Néanmoins, si à chaque fois que tu regardes une fonction son contenu est clair, tu sauras aisément si c'est ce que tu cherches ou pas (si tu sais ce que tu cherches).
Quand les fonctions sont propres, que tu cherche une fonctionnalité précise pour corriger un bug ou quand tu regardes simplement le code pour comprendre ce qu'il fait, tu voyage facilement dedans, tout comme un livre dont tu es le héros : quand tu as compris le texte, tu choisis ou tu vas jusqu'à ce que tu trouves ce que tu cherche. Si le code est pas clair, alors tu dois non seulement essayer de deviner le sens de ce que tu lis, mais en plus tu peux être amené à devoir regarder toutes les fonctions qu'il utilise pour essayer de mieux comprendre ce qui se passe dans cette fonction.
Tu chercheras rarement à comprendre la totalité d'un programme (à moins qu'il ne soit particulièrement simple), il est donc inutile de considérer la complexité de l'ensemble du programme. Ce qui importe est la complexité locale, que tu retrouves dans chaque fonction, parce qu'on va de fonction en fonction.
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager