Après mon exemple est peut-être suffisamment simple pour le remplacer par une assertion, mais en attendant avec plusieurs conditions style :
Une assertion devrait tester de la même manière toutes les conditions déjà évaluées (enfin les évaluer avant), ce qui n'est potentiellement pas très rentable (si tu as des fonctions gourmandes, elles sont évaluées que si nécessaire ici, alors que toi tu les évalues toutes pour constater que l'assertion passe, avant de réévaluer les nécessaires dans les if). En ce sens, les assertions ne sont que du sucre : c'est bien joli pour réduire le code dans des cas particuliers, mais ça n'ajoute rien de concret au langage. Ça n'a donc aucun sens de dire que "c'est la bonne manière de coder". Tu utilises l'assertion si tu veux que ce soit succinct, tu utilise un if else si tu veux quelque chose de plus expressif ou si tu as besoin de quelque chose de plus complexe. Tu peux dire que l'un est mieux que l'autre uniquement quand tu précise le critère de jugement. En attendant, le choix du critère reste subjectif.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10 if (condition1) { traitement1 } else if (condition2) { traitement2 } else ... if (conditionN) { traitementN } else { throw exception // ce cas ne doit pas arriver }
Cependant, le throw indique explicitement qu'on a atteint un point "où l'on ne devrait jamais aller", vu qu'il aura comme résultat de faire remonter un message d'erreur à la pile d'appel.
Encore une fois, le fait que la fonction lance une exception intéresse au plus haut point l'utilisateur de la fonction qui, a priori, ne devrait pas avoir à aller voir ce qui se passe dedans, simplement parce qu'il n'a pas forcément la possibilité de le faire (bon, il l'aura sans doute plus facilement avec java ou C#, mais avec une bibliothèque "fermée" en C++... ) et le code se suffit normalement à lui-même pour celui qui devra maintenir la fonction car, encore une fois, le fait d'indiquer "ceci ne devrait pas arriver" en commentaire ne fait que paraphraser le code.
Du coup, cette information a tout à fait sa place dans le cartouche de la fonction, ainsi que les N conditions qui permettent d'en assurer le bon fonctionnement.
Ceci dit, si N conditions sont possible, il y a de fortes chances que l'utilisateur se trouvera essentiellement dans des situations dans lesquelles il n'aura besoin de s'assurer de la validité que de quelques unes d'entre-elles, quand il n'aura pas à s'inquiéter de la validité que d'une seule d'entre elles.
Désolé si ça porte à confusion : le "ce cas ne dois pas arriver" c'est juste pour rappeler l'objectif de cette ligne. Typiquement ici tu renvois une exception avec une description qui correspond à la version "langage naturel" de la condition qui correspond à ce else (ou quelque chose de plus abstrait/simplifié/compréhensible, l'idée étant de dire pourquoi cette partie n'est pas censée être exécutée). Il n'y a donc pas de commentaire.
De la même manière que le code dans les if doit être assez explicite sur ce que fait le code, l'exception doit être assez explicite sur ce qui fait que c'est une erreur.
Mais le fait que tu lances un exception se suffit à lui-même, surtout si le nom de l'exception est explicite, ne crois tu pas
Le mot clé throw sera assimilé à un "vous n'auriez jamais du arriver ici", et le nom de l'exception (s'il est correctement choisir) te dira pourquoi tu n'aurais jamais du arriver ici...
Le code t'indique donc aussi bien le quoi (oups, tu es arrivé à ce point, c'est pas bien!) que le pourquoi (le nom de l'exception)
Oui tout àa fait, après c'est un choix entre utiliser une exception générique avec un message spécifique ou faire ta propre classe d'exception avec le message spécifique déjà intégré (qui se retrouvera dans les logs, donc à ne pas négliger).
Ben, du seul point de vue de la discussion en cours (car il peut y avoir d'autres aspects à prendre en considération ), que tu aies un code proche de
ou un code proche de
Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 if (condition1) { traitement1 } else if (condition2) { traitement2 } else ... if (conditionN) { traitementN } else { throw SomeGenericException("there are no valid condition"); }
ne changera en soi pas grand chose dans le sens où les deux se suffisent à mon sens amplement à eux-même.
Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 if (condition1) { traitement1 } else if (condition2) { traitement2 } else ... if (conditionN) { traitementN } else { throw NoValidConditionFound(); }
Ce qui importe, dans l'optique de la discussion, c'est que, si tu rajoute un commentaire proche de //vous ne devriez pas passer ici ou, pire encore, proche de //aucune condition n'est vérifiée, ton commentaire ne fera que paraphraser le code et sera donc purement et simplement inutile car le fait qu'une exception soit lancée indique clairement au lecteur du code qu'il y a "quelque chose qui ne va pas"
Quel intérêt de mettre une exception alors ? Si on met une exception, c'est que c'est un cas qui peut arriver et en aucun cas un outil de debug.Le mot clé throw sera assimilé à un "vous n'auriez jamais du arriver ici", et le nom de l'exception (s'il est correctement choisir) te dira pourquoi tu n'aurais jamais du arriver ici...
Parce que personne n'est à l'abri d'une erreur et que cette exception sera toujours plus explicite qu'une erreur générée on ne sait trop où. Perso je préfère qu'on me dise tout de suite que j'ai fais une bourde à tel endroit, parce que la conception considère que ce cas ne doit pas arriver, plutôt qu'on me dise "ici ça marche pas" et que je doive retrouver la source. Si le else correspond à un cas qui est effectivement impossible, c'est le boulot du compilateur de retirer le bout de code qui ne sera jamais appelé (optimisation). D'ailleurs, c'est pour ça que je fais généralement une exception générique avec un message explicite, parce qu'elle n'a pas vocation à être récupérée par le programmeur. Je vais pas créer une classe pour une exception qui n'a pas vocation à être reconnue.
Après qu'une exception soit utilisée pour du debug ou pour faire une opération d'urgence, c'est au choix du programmeur. Quand tu as une exception qui te dis que tu n'as pas pu ouvrir un fichier, si tu ne peux rien faire sans, ben tu te contente de renvoyer l'exception, tu n'en fais rien. Du coup ça fini en debug que tu le veuilles ou non.
Cela dépend des LoC et de la complexité, cyclomatique ou non:
Si l'on parcourt le code source de nombreux langages (php,Java) populaires et programmes, on constatera que :
- toutes ou plupart des déclarations de fonctions sont commentées
- on trouve régulièrement des commentaires dans le code
Mais ce sont le produit d'années/homme de travail.
Questions :
1/ aimez-vous maintenir ou lire le code non commenté d'un autre ?
2/ apprendriez-vous un langage si celui-ci n'a aucune documentation ?
3/ comment écrire un documentation sur un produit non commenté ?
Remarques :
Si vous écrivez votre documentation, vous ne faites que commentez ce que vous avez fait, mais en dehors de son code.
Si vous ne commentez pas, vous ne faites que raccourcir la fin de vie de votre produit: il ne sera pas maintenu, il réclamera une phase d'adaptation conséquente, sa date technique augmentera
Pour une chose assez simple comme de l'ETL, ne pas écrire de commentaires peut se justifier. Mais dès lors que la complexité cyclomatique et le nombre de développeur augmente, la dette technique suit, clairement. Une des manière de la réduire est d'organiser son code, de bien nommer ses méthodes et variables, de ne pas faire de copier-coller. Quitte a faire beaucoup de refactoring.
Une expérience personnelle : mon équipe -de 3- travaillait sur une API en Java, une autre équipe -de 2- travaillait sur l'IHM en .Net et nous a imposé de fournir une documentation. Complète et à jour, c'est la que cela se corse
Nous nous sommes acquitté de la tâche via enunciate, l'autre aspect positif cela nous a aussi imposé une plus grande rigueur dans la définition des API : quand on ne prend pas le temps de relire son code et de se l'expliquer, on ne voit ses incohérences.
Une bonne expérience au final.
Donc prenez l'habitude de commenter, cela ne coute rien et cela fera économiser des millions à votre boite.
Et la prochaine fois qu'on vous demande de reprendre du code non commenté... avertissez que cela sera long, car il n'y a pas de documentation.
Pour les situations qui ne devraient pas arriver, c'est assert qui est approprié : si j'en arrive là alors c'est que j'ai oublié de penser à une situation, c'est une information destinée au développeur et qui ne devrait pas apparaître dans le produit final.
Pour les situations anecdotiques (exceptionnelles ^^) faisant pourtant parfaitement partie des utilisations prévues mais pour lesquelles il est impossible savoir quoi faire ou retourner à l'emplacement de l'exception, on délègue la décision de ce qu'il faut faire à l'appelant, puisqu'il sait mieux que nous quelles sont ses intentions .
Une exception qui dès l'écriture de son throw est destinée à remonter obligatoirement la totalité de la pile est absurde. Si elle n'a aucune possibilité d'être rattrapée alors elle n'a aucune raison d'être.
Ça c'est ta manière de travailler, pas celle de tout le monde. En l'occurrence, entre principes et pratique (au sens être pratique), la pratique prévaut, dans le sens où c'est pas un principe qui fera un code qui marche bien. Par exemple les design patterns ne sont pas bien en soit, tout dépend de comment on les utilise. Les exceptions c'est pareil, en tant qu'outils ils ont peut-être été faits pour une utilisation précise, mais si une utilisation dérivée permet d'avoir une amélioration, même via un compromis, c'est avant tout un choix, et non une règle à suivre. Perso, je préfère ne pas considérer que mon programme est valide par défaut et garder un garde-fou bien pratique : ton assertion n'est plus dans le produit final, mais si tes tests ne sont pas exhaustifs (et en général ils ne le sont pas) rien ne prouve a priori que ça n'arrivera vraiment pas. Je préfère un filet de trop pour des logs évidents plutôt qu'une erreur qui nécessitera potentiellement beaucoup de temps de débogage par abus de confiance.
Sauf que, justement, il n'apparait pas dans le produit final, et qu'il faut être très prudent avec les assert.
Ils ne devraient, en sommes, pas apparaitre au niveau de l'utilisation de la données qu'ils vérifient, simplement parce que si tu finis par te retrouver dans une situation dans laquelle l'assertion n'est pas vérifiée mais pour laquelle tu n'as pas de scénario de test, tu vas te retrouver avec, au mieux, avec un plantage dont tu auras énormément à retrouver l'origine, au pire, avec des données totalement incohérentes.
C'est, en effet, le but principal des exceptionsPour les situations anecdotiques (exceptionnelles ^^) faisant pourtant parfaitement partie des utilisations prévues mais pour lesquelles il est impossible savoir quoi faire ou retourner à l'emplacement de l'exception, on délègue la décision de ce qu'il faut faire à l'appelant, puisqu'il sait mieux que nous quelles sont ses intentions .
Pas forcément.Une exception qui dès l'écriture de son throw est destinée à remonter obligatoirement la totalité de la pile est absurde. Si elle n'a aucune possibilité d'être rattrapée alors elle n'a aucune raison d'être.
Il est souvent largement préférable de faire planter "correctement" l'application suite à une exception qui a remonté la pile d'appel jusqu'au début que de laisser le programme continuer à travailler avec des données incohérentes.
De plus, ce n'est pas parce que l'on n'a pas l'occasion (dans le reste du code existant, s'entend) de traiter une exception au moment où elle est écrite que nous ne nous donnerons pas l'occasion "plus tard" de la traiter correctement.
Ceci dit, l'utilisation d'assertions et d'exceptions n'est pas le réel problème posé par la discussion et ne sont pris qu'à titre d'exemple.
La question posée ici est "Un code bien écrit a-t-il besoin des commentaires ?" et, a priori, qu'il s'agisse d'assertion ou d'exception, ce sont deux choses qui devraient se suffire à elles même et pour lesquelles tous commentaires ne feraient que paraphraser le code, ce qui les rendrait inutiles
C'est étrange comme sujet... et ambigu.
Un 'code bien écrit', c'est à dire avec des retours à la ligne et des sauts de lignes pour aérer le code ou un code parfait, bien conçu, bien réalisé, optimisé
La seule raison de ne pas commenter du code c'est de débuter dans le développement.
L'euphorie du pouvoir de création ( je crois que certains ont appelé çà 'la programmation spontanée' dans un autre sujet ), l'insouciance du lendemain ( maintenance, késako ? ), l'absence de contraintes ( choisir ses projets, ses clients, après tout on fait ce boulot car on adore çà ), bref le bonheur est dans le code !
Et puis, on se trouve confronté aux réalités techniques et professionnelles.
Techniques
Replonger dans du code qui a 10/20 ans, écrit par nous ou pire par un autre, et sans commentaires, est un grand moment de solitude ( moi j'adore, je suis un ours ), et même si le code est 'bien écrit' : CaNeChangeRienALaNecessiteDexpliquerSonHistoire()
Professionnelles
Changer de projets est une évidence, et certains sont gros ( voir énormes ) et l'intervention ponctuelle. Il est inimaginable que les développeurs qui interviennent au milieu de ces milliers de lignes de code, fassent leur petit pâté sans mettre un commentaire et s'en aillent, c'est la catastrophe assurée
Commenter du code est nécessaire, et je suis sûr que même un géant comme Donald Knut s'est fendu de commentaires dans le code de son compilateur.
Alors un peu d'humilité
Et puis, on se trouve confronté à d'autres réalités techniques et professionnelles :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 // Ceci change tout à la nécessité d'expliquer son histoire CaNeChangeRienALaNecessiteDexpliquerSonHistoire() { ... }
Plus sérieusement, je pense que les 17 pages de ce thread montrent bien qu'il ne suffit pas de proclamer "il faut des commentaires !" pour que le code devienne magiquement maintenable, encore faut-il définir lesquels, quand, comment, pourquoi...
Ca c'est pas de l'histoire !
Juste un cartouche pas meilleur que ceux produit par un générateur , qui lui mettra au moins une date...
Ce qui peut changer tout, c'est d'avoir la trace des évolutions.
Il ne s'agit pas, non plus, de commenter chaque ligne de code, mais d'adapter les explications selon le langage utilisé. On ne commente pas de la même manière du Cobol et du Java.
Mais on peut toujours écrire n'importe quoi dans ses commentaires, tant qu'on ne recherche pas la qualité et qu'il n'y aura jamais de revue de code ou d'audit.
Pour ce qui est de la maintenabilité, ce n'est qu'une question de budget... pas de technique.
A priori, si problème de date il y a, c'est essentiellement un problème d'organisation du travail.
Avec les outils existant à l'heure actuelle, avoir un projet important qui n'est pas suivi par un système de contrôle de version quelconque (qu'il s'agisse de mercure, de CVS, de SVN, de git ou n'importe quel autre ne m'importe guère) est une pure hérésie
On va surtout utiliser des normes de codage différentes!Il ne s'agit pas, non plus, de commenter chaque ligne de code, mais d'adapter les explications selon le langage utilisé. On ne commente pas de la même manière du Cobol et du Java.
Et c'est normal dans le sens où l'on parle ici de deux langages totalement différents tant au point de vue du paradigme utilisé que du point de vue des restrictions apportées par chacun de ces langages.
Mais un commentaire inutile ou non mis à jour en java posera exactement les même problèmes qu'un commentaire équivalent en cobol
Justement, le fait est que l'on essaye ici de définir ce qui pourra apporter un minimum de qualitéMais on peut toujours écrire n'importe quoi dans ses commentaires, tant qu'on ne recherche pas la qualité et qu'il n'y aura jamais de revue de code ou d'audit.
Je ne peux que m'inscrire en faux contre cette affirmation.Pour ce qui est de la maintenabilité, ce n'est qu'une question de budget... pas de technique.
Il ne revient absolument pas plus cher d'écrire quelque chose de maintenable que d'écrire un code dans lequel une chatte ne retrouverait pas ses jeunes! Il faut "juste" que le codeur soit motivé à écrire un code de qualité.
C'est la technique utilisée (et je ne parle pas du langage, mais de la manière dont le langage est utilisé ! ) qui rendra un code facilement maintenable (et plus ou moins évolutif) ou non, et c'est la maintenabilité du code qui fera ou non exploser les budgets.
Bien sur, le budget peut influer sur les choix de conceptions (bof, tu sais, ca doit tourner après demain, et j'ai pas envie de te payer une heure à faire en sorte que le code puisse évoluer: contente toi d'un POC pour l'instant, on verra plus tard) et d'une manière sur l'évolutivité du projet, et donc sur le (non) respect de certains budgets, mais, a priori, si le budget a une quelconque incidence sur la technique, il faut surtout la chercher au niveau de celui qui devra mettre la technique en oeuvre et de sa motivation à faire "quelque chose de correct" pour le budget qui lui est imparti.
Parler de date était un exemple, qu'un simple générateur ou gestionnaire de version peut enregistrer mieux que certains développeurs, semble-t-il.
Et l'histoire est une succession de dates, événements, acteurs, paramètres, et autres codes commentés,..
Génial les outils de versionning... à l'heure actuelle,
=> mais les applis à maintenir ne sont pas toutes récentes=> l'industrie logiciel reste encore à s'imposer=> ce n'est pas toujours le développeur qui gère le versionning, surtout en grosse équipe=> et quid dans 10 à 20 ans ?
Ce qui peut sembler inutile en Java ne l'est peut-être pas en Cobol, justement du fait des différences.
Ce n'est pas un commentaire inutile qui pose problème, c'est l'absence de commentaire.
La qualité c'est la bonne pratique,
la bonne pratique c'est de disposer du maximum d'information
l'information c'est d'abord le code commenté
Personne ne sait qui interviendra dans les arcanes de nos sources, quand il le fera, pourquoi il le fera et comment il les abordera.
Alors plus il aura d'informations moins il perdra de temps ( et moins il nous prendra pour un charlot )
Il ne revient absolument pas plus cher d'écrire quelque chose de maintenable que d'écrire un code dans lequel une chatte ne retrouverait pas ses jeunes!
...
c'est la maintenabilité du code qui fera ou non exploser les budgets.
Oui la maintenance à un coût, et plus on perd du temps à comprendre le code plus c'est cher. Et on perd du temps souvent parce que l'on ne comprend pas ce que le développeur a voulu faire et qu'il ne l'a pas expliqué !
Donc c'est bien juste un problème de budget ( de temps ), pas de technique ( même si c'est mal écrit, c'est maintenable ).
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