IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C++ Discussion :

Je dois revenir au C++ quinze ans après l'avoir quitté. Qu'est-ce qui a changé ?


Sujet :

C++

  1. #21
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 275
    Points : 10 985
    Points
    10 985
    Par défaut
    Citation Envoyé par grunt2000 Voir le message
    Je ne cherche vraiment pas une maîtrise fine du C++ dans ses arcanes.
    [...]
    Aujourd'hui, mes règles sont :
    - Toujours simple : tout est écrit pour la maintenance future par des développeurs autres que soi, ayant de un à cinq ans d'expérience.
    - Toujours appuyé sur des API externes éprouvées. On n'invente aucun algorithme que quelqu'un a déjà codé ailleurs de manière connue comme fiable par la communauté informatique.
    - Tout code non commenté est rejeté quelle que soit la valeur de son créateur. De ce côté-là, les merge-request / pull-request apportés par les Gitlab, Github ont vraiment fait progresser la qualité des développements en permettant de refuser des commits impropres.

    En un mot : j'écris des applications pour qu'elles fassent un travail particulier, clair et précis, pas pour mettre en valeur le langage utilisé. Qu'importe si je ne l'emploie qu'à 70% de ses capacités, si 99% de ceux qui le lisent peuvent ensuite le comprendre et le maintenir.
    Je comprends et partage tes préoccupations. Le NIH est une plaie, la maintenabilité est importante.

    Ce qu'il faut retenir de mon message précédent : developper en C++ ne se résume pas à sortir 2 gros frameworks, surtout qu'il y a plein de frameworks spécialisés. Ils sont vraiment nombreux. Tu parles de maths, OK, si c'est du matriciel, pars vers eigen ou blaze p.ex. Tes données, en fonction du format, cela va dépendre, dans mes domaines, je vois beaucoup netCDF, HDF, GDAL, avec ou sans sur-couche C++ plus ou moins bien gaulée. Pour les stats, je n'ai pas assez de recul.

    Autre point, je ne parle pas de maitriser le langage, juste de faire le saut dans la modernité. Utiliser des constructions du C++ qui ressemblent beaucoup (sous-entendu: "trop!") à du C peut paraitre rassurant quand on a connu le C++ avant 98 ou quand on vient du C, mais c'est un piège. Ta maintenabilité sera plus importante si tu embrasses le RAII. Je ne parle pas des autre arcanes du langage. Juste de ça. Il arrive un moment où il faut apprendre un minimum d'un langage avant de s'en servir. Toute la difficulté est d'identifier le minimum, pour que sans produire du code de qualité production, au moins produire du code maintenable qui réponde aux besoins. Le RAII devrait faire parti du minimum en C++. Quand on commence à sortir de l'OO, il y a les principes sous-jacent qu'il est bon de comprendre. C'est pareil.

    Citation Envoyé par grunt2000 Voir le message
    – Pour les traitements mathématiques, j'ai l'impression que Python a vraiment des atouts. Je vais voir si mes expériences le confirment.
    Honnêtement, c'est le cas. Les sous-couches mathématiques en Python peuvent-être optimisées (typiquement si tu installes la distribution intel de python via leur site ou conda, tu as encore un gain par rapport à scipy/numpy de base qui va gommer toute différence que tu aurais pu percevoir avec du C++ fait naïvement à la main). L'intégration de calculs scientifiques en Python me parait de moins en moins aberrante. Et si tu vois qu'un cacul n'est pas efficace, tu le fais en C/Fortran/C++ et l'encapsule dans du Python et le tour est joué.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  2. #22
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Il n'y a qu'un point sur lequel je ne suis peut-être pas d'accord avec toi. Et encore, tout dépend de ce que tu veux dire par les termes que tu a employés:
    Tout code non commenté est rejeté quelle que soit la valeur de son créateur.
    Car, pour moi, un bon code est un code qui n'a pas besoin de commentaires. Ou, plus prosaïquement : le bon commentaire est celui que l'on ne devra pas écrire.

    Car, si tu choisi tes identifiants (noms de type, de paramètres ou de variables, de fonctions, ...) correctement, le nom choisi va -- automatiquement -- donner un aperçu de l'utilité du type, de la variable ou de la fonction en question; de sa "raison d'être", de l'utilisation que tu prévois d'en faire.

    A ce titre, on pourrait dire que tout bon code est abondamment commenté, malgré le fait qu'il ... ne contienne aucun commentaire

    Par contre, si tu entends par cette phrase le fait que tu refusera systématiquement un code qui ne contienne pas un commentaire "paraphrasant" le code, là, je ne peux qu'être en contradiction flagrante avec toi. Car ce qui compte, c'est le code, rien que le code, juste le code.

    Neuf fois sur dix, les commentaires qui se trouvent à l'intérieur d'une fonction vont se contenter d'exprimer "autrement" ce que l'auteur du commentaire voudrait que le code fasse, qui est parfois très différent de ce que le code fait effectivement. Or, ce genre de commentaire devient facilement obsolète. Et personne ne prendra le risque de supprimer un commentaire obsolète.

    On en arrive donc régulièrement à se retrouver avec du code contenant des commentaires "d'un autre temps", exprimant une approche qui n'a plus lieu d'être, qui ne représente rien d'autre que du bruit en comparaison du code réel. Et le gros problème, c'est que ce "bruit" risque de devenir bien plus important pour le lecteur du code que le code lui-même: dans le meilleur des cas, le lecteur va lire ce commentaire qui n'a en réalité aucune raison d'être et se "baser sur le fait que c'est ce que fait le code", sans prendre la peine d'aller vérifier si c'est bel et bien le cas.

    Dans le pire des cas, le lecteur va se rendre compte que le commentaire et le code ne sont absolument pas en adéquation, et il voudra remédier à ce problème. La question qu'il devra alors se poser est "qu'est ce que je fais pour y remédier " "Dois-je supprimer ce commentaire indu et en écrire un qui soit en adéquation avec le code " ou "dois-je modifier le code pour qu'il reflète ce que le commentaire dit qu'il fait ".

    La bonne réponse serait -- ou du moins la "moins mauvaise réponse" -- de supprimer le commentaire obsolète et de le remplacer par un commentaire qui dépeigne effectivement le code, car le code a toujours raison. Encore faut il que le lecteur ait "le cran" de supprimer ce commentaire obsolète qui semble "si important".

    La pire des solutions qu'il pourrait choisir est de "plier le code" aux souhaits du commentaire, en le réécrivant pour qu'il lui corresponde effectivement. Car cela aura pour effet de ramener le code peut-être des années en arrière, avec tout ce que cela peut comporter.

    Maintenant, je ne dis pas non plus que tous les commentaires sont mauvais! Les commentaires destinés à "documenter" (souvent appelés "cartouche") une fonction ou un type de donnée, en indiquant leur raison d'être (ainsi que des paramètres éventuels), et leur utilisation voire -- pourquoi pas -- en indiquant l'algorithme qui est utilisé par la fonction ou -- mieux encore, les contrats qui devront être respectés ont toute ma sympathie.

    Mais ce ne sont pas là des commentaires qui paraphrasent le code. Et, de ce fait, ils n'ont pas de "période obsolescence programmée", car l'interface décrite par une fonction restera d'application aussi longtemps que la fonction existera et sera utilisée.
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  3. #23
    Membre éclairé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    605
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 605
    Points : 670
    Points
    670
    Par défaut
    J'ai constaté deux choses :
    – Tout développeur que je connais dira qu'il écrit du bon code. Je n'en ai jamais rencontré aucun qui m'ait dit le contraire.
    Alors ce qui se passe, c'est que plus personne ne commente parce que "Si les autres, eux, le devraient (quand même, ce serait bien vu ce qu'ils écrivent...), soi : non, puisque l'on écrit du bon code, propre.". D'après soi.

    – Le problème n'apparaît pas lors de l'écriture des programmes où tout à ce que l'on fait, l'on ne perd pas son fil directeur.
    Les problèmes viennent plus tard, lors des situations d'urgence ou de la maintenance des années après.
    Là, la seule façon de retrouver la manière dont le code fonctionne est de le lire instruction par instruction, comme si l'on était soi-même le compilateur C++. C'est très fastidieux et très lent. Et plus la fatigue due à cet exercice devient grande, et plus les erreurs d'interprétation s'accumulent.
    Les commentaires, même avec le risque qu'ils soient obsolètes (ce qui est moins fréquent qu'on ne le pense) servent d'index pour se diriger plus vite dans des situations où la vélocité est requise.
    Et si les commentaires s'avèrent faux... c'est encore mieux, puisqu'ils donnent alors l'origine des bugs !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    // Je vais peindre la porte en bleu !
    couleur = ROUGE;
    
    // Qui a raison ?  Celui qui a écrit le code ou celui qui a demandé la règle de gestion écrite dans le commentaire ?
    // On va s'en enquérir auprès d'un responsable métier pour décider duquel des deux (du développeur, de l'analyste métier) s'est trompé.

    Et surtout :
    S'il y a le feu en prod, et que les codes sources qui semblent en cause sont non commentés, c'est irritant.
    S'il deviennent de plus en plus laborieux à lire, qu'on les comprend pas (on ne parvient pas à refaire le raisonnement que le développeur faisait, ou le contexte dans lequel il était),
    alors le jugement tombe vite : ce programmeur qui croyait pouvoir se permettre de ne pas commenter ses traitements tellement il se croyait bon, il va falloir qu'il devienne plus humble et se resocialise. Et plus le bug sera long à dénicher, plus la colère sera grande.

    Des sources dont le code est en erreur, mais qui sont commentés, son développeur se verra moins mal jugé si ses commentaires permettent rapidement de comprendre ce qu'il voulait faire et de repérer l'origine des incidents :
    on aura trouvé son erreur beaucoup plus rapidement, et senti qu'il faisait l'effort de se rendre accessible aux autres. C'est de la politesse, mais ça fait son effet.
    Ça pourra n'être que quelques secondes de stress. "Où c'est qu'il fait ça ? ... Il dit là ? Ah ! C'est juste ça..."

    Les commentaires sont des panneaux indicateurs et des déclarations d'intention pour les autres.

    Et de toutes façons, l'époque est à en mettre et c'est une pratique désormais, alors que les git masters sont de plus en plus féroces et rejettent à tour de bras ce qui leur est soumis.
    Il devient rare qu'un projet open source, par exemple, laisse passer du code non commenté.

    Après tout ce que j'ai écris, tu comprends pourquoi c'est indéfendable.

  4. #24
    Membre expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    739
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2011
    Messages : 739
    Points : 3 627
    Points
    3 627
    Par défaut
    Citation Envoyé par grunt2000 Voir le message
    Les commentaires, même avec le risque qu'ils soient obsolètes (ce qui est moins fréquent qu'on ne le pense) servent d'index pour se diriger plus vite dans des situations où la vélocité est requise.
    Et si les commentaires s'avèrent faux... c'est encore mieux, puisqu'ils donnent alors l'origine des bugs !
    Les 2 phrases ne me semblent pas compatibles. Si on veut être rapide, on ne va pas lire 2 fois l'information (code et commentaire), mais s'attarder sur le plus simple. Si on le lit un commentaire faux, on va continuer la lecture avec une fausse idée du fonctionnement.


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    // Je vais peindre la porte en bleu !
    couleur = ROUGE;
    
    // Qui a raison ?  Celui qui a écrit le code ou celui qui a demandé la règle de gestion écrite dans le commentaire ?
    // On va s'en enquérir auprès d'un responsable métier pour décider duquel des deux (du développeur, de l'analyste métier) s'est trompé.
    Celui qui a écrit le code puisque c'est lui qui écrit les 2 lignes. Ce genre de chose ne devrait pas passer une relecture et les tests justifient le résultat. S'il y a une erreur sur la couleur rouge de la porte parce qu'elle devrait être effectivement bleue, alors le commentaire est juste, mais ce n'est pas lui qui va aide à résoudre le problème, le code étant suffisamment explicite.

    Pour moi, un commentaire doit indiquer

    - les post et pré conditions
    - la raison du pourquoi le code est ainsi ; comme avoir choisi un algo de tri par rapport à un autre dans une situation particulière.
    - ce que le code fait et qui n'est pas explicite (voir qu'il ne fait pas).
    - à quoi sert la classe/fonction et éventuellement quand l'utiliser, pourquoi et comment elle le fait.

    La plupart de ces commentaires peuvent être supprimés par la présence d'un type explicite. Il est inutile de dire qu'une fonction attend une entrée en seconde lorsque le type attendu est std::chrono::seconds par exemple. S'il faut mettre un commentaire pour indiquer que le true en troisième paramètre sert à activer le chiffrement, alors le code n'est pas suffisamment explicite est devrait être remplacé par quelque chose proche de EnableCryto::Yes.

    En quelques mots, le commentaire ne devrait être là que pour ajouter une information que le code ne peut pas explicitement envoyer. Les commentaires qui paraphrase une ligne sont des parasites qui perturbent la lecture.

  5. #25
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Citation Envoyé par grunt2000 Voir le message
    J'ai constaté deux choses :
    – Tout développeur que je connais dira qu'il écrit du bon code. Je n'en ai jamais rencontré aucun qui m'ait dit le contraire.
    Alors ce qui se passe, c'est que plus personne ne commente parce que "Si les autres, eux, le devraient (quand même, ce serait bien vu ce qu'ils écrivent...), soi : non, puisque l'on écrit du bon code, propre.". D'après soi.

    – Le problème n'apparaît pas lors de l'écriture des programmes où tout à ce que l'on fait, l'on ne perd pas son fil directeur.
    Les problèmes viennent plus tard, lors des situations d'urgence ou de la maintenance des années après.
    Sur ce point, j'aurais effectivement du mal à te contredire, car je suis tout à fait d'accord avec toi. Par contre,
    Là, la seule façon de retrouver la manière dont le code fonctionne est de le lire instruction par instruction, comme si l'on était soi-même le compilateur C++. C'est très fastidieux et très lent. Et plus la fatigue due à cet exercice devient grande, et plus les erreurs d'interprétation s'accumulent.
    Les commentaires, même avec le risque qu'ils soient obsolètes (ce qui est moins fréquent qu'on ne le pense) servent d'index pour se diriger plus vite dans des situations où la vélocité est requise.
    Et si les commentaires s'avèrent faux... c'est encore mieux, puisqu'ils donnent alors l'origine des bugs !
    Là, je ne suis plus d'accord avec toi, car, comme je l'ai dit, seul le code importe au compilateur.

    Si tu choisi correctement ne nom de tes fonctions, de tes types, de tes données, le code en arrive à se "commenter de lui-même" si:
    1. tu crées des petites fonctions qui ne font qu'une chose mais qui la font bien
    2. tu crées des variables qui ne seront utilisées que dans un seul but bien précis

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    // Je vais peindre la porte en bleu !
    couleur = ROUGE;
    
    // Qui a raison ?  Celui qui a écrit le code ou celui qui a demandé la règle de gestion écrite dans le commentaire ?
    // On va s'en enquérir auprès d'un responsable métier pour décider duquel des deux (du développeur, de l'analyste métier) s'est trompé.
    A condition:
    • que le responsable métier soit disponible pour "cette connerie"
    • que celui qui a écrit le commentaire soit encore "dans la boite"
    • que celui qui a écrit le commentaire soit pas "occupé à autre chose"
    • ... plein d'autres choses qui pourraient faire que "ce n'est pas le moment" de faire ch...er les gens avec ca...


    Avec un code proche deon n'a pas besoin de commentaires. La porte est rouge. Point.

    S'il s'avère qu'elle doit être bleue, hé bien, on modifie le code en
    Et c'est aussi bien.
    Et si on la veut rouge et verte à petit pois, on modifie le code en
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    peindrePorte(ROUGEETVERTAPETITPOIS);
    Le commentaire n'apporte rien que le code n'apporte pas lui-même de manière explicite. il n'a donc aucune raison d'être !
    Et surtout :
    S'il y a le feu en prod, et que les codes sources qui semblent en cause sont non commentés, c'est irritant.
    C'est encore plus irritant lorsqu'il y a le feu en prod et que les commentaires s'avèrent être totalement décalés par rapport au code.
    S'il deviennent de plus en plus laborieux à lire, qu'on les comprend pas (on ne parvient pas à refaire le raisonnement que le développeur faisait, ou le contexte dans lequel il était),
    alors le jugement tombe vite : ce programmeur qui croyait pouvoir se permettre de ne pas commenter ses traitements tellement il se croyait bon, il va falloir qu'il devienne plus humble et se resocialise. Et plus le bug sera long à dénicher, plus la colère sera grande.
    Des bugs, tu peux me croire, j'ai eu à en gérer un paquet considérable.

    Et, si j'ai ralé sur le fait de n'avoir pas de commentaire, c'est avant tout pour deux raisons:
    parce que je me trouvais face à une fonction kilométrique qui faisait cinq choses en meme temps (et même pas bien)
    parce que je me trouvais face à des noms de variables qui ne me donnaient aucune indications quant à leur utilité.

    Alors, oui, je peux le dire honnêtement : j'aurais sans doute aimé avoir un commentaire sur "maintenant, nous attaquons tel aspect du problème" ou "cette donnée sera utilisée pour...".
    Mais l'un dans l'autre, si le SRP avait été respecté, qu'on avait divisé cette fonction kilométrique en cinq fonctions spécifiques prenant chacune un aspect du problème en charge, si les noms de variables avaient été mieux choisis, je n'aurais jamais eu besoin des commentaires.

    D'ailleurs, c'est bien simple, c'est ce que j'ai fini par faire pour corriger le bug: diviser cette fonction en quatre, cinq, six (en fait, autant que nécessaires) fonctions s'occupant spécifiquement d'un aspect du problème, et choisir des noms "auto commentant" pour les variables de toutes sortes.

    Des sources dont le code est en erreur, mais qui sont commentés, son développeur se verra moins mal jugé si ses commentaires permettent rapidement de comprendre ce qu'il voulait faire et de repérer l'origine des incidents :
    on aura trouvé son erreur beaucoup plus rapidement, et senti qu'il faisait l'effort de se rendre accessible aux autres. C'est de la politesse, mais ça fait son effet.
    Ça pourra n'être que quelques secondes de stress. "Où c'est qu'il fait ça ? ... Il dit là ? Ah ! C'est juste ça..."
    Bien à tord!

    J'admets volontiers que l'on sera "plus enclin" à pardonner à quelqu'un qui aura laissé passer une erreur dans un code lisible que dans un code illisible.

    Mais conditionner son pardon à la présence de commentaires dans le code est absurde, ne serait-ce que parce qu'ils sont le symptome supplémentaire du fait que l'auteur du code a échoué dans son objectif premier qui est: écrire un code lisible et surtout compréensible.

    Après tout, s'il avait jugé son code lisible et compréhensible, il n'aurait jamais estimé nécessaire de rajouter un commentaire pour en faciliter la compréhension .

    Les commentaires sont des panneaux indicateurs et des déclarations d'intention pour les autres.
    Le code n'est qu'un ensemble de panneaux indicateurs et de déclarations d'intentions.

    Les commentaires, c'est du bruit. Avec un peu de chance, ce bruit a du sens, permet de comprendre ce que le code ne permet pas de comprendre.

    Et de toutes façons, l'époque est à en mettre et c'est une pratique désormais, alors que les git masters sont de plus en plus féroces et rejettent à tour de bras ce qui leur est soumis.
    Il devient rare qu'un projet open source, par exemple, laisse passer du code non commenté.
    A mon avis, on ne visite pas les même répertoires git!

    Il y a vingt ans de cela, la règle était presque 1/3 de code pour 2/3 de commentaires!
    Dans les projets que je suis régulièrement, tu trouveras bon nombre de cartouches mais pour ainsi dire aucun commentaire "in situ" (comprends: directement dans le code).

    Maintenant, si les gitmasters demandent à ce que le code proposé soit commenté, poses toi peut être la question de savoir pourquoi... Et tu risques d'être surpris.
    Après tout ce que j'ai écris, tu comprends pourquoi c'est indéfendable.
    A part que tu sembles incapable -- selon tes propres dires -- d'écrire du code lisible et compréhensible, tu ne m'a convaincu de rien du tout.

    Comprends moi bien! Je n'ai pas la prétention de fournir du code qui ne nécessitera aucun changement par la suite! Mon statuts d'expert en C++ ne m'assure qu'une seule chose: les erreurs que je laisserai passer dans mon code seront sans doute bien plus catastrophiques que celles que laisseraient passer un débutant. Et j'en suis bien conscient.

    Mais c'est une idée fausse de croire que le fait de commenter du code puise "comme par magie" transformer du code mal écrit / difficilement compréhensible en quelque chose de facile à lire et à comprendre.

    Un code de m...de restera un code de m...de, quel que soit la quantité de parfum dont on le pulvérisera ou l'écrin dans lequel on le mettra: il sentira toujours la m...de.

    S'il est mal écrit, tu auras beau ajouter tous les commentaires que tu veux, ton code restera mal écrit, et sujet aux interprétations douteuses ou aux quiproquos.

    Quand j'écris du code, je fais en sorte qu'il puisse se comprendre sans l'aide du moindre commentaire, en choisissant correctement mes identifiants, en le séparant en fonctions simples, et en l'indentant correctement.

    Si, à un moment quelconque (peut-être plusieurs semaines après), je me rend compte qu'un commentaire aurait été le bienvenu à une place quelconque de mon code, je ressens cela comme un échec personnel, et je réécrirai donc mon code en essayant de choisir mes identifiants d'une manière plus adaptée qui me permette de n'avoir pas à rajouter le commentaire.

    Comme je l'ai dit, cela ne veut pas dire que je ne met aucun commentaire. Je met systématiquement un cartouche relatif au fichier et un cartouche par type / fonction que je déclare dans mes en-tête. Mais dans l'implémentation de mes fonction tu ne verras jamais un commentaire, à moins que je ne présente ce code dans une optique didactique (dans ce cas, tu verras sans doute un nombre de commentaire égal à supérieur au nombre d'instructions).

    Mais je te mets au défi d'estimer (à juste titre, nous sommes bien d'accord) qu'un commentaire aurait pu être utile pour lever la moindre ambiguité dans mon code!

    A titre d'exemple, récemment, quelqu'un a qualifié le code que je lui présentais de "quasiment poétique".

    Peut-être suis-je trop "imbu de ma personne" je ne peux entièrement écarter l'idée bien que je me voie plutôt comme quelqu'un de généralement modeste.

    Peut-être suis-je une sorte d'OVNI, une personne comme on n'en rencontre qu'une sur 100 ou sur 1000 J'en doute très sérieusement.

    Mais je peux t'assurer qu'il y a beaucoup de développeur professionnels qui voient les choses exactement de la même manière que moi, et qui ne mettent des commentaires qu'à regret dans leur code.
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  6. #26
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 275
    Points : 10 985
    Points
    10 985
    Par défaut
    Ces histoires de commentaires, c'est des histoires d'équilibre. Dans un monde idéal, le code est suffisamment découpé pour que l'on soit capable d'enchainer des fonctions aux noms suffisamment explicites pour voir ce que l'on fait exactement. On peut même y intercaler des assertions pour indiquer dans quel état on pense être avant d'enchainer.
    Seulement en vrai, on a plus souvent des fonctions de 50-100 lignes que des fonctions de 25.

    J'aime beaucoup le résumé de jo_link_noir quant aux commentaires. Car effectivement, ces commentaires sont excessivement pertinents. Le problème? Comment s'assurer qu'ils ont bien été mis? Et bien on met de seuils dans des outils, et on se retrouve vite à voir du code qui paraphrase, et là est le problème. En effet, l'écart entre code et commentaires arrive vite.
    Plus d'une fois je me suis retrouvé à maintenir du code écrit par des personnes passées à autre chose (et dont non contactables) qui faisait autre chose que ce qui était écrit dans les commentaires. Bien évidemment, quand il y a un bug, c'est l'enfer.

    NB: même avec des types opaques comme suggérés par jo_link_noir, avec la philo AlmostAlwaysAuto, il nous faut correctement nommer nos variables, et si jamais une seconde devient milliseconde... il y a un soucis si on veut donner une telle précision.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  7. #27
    Membre éclairé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    605
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 605
    Points : 670
    Points
    670
    Par défaut
    Le principe c'est qu'il n'est pas nécessaire par un commentaire de paraphraser ce qu'une instruction fait, puisqu'il suffit de la lire.
    Mais un commentaire situé au dessus d'un groupe d'instructions impératives qui explique globalement ce que ce bloc atomique fait (parce que l'ensemble de ce bloc va s'exécuter intégralement ou pas du tout), s'avèrera utile pour le résumer.
    Un commentaire au dessus d'une condition aussi.

    Aussi, mes fonctions ont un nombre de commentaires en rapport avec leur nombre cyclomatique. S'il y a trois if ou while, alors il y aura sans doute trois ou quatre commentaires : chacun expliquant pourquoi on est là, et ce que l'on va y faire.
    En Français, et en utilisant un vocabulaire métier dès que possible. Inutile de parler des manip techniques que l'on fait, si ce n'est pas nécessaire. Si je peux m'exprimer avec les mots et le vocabulaire des demandeurs du programme, ce sera mieux.

    Ainsi j'aurais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    // On récupère l'ordonnance et son porte-monnaie
    .... Bloc impératif ...
    
    // On choisit la pharmacie à laquelle son se rend en fonction de l'heure qu'il est
    .... Boucle while ...
    
    // Si aucune n'a convenu on lève une exception
    ....
    // Sinon, on lui soumet notre ordonnance
    ...
    Selon moi, les commentaires expliquent ce qu'un programme a l'intention de faire en langage humain. À quel problème il répond, et la manière dont il a l'intention d'agir.
    En dessous de mes commentaires, je peux écrire en C++, en Java, en ce que je veux, c'est pas le souci.

    Même une méthode privée, dont l'objectif est souvent technique et n'est souvent faite que d'un seul bloc d'instructions impératives ou d'une boucle ou d'un ou deux tests, gagne à prendre un commentaire qui la synthétise un peu.
    En effet, même un exploit technique accompli par quelqu'un un jour peut être difficile à se re-figurer plus tard, et quelques explications ne gêneront pas.


    Quand il y a un problème en production liée au code, c'est qu'au moins une personne fait une erreur.
    Et le principe d'un bug, c'est que l'on ne sait pas quelle envergure il a, et quels labeurs il faudra pour le corriger.
    En prévision de ces situations là, je trouve sage d'avoir des commentaires. Parce qu'il n'est pas certain que l'on sera celui qui ré-interviendra sur son propre code en cas d'incident,
    et je trouve trop sévère de laisser du code sec, sans explications.

    D'autant que quand même si expert de la programmation il y a,
    (chose Ô combien subjective)
    Eh bien on peut se dire que cet expert-là, un commentaire correct, il doit quand même savoir l'écrire. Ne serait-ce que pour qu'il ait un but didactique.

  8. #28
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 965
    Points
    32 965
    Billets dans le blog
    4
    Par défaut
    Sauf qu'en C++, autant faire une lambda correctement et explicitement nommée pour réaliser ce bloc. Et tu as sûrement un équivalent possible dans les autres langages.
    Ajouter un commentaire ça
    - fait redondant avec le code
    - ajoute un truc en plus à maintenir ou il n'aura plus rien à voir à un moment
    Du coup la plus-value d'un commentaire de ce type, sauf éventuellement pour auto-générer de la doc, je cherche encore.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  9. #29
    Membre éclairé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    605
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 605
    Points : 670
    Points
    670
    Par défaut
    Je veux bien la représentation de mon petit algorithme en lambda pour voir à quelle point elle s'avèrerait pertinente
    car j'ai du mal à me représenter ce qu'elle serait pour être si explicite qu'elle éviterait un commentaire métier destiné à expliquer les règles de gestion, que personnellement je pense qu'il est bon de détailler à cet endroit.


    Mais surtout, ce qui m'étonne c'est l'argument où vous dites que vous allez être capable faire une lambda pour répondre à un algorithme métier, ce qui ne me semble pas rien en termes de connaissances pour l'établir déjà,
    et que vous dites que le jour où vous devrez maintenir cette lambda, il y aura déphasage de commentaire.
    Parce qu'implicitement, vous pensez que ce commentaire vous ne prendrez pas le temps de l'éditer correctement ?

    Quand même, c'est pas crédible, ça.


    Bon, mais tout ça n'est pas bien grave si l'on ne se convainc pas les uns les autres de nos pratiques respectives.
    Le débat existait avant nous, il nous survivra aussi.

  10. #30
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 704
    Points
    2 704
    Par défaut
    Un commentaire n'est pas tant utile pour savoir ce que le code fait, mais pourquoi il le fait.

  11. #31
    Expert éminent
    Avatar de Pyramidev
    Homme Profil pro
    Développeur
    Inscrit en
    Avril 2016
    Messages
    1 469
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 469
    Points : 6 102
    Points
    6 102
    Par défaut
    Citation Envoyé par Bousk Voir le message
    Sauf qu'en C++, autant faire une lambda correctement et explicitement nommée pour réaliser ce bloc.
    En quoi un nom de lambda serait-il meilleur qu'un commentaire ? Au contraire, un commentaire a le mérite de pouvoir contenir des espaces et de la ponctuation.

    Personnellement, j'écris des commentaires dans les cas suivants :
    • Résumer en quelques mots ce que fait une fonction ou ce que représente une classe, sauf si le nom de la fonction ou de la classe est déjà un résumé satisfaisant ou si le code n'est pas résumable.
      Le rôle du résumé est d'éviter d'obliger le lecteur à plonger dans le code s'il a besoin d'une information plus précise que le nom de la fonction ou de la classe mais pas forcément aussi précise que le code.
    • Résumer ce que fait un bloc de code, quand il est résumable.
    • Décrire le rôle d'un callback ou d'une fonction virtuelle (sauf si le nom est déjà clair).
    • Commentaires \todo.
    • Rappeler certaines subtilités du C++ que ne connaissent pas la plupart des développeurs de l'équipe. Exemple :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      // Rappel : propriétés de l'initialisation d'une variable locale statique :
      // - Si l'initialisation lance une exception, elle est considérée comme non faite et
      //   sera retentée au prochain passage.
      // - L'initialisation est thread-safe depuis C++11.
    • Expliquer tout choix qui paraîtrait étrange à quelqu'un qui ne connaît pas le contexte. Exemple : bidouille pour contourner un bogue d'un outil externe.
    • Distinguer l'interface de l'implémentation. Exemple : Avertir qu'un certain std::set pourrait être changé en std::unordered_set. Donc l'utilisateur ne doit pas supposer que les éléments sont triés.
    • Pour une classe commune à plusieurs applications qui ne compilent pas forcément avec le même environnement, écrire qu'elle doit pouvoir compiler sur tel programme qui n'a pas accès à tel environnement, qui compile avec tel IDE qui ne supporte pas certaines fonctionnalités récentes du langages ou qui a tel bogue à contourner…
    • Parfois, des commentaires sur la validité des itérateurs, références et pointeurs.
    • Commentaires "voir aussi" (\sa en Doxygen) quand plusieurs fonctions ou classes répondent à des besoins similaires.
    • Commentaires \deprecated quand une fonction ou classe du code commun a une conception foireuse mais doit continuer d'exister un certain temps pour laisser le temps de migrer vers la fonction ou classe de remplacement.
    • Commentaires palliatifs sur la conception foireuse du code legacy qu'on n'a pas le temps de corriger, parce que cela prendrait plusieurs décennies.


    J'oublie sûrement quelques cas.

    Néanmoins, avant d'écrire un commentaire explicatif, je pense qu'il faut avoir le réflexe suivant : Se demander à quoi aurait ressemblé le code si on essayait de le rendre le plus clair possible sans commentaires.
    Cela ne veut pas forcément dire que le code clair sans commentaires sera forcément meilleur. Par exemple, je ne vois pas l'intérêt de transformer un commentaire en nom de lambda.
    Cependant, quand on a besoin d'écrire un commentaire pour clarifier le code, parfois, c'est pour pallier un problème de nommage voire un défaut de conception, comme le cumul des responsabilités.

  12. #32
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Justement pyramidev, c'est ce qu'on dit:

    Un commentaire qui explique le pourquoi d'un code peut encore passer(*), mais certainement pas un commentaire qui explique ce que fait le code.

    (*)Et encore : tout programmeur "un tant soit peu consciencieux" connaît a priori un minimum les chausse-trapes du langage qu'il utilise. Se sentir obligé de rajouter des commentaires pour rappeler ces chausse-trapes, c'est peut être quelque peu condescendant, non

    C'est un peu comme si tu mettais (dans du code non destiné à visée pédagogique, s'entend) un commentaire comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    // WARN: new may throw std::bad_alloc
    int * ptr = new int;
    A priori, les gens le savent

    Et si tu mets cette information en commentaire, par exemple (je me fous normalement de savoir si le cartouche servira ou non à la génération automatique de documentation, mais je vais bien montrer que je sais qu'il peut le faire en utilisant le format doxygen)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    /** @brief Fonction qui crée dynamiquement un objet dérivé de <Type> sur base des paramètres recus
      *
      * @param [in] truc ...blabla
      * @param [in] machin ... blabla
      * @return un pointeur sur le type réel pour lequel on a eu recours à l'allocation dynamique
      * @warning l'allocation dynamique de la mémoire peut échouer.  une exception de type bad_alloc est alors lancée
      */
    TYPE * create(t1 truc, t2 machin){
        if(condition_sur_truc)
            return new TYPE1(/* ... */);
        else if(condition_sur_machin)
            return new TYPE2(/* ... */);
        return nullptr;
    }
    Ben, je suis désolé, mais la ligne @warning ... n'a absolument rien à faire dans l'histoire. Pas plus que les lignes qui auraient pour but d'exprimer (afin édification personnelle du lecteur du code) l'algorithme tel qu'il est mis en oeuvre.

    Pour tout le reste, ce que tu nous expose, ca rentre ni plus ni moins dans ... les cartouches, car ils s'appliquent à une fonction, à un algorithme ou à un type, qui ne souffriront pas d’obsolescence tant que la fonction ou le type existera (c'est à dire : pour ... toujours, a priori) et dont je suis le premier à reconnaître les bénéfices.

    Et encore, je passe volontiers sur le fait que, parfois, un cartouche prend tout son sens, alors qu'il n'apporte pas vraiment de plus value primordiale dans certaines circonstances. Prend l'exemple d'un simple accesseur classique:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    /** @brief permet à l'utilisateur de récupérer la valeur de X
      *
      */
    TYPE getX() const;
    La plus-value de ce genre de cartouche est relativement nulle, vu que n'importe qui lisant getX() se doutera forcément que l'on récupère... la valeur de X (ou sa représentation actuelle en mémoire)

    J'étais, à la base, bien décidé à ne pas citer ce "cas particulier" pour les cartouches, tant j'estime que les cartouches sont utiles et intéressant et tant j'estime que tout type défini par l'utilisateur et toute fonction devrait en être pourvu(e).

    Mais, pourtant, tu seras d'accord avec moi pour dire que ce dernier cartouche est une pure perte de temps étant donné qu'il n'apporte absolument aucune plus value
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  13. #33
    Membre éclairé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    605
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 605
    Points : 670
    Points
    670
    Par défaut
    Le problème, koala01, c'est que tu considères d'entrée de jeu que nous n'allons nous servir des commentaires que pour y écrire au mieux des évidences, au pire des âneries.
    Là dans ton exemple, tu choisis une fonction dont nous n'avons aucune idée de ce qu'elle pourrait faire.

    (je t'en fais une pire en Java si tu veux : Object[] maFonction(Object[] args) throws Exception. Peut prendre n'importe quels arguments, renvoie une série de n'importe quoi (ou null, d'ailleurs...), et ne sait pas ce qui peut l'interrompre.
    C'est la fonction universelle () : elle permet d'écrire un programme avec une seule fonction. On l'appelle avec des arguments différents et on met plein de if dedans...
    Son problème ? Elle a effectivement existé, et je l'ai rencontrée...)


    Je reprends ton premier exemple, en choisissant d'abord un thème à son sujet.


    Code : 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
    18
    19
    20
    21
    22
    23
    /** @brief Réalise une omelette ou un lardon grillé à partir d'ingrédients, s'ils sont frais.
      * @param [in] oeuf Un oeuf. Peut valoir nullptr.
      * @param [in] lardon Un lardon. Peut valoir nullptr.
      * @return Une omelette aux lardons si possible, une omelette seulement ou un lardon grillé seulement, dans cet ordre, sinon.
      * renvoie nullptr si aucun ingrédient n'a été fourni ou si aucun n'est consommable.
      */
    Plat * create(Oeuf oeuf, Lardon lardon){
        // Faire en priorité une omelette (aux lardons, si possible) si tous les ingrédients le permettent.
        if(oeuf != nullptr && oeuf.isFrais())
        {
            return new Omelette(oeuf, lardon);
        }
        else
        {
           // Sinon, chercher à faire un lardon grillé.
           if(lardon != nullptr && !lardon.isPerime())
           {
            return new LardonGrille(lardon);
           }
        }
    
        return nullptr;
    }
    (j'ai sûrement dû louper une instruction quelque-part, parce que le code ne s'illumine pas en C++)

    La personne qui lit la documentation de cette fonction n'a pas besoin d'entrer dans son code pour l'analyser.
    En passant son pointeur de souris au dessus d'elle, elle saura presque tout d'elle. Si le code de niveau d'appel supérieur est fait de dizaines d'appels d'autres fonctions, le temps gagné est important : on n'entre examiner le code des seules méthodes où l'on juge que cela va vraiment être utile.

    @warning, je ne l'utiliserais pas trop, en effet. Par contre, si je voulais aller plus loin et rendre ma fonction plus sage, je l'empêcherais de me renvoyer un nullptr et je l'adapterais pour lui donner ce comportement :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    /** @brief Réalise une omelette ou un lardon grillé à partir d'ingrédients, s'ils sont frais.
      * @param [in] oeuf Un oeuf. Peut valoir null.
      * @param [in] lardon Un lardon. Peut valoir null.
      * @return Une omelette aux lardons si possible, une omelette seulement ou un lardon grillé seulement, dans cet ordre, selon ce qui est possible.
      * @exception AlimentPerimeException si un des ingrédients transmis est impropre à la consommation.
      * @exception AucuneRecetteException si aucun plat ne peut être réalisé avec les ingrédients fournis (probablement parce qu'aucun n'a été fourni).
      */
    ...
    }
    Un commentaire sur un getter est moins utile, il reste sympathique s'il y a du camel case dans le nom de la variable retournée ou si celle-ci n'est pas explicite (quoi que dans ce dernier cas, j'essaierais de renommer le getter en quelque-chose de plus clair : cela ne sert à rien de nommer son getter getXDF() si XDF n'évoque rien à la plupart des gens).

    Là encore, il faut prendre un exemple concret pour l'illuster :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    /** @brief Renvoie la date à laquelle notre tâche s'est terminée
      * @return Date d'arrêt ou nullptr si celle-ci n'est soit pas démarrée, soit pas terminée.
      */
    Date getDateArret();
    Tu ne vois pas encore quoi faire des commentaires parce que tu les imagines comme eux-mêmes pensant en C++ ou répétant le code instruction par instruction.
    Ce n'est pas ce qu'ils font. Ils expliquent ce qu'une fonction va chercher à entreprendre, ses prérequis en terme de paramètres d'appel, et comment elle va réagir en cas de situation inattendue.

  14. #34
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 965
    Points
    32 965
    Billets dans le blog
    4
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    // On récupère l'ordonnance et son porte-monnaie
    .... Bloc impératif ...
    
    // On choisit la pharmacie à laquelle son se rend en fonction de l'heure qu'il est
    .... Boucle while ...
    
    // Si aucune n'a convenu on lève une exception
    ....
    // Sinon, on lui soumet notre ordonnance
    ...
    Citation Envoyé par grunt2000 Voir le message
    Je veux bien la représentation de mon petit algorithme en lambda pour voir à quelle point elle s'avèrerait pertinente
    car j'ai du mal à me représenter ce qu'elle serait pour être si explicite qu'elle éviterait un commentaire métier destiné à expliquer les règles de gestion, que personnellement je pense qu'il est bon de détailler à cet endroit.
    Rien de plus simple, et une lambda n'est rien d'autre qu'une fonction que l'on peut écrire simplement n'importe où. Te suffit donc de traduire tout simplement ton algo en code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    ...
    Ordonnance ord;
    PorteMonnaie pm;
    auto recupererOrdonnanceEtPorteMonnaie = [this](Ordonnance& o, PorteMonnaie& p) { ... };
    recupererOrdonnanceEtPorteMonnaie(ord, pm);
     
    auto trouverPharmacie = [this]() {...};
    Pharmacie* ph = trouverPharmacie();
     
    if (ph == nullptr)
       throw ...
     
    ph->soumettreOrdonnance(ord);
    Clair, net, inutile d'encombrer de commentaires pour décrire ce que ça fait.


    Citation Envoyé par Pyramidev Voir le message
    En quoi un nom de lambda serait-il meilleur qu'un commentaire ? Au contraire, un commentaire a le mérite de pouvoir contenir des espaces et de la ponctuation.
    Mon boulot c'est d'écrire le code, destiné à être lu par d'autres codeurs et compris par le compilo, pas un roman pour tartempion qui n'aurait pas du avoir accès au repo de code s'il n'y comprend rien et cherche juste à savoir comment marche le logiciel.
    Si c'est faire de jolies phrases qui t'intéresse, je t'invite à écrire des spéc, doc et autres manuels. Externes au programme.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  15. #35
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 518
    Points
    41 518
    Par défaut
    Citation Envoyé par Bousk Voir le message
    Rien de plus simple, et une lambda n'est rien d'autre qu'une fonction que l'on peut écrire simplement n'importe où. Te suffit donc de traduire tout simplement ton algo en code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    ...
    Ordonnance ord;
    PorteMonnaie pm;
    auto recupererOrdonnanceEtPorteMonnaie = [this](Ordonnance& o, PorteMonnaie& p) { ... };
    recupererOrdonnanceEtPorteMonnaie(ord, pm);
     
    auto trouverPharmacie = [this]() {...};
    Pharmacie* ph = trouverPharmacie();
     
    if (ph == nullptr)
       throw ...
     
    ph->soumettreOrdonnance(ord);
    Clair, net, inutile d'encombrer de commentaires pour décrire ce que ça fait.
    J'ai du mal à voir ce que ça a de mieux qu'un commentaire. Mais je suppose qu'au moins ça permet de décomposer son code en fonctions sans avoir le problème de "code ravioli" qui va habituellement avec...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  16. #36
    Expert éminent
    Avatar de Pyramidev
    Homme Profil pro
    Développeur
    Inscrit en
    Avril 2016
    Messages
    1 469
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 469
    Points : 6 102
    Points
    6 102
    Par défaut
    Citation Envoyé par grunt2000 Voir le message
    Code : 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
    18
    19
    20
    21
    22
    23
    /** @brief Réalise une omelette ou un lardon grillé à partir d'ingrédients, s'ils sont frais.
      * @param [in] oeuf Un oeuf. Peut valoir nullptr.
      * @param [in] lardon Un lardon. Peut valoir nullptr.
      * @return Une omelette aux lardons si possible, une omelette seulement ou un lardon grillé seulement, dans cet ordre, sinon.
      * renvoie nullptr si aucun ingrédient n'a été fourni ou si aucun n'est consommable.
      */
    Plat * create(Oeuf oeuf, Lardon lardon){
        // Faire en priorité une omelette (aux lardons, si possible) si tous les ingrédients le permettent.
        if(oeuf != nullptr && oeuf.isFrais())
        {
            return new Omelette(oeuf, lardon);
        }
        else
        {
           // Sinon, chercher à faire un lardon grillé.
           if(lardon != nullptr && !lardon.isPerime())
           {
            return new LardonGrille(lardon);
           }
        }
    
        return nullptr;
    }
    Le problème de ces commentaires est qu'ils ne résument pas le code : ils répètent le code.
    Dans un cas comme celui-là, je n'aurais écrit aucun commentaire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    std::unique_ptr<Plat> essayerDeFaireUnPlat_canBeNull(Oeuf* oeufOptionnel, Lardon* lardonOptionnel)
    {
        if(oeufOptionnel != nullptr && oeufOptionnel->isFrais())
            return std::make_unique<Omelette>(*oeufOptionnel, lardonOptionnel);
     
        if(lardonOptionnel != nullptr && !lardonOptionnel->isPerime())
            return std::make_unique<LardonGrille>(*lardonOptionnel);
     
        return std::unique_ptr<Plat>();
    }
    Remarque : Attention, dans le code ci-dessus, on risque de faire une omelette avec des lardons périmés.

    Citation Envoyé par Bousk Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    Ordonnance ord;
    PorteMonnaie pm;
    auto recupererOrdonnanceEtPorteMonnaie = [this](Ordonnance& o, PorteMonnaie& p) { ... };
    recupererOrdonnanceEtPorteMonnaie(ord, pm);
     
    auto trouverPharmacie = [this]() {...};
    Pharmacie* ph = trouverPharmacie();
    Le même code avec des commentaires à la place des noms de lambda :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    Ordonnance ord;
    PorteMonnaie pm;
     
    // Récupérer l'ordonnance et le porte-monnaie.
    [this, &ord, &pm] { ... }();
     
    // Trouver la pharmacie.
    Pharmacie* ph = [this]() {...}();

  17. #37
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Citation Envoyé par grunt2000 Voir le message
    Le problème, koala01, c'est que tu considères d'entrée de jeu que nous n'allons nous servir des commentaires que pour y écrire au mieux des évidences, au pire des âneries.
    Là dans ton exemple, tu choisis une fonction dont nous n'avons aucune idée de ce qu'elle pourrait faire.

    (je t'en fais une pire en Java si tu veux : Object[] maFonction(Object[] args) throws Exception. Peut prendre n'importe quels arguments, renvoie une série de n'importe quoi (ou null, d'ailleurs...), et ne sait pas ce qui peut l'interrompre.
    C'est la fonction universelle () : elle permet d'écrire un programme avec une seule fonction. On l'appelle avec des arguments différents et on met plein de if dedans...
    Son problème ? Elle a effectivement existé, et je l'ai rencontrée...)


    Je reprends ton premier exemple, en choisissant d'abord un thème à son sujet.


    Code : 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
    18
    19
    20
    21
    22
    23
    /** @brief Réalise une omelette ou un lardon grillé à partir d'ingrédients, s'ils sont frais.
      * @param [in] oeuf Un oeuf. Peut valoir nullptr.
      * @param [in] lardon Un lardon. Peut valoir nullptr.
      * @return Une omelette aux lardons si possible, une omelette seulement ou un lardon grillé seulement, dans cet ordre, sinon.
      * renvoie nullptr si aucun ingrédient n'a été fourni ou si aucun n'est consommable.
      */
    Plat * create(Oeuf oeuf, Lardon lardon){
        // Faire en priorité une omelette (aux lardons, si possible) si tous les ingrédients le permettent.
        if(oeuf != nullptr && oeuf.isFrais())
        {
            return new Omelette(oeuf, lardon);
        }
        else
        {
           // Sinon, chercher à faire un lardon grillé.
           if(lardon != nullptr && !lardon.isPerime())
           {
            return new LardonGrille(lardon);
           }
        }
    
        return nullptr;
    }
    (j'ai sûrement dû louper une instruction quelque-part, parce que le code ne s'illumine pas en C++)

    La personne qui lit la documentation de cette fonction n'a pas besoin d'entrer dans son code pour l'analyser.
    En passant son pointeur de souris au dessus d'elle, elle saura presque tout d'elle. Si le code de niveau d'appel supérieur est fait de dizaines d'appels d'autres fonctions, le temps gagné est important : on n'entre examiner le code des seules méthodes où l'on juge que cela va vraiment être utile.
    Et que crois tu que tu fais, si ce n'est émettre une évidence avec des commentaires du style // Faire en priorité une omelette (aux lardons, si possible) si tous les ingrédients le permettent.

    Le cartouche, je n'ai rien contre, il documente la fonction, il te dit comment l'utiliser, et cette information est stable dans le temps

    Mais les commentaire à l'intérieur de la fonction, il ne servent à rien, car il ne font que paraphraser le code.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    /** @brief Renvoie la date à laquelle notre tâche s'est terminée
      * @return Date d'arrêt ou nullptr si celle-ci n'est soit pas démarrée, soit pas terminée.
      */
    Date getDateArret();
    Oui, mais, encore une fois, c'est un cartouche et je n'ai rien contre les cartouches que je trouve au contraire indispensables dans la très grande majorité des cas.

    Tu ne vois pas encore quoi faire des commentaires parce que tu les imagines comme eux-mêmes pensant en C++ ou répétant le code instruction par instruction.
    Ce n'est pas ce qu'ils font. Ils expliquent ce qu'une fonction va chercher à entreprendre, ses prérequis en terme de paramètres d'appel, et comment elle va réagir en cas de situation inattendue.
    Déjà, si un commentaire te parle d'autre chose que du code, c'est qu'il y a un sérieux problème, non

    Donc oui, un commentaire va -- par nature -- essayer d'exprimer ce qu'exprime le code d'une autre manière. Plus ou moins bien tournée, soit, mais le point reste malgré tout acquis.

    De plus, ce n'est pas au commentaires de t'expliquer cela, c'est au code. Code qui doit "s'auto commenter" grâce au choix judicieux des différents identifiants que tu utilises.
    Allez, un petit exemple: mettons une fonction d'une bonne septantaine de lignes, qui va rechercher le nombre de truc et le nombre de bidules dans un jeu de données, puis qui va générer un nouveau jeu de données en fonction des résultat. Comme je n'ai pas d'exemple de ce type sous la main, les instruction effectivement effectuée seront le plus souvent mise sous forme de commentaire.

    Premier essai: aucun commentaire, des identifiants mal choisis. Elle prendra la forme de
    Code : 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
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    void foo(){
        int i;
        int j;
        while(une_condition_generale){
            /* ... */
            if(condition){
                ++i;
            }else if (autre_condition){
                ++j;
            }
            /* ... */
            if(condition){
                --i;
            }else if(autre_condition){
                --j;
            }
            /* ... */
            if(condition){
                /* ... */
                ++i;
                --j; 
            }else if(autre_condition){
                /* ... */
                --i;
                ++j;
            }
            /* ... */
        }
        std::vetor<TYPE> tab{i*j, valeur_defaut};
        /* ... */
    }
    Nous sommes d'accord sur un point: on a envie de taper la tête du type qui a écrit ce genre de code contre un mur. Par chance, il s'en rendra sans doute compte lui-même: son code manque d'expressivité. Il va donc essayer d'améliorer les choses avec des commentaires. Voyons à quoi cela pourrait correspondre:
    Code : 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
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    void foo(){
        int i;    // nombre de trucs
        int j;    // nombre de bidule
        while(une_condition_generale){
            /* ... */
            if(condition){
                ++i;   // j'ai trouvé un nouveau truc
            }else if (autre_condition){
                ++j;  // j'ai trouvé un nouveau bidule
            }
            /* ... */
            if(condition){
                --i;    // je ne prend pas le dernier truc trouvé en compte
            }else if(autre_condition){
                --j;    // je ne prend pas le dernier bidule trouvé en compte
            }
            /* ... */
            if(condition){
                /* ... */
                // ce que j'ai pris pour un bidule dans un premier temps est en réalité un truc
                ++i;
                --j; 
            }else if(autre_condition){
                /* ... */
                // ce que j'ai pris pour un truc dans un premier temps est en réalité un bidule 
                --i;
                ++j;
            }
            /* ... */
        }
        // je veux nombre de truc * nombre de bidules dans mon tableau.
        std::vetor<TYPE> tab{i*j, valeur_defaut};
        /* ... */
    }
    Avec des identifiants bien choisis, tous ces commentaires devenaient inutiles. Car il "suffisait" d'appeler la variable i nombreDeTruc et la variable j nombredeBidule pour que cela prenne une toute autre forme. La preuve:
    Code : 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
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    void foo(){
        int nombreDeTruc;
        int nombreDeBidule; 
        while(une_condition_generale){
            /* ... */
            if(condition){
                ++nombreDeTruc;
            }else if (autre_condition){
                ++nombreDeBidule;
            }
            /* ... */
            if(condition){
                --nombreDeTruc;
            }else if(autre_condition){
                --nombreDeBidule;
            }
            /* ... */
            if(condition){
                /* ... */
                ++nombreDeTruc;
                --nombreDeBidule; 
            }else if(autre_condition){
                /* ... */
                --nombreDeTruc;
                ++nombreDeBidule;
            }
            /* ... */
        }
     
        std::vetor<TYPE> tab{ nombreDeTruc * nombreDeBidule, valeur_defaut};
        /* ... */
    }
    Mieux encore, si j'avais séparé la logique, je n'aurais plus eu 70 lignes de code mais royalement 15 (et deux appels de fonction que j'aurai pu tester séparément), et les derniers besoins de commentaires (ceux qui permettent de "s'y retrouver" dans la logique) disparaissaient.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    void foo(){
        auto nombreDeTruc = compterNombreDeTrucs(/* paramètres*/);
        auto nombreDeBidule = compterNombreDeBidules(/* paramètres*/);
        std::vector<TYPE> tab{ nombreDeTruc * nombreDeBidule, valeur_defaut};
        /* ... */
    }
    Tu pourras donc dire ce que tu veux, mais tu n'arriveras pas à me convaincre, quand le commentaire est autre chose un cartouche destiné à documenter un type ou une fonction, qu'un commentaire puisse être autre chose que l'aveu même de la part de l'auteur du code de son incapacité à le rendre expressif.
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  18. #38
    Membre éclairé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    605
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 605
    Points : 670
    Points
    670
    Par défaut
    Tu n'as pas compris mon objectif initial au travers des commentaires :
    m'en servir comme index pour ne pas avoir à lire les lignes de code, et me diriger avec eux au plus près de l'endroit où là seulement j'irai examiner le code avec un but précis.
    Cela veut dire entre-autres, ne pas avoir à ouvrir tous les sources ni examiner toutes les fonctions pour lire ce qu'il y a dedans.

    Tu peux me montrer tout le beau code que tu veux,
    je pourrais te répondre que c'est seulement d'après toi qu'il est beau et que son contenu bien choisi.
    Je préfèrerai éviter de le lire en entier aux moments critiques, tout simplement parce que le temps ne me sera pas donné pour le faire.

    Si un bug se balade dans 30 000 lignes de code, on est très mal si on doit compiler de tête 30 000 lignes de code et les interpréter, si l'on en est pas l'auteur.
    "Sauf si c'est bien fait", penseras-tu. Mais si ce jour-là on se rend compte que c'est mal fait ?
    Dans quel abîme se trouve t-on alors ?

  19. #39
    Expert éminent
    Avatar de Pyramidev
    Homme Profil pro
    Développeur
    Inscrit en
    Avril 2016
    Messages
    1 469
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 469
    Points : 6 102
    Points
    6 102
    Par défaut
    Citation Envoyé par grunt2000 Voir le message
    La personne qui lit la documentation de cette fonction n'a pas besoin d'entrer dans son code pour l'analyser.
    En passant son pointeur de souris au dessus d'elle, elle saura presque tout d'elle. Si le code de niveau d'appel supérieur est fait de dizaines d'appels d'autres fonctions, le temps gagné est important : on n'entre examiner le code des seules méthodes où l'on juge que cela va vraiment être utile.
    Si je comprends bien, l'outil accepte d'afficher les 10 lignes de documentation d'une fonction, mais n'affiche pas les 10 lignes de code auto-documentés d'une fonction "sans documentation".
    Quand tu fais une manip du genre "clic droit >> aller à la définition de la fonction", existe-il une manip rapide comme un raccourcis clavier pour revenir instantanément à la ligne de code où tu étais juste avant ?

  20. #40
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 068
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 068
    Points : 12 111
    Points
    12 111
    Par défaut
    Citation Envoyé par grunt2000
    Aussi, mes fonctions ont un nombre de commentaires en rapport avec leur nombre cyclomatique.
    Le nombre cyclomatique d’une fonction doit rester bas, et les outils de validations statiques permettent de renforcer cela, pas les commentaires.

    Citation Envoyé par grunt2000
    En Français, et en utilisant un vocabulaire métier dès que possible. Inutile de parler des manip techniques que l'on fait, si ce n'est pas nécessaire
    Non, le vocabulaire métier de l’expert du domaine doit rester cantonné dans la partie "business" de l’application. La couche d’accès au données ne doit être que technique et les couches d’IHM doivent utiliser les concepts données à l’utilisateur final, qui n’a pas à connaitre tout le jargon pour faire ça tâche.

    Citation Envoyé par grunt2000
    Tu n'as pas compris mon objectif initial au travers des commentaires :
    m'en servir comme index pour ne pas avoir à lire les lignes de code,
    C'est bien ce que te reproche TOUS les intervenants (syndrome de Galilée ?).
    Le code est au moins aussi explicite que des commentaires descriptifs à jours.

    En plus, le fait d'avoir un code explicite oblige à travailler la conception, ce que des commentaires "descriptifs" ne permettent pas.

    Cela veut dire entre-autres, ne pas avoir à ouvrir tous les sources ni examiner toutes les fonctions pour lire ce qu'il y a dedans.
    Idem avec des modules, des classes, des méthodes, des arguments, des variables des champs correctement nommé.
    Et en plus, c'est à jour, et c'est cohérent avec la conception voulu.

    je pourrais te répondre que c'est seulement d'après toi qu'il est beau et que son contenu bien choisi.
    Revue par les paires, sans notion de seigneurie, les débutants ayant largement leur mot à dire.
    Et je pense largement que l'approche de @koala01 sera gagnante.

    Je préfèrerai éviter de le lire en entier aux moments critiques, tout simplement parce que le temps ne me sera pas donné pour le faire.
    Idem pour la documentation (pas à jour) et des commentaires qui font un "bruit" complètement contre-productif.
    Conception modulaire et Tests unitaires font largement leur travail ainsi que les mécanismes de dumps et de trace AUTOMATIQUES.
    C'est un problème de méthode et de conception, les commentaires ne font que les cacher "élégamment".

    Si un bug se balade dans 30 000 lignes de code, on est très mal si on doit compiler de tête 30 000 lignes de code et les interpréter, si l'on en est pas l'auteur.
    30 000 lignes de code, c'est rien pour un projet mais si vos mécanismes de détections d'anomalies (watchdog, analyses de log, compteur de performances, etc...) ne permettent pas d'isoler plus finement une anomalie, c'est que vous avez bien merdé la conception de la solution.
    Et 30 000 lignes de code correctement conçu, c'est largement plus rapide à lire et à comprendre que 30 000lignes de commentaire avec une orthographe approximative et qui corresponde à une vue "rêvée" de la réalité et non celle-ci.

    "Sauf si c'est bien fait", penseras-tu. Mais si ce jour-là on se rend compte que c'est mal fait ?
    Dans quel abîme se trouve t-on alors ?
    Si je me retrouve avec du code qui m'oblige à lire les commentaires, c'est directement poubelle et je reprend les spécifications (sauf que bien souvent, les commentaires à gogo, c'est pour ne pas faire de vraie spécification et que le développeur met ses choix par désarrois dans ces commentaires).

Discussions similaires

  1. Que faire après quinze ans en tant que développeur?
    Par alineas1 dans le forum Emploi
    Réponses: 11
    Dernier message: 05/02/2016, 09h42
  2. [Opinion]Que pensez vous du .net framework 10 ans après?
    Par Hinault Romaric dans le forum Général Dotnet
    Réponses: 177
    Dernier message: 02/09/2010, 14h32
  3. Réponses: 15
    Dernier message: 08/10/2009, 09h24
  4. Réponses: 10
    Dernier message: 09/09/2009, 16h32
  5. problème de positionnement 4 ans après.
    Par Ekimasu dans le forum Balisage (X)HTML et validation W3C
    Réponses: 1
    Dernier message: 30/03/2008, 16h00

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo