J'aime beaucoup cette notion de contrat implicite. :)
Version imprimable
tss tss... Et là j'aurais encore l'argument de l'encapsulation...
Mais même ce code je ne le présuppose pas comme vrai :
Pour moi cette assertion peut claquer. (bon sur un int j'exagère un peu, bien que ça dépende du contexte).Code:
1
2
3
4
5
6 int var(0); //... var = 4; assert(var == 4);
Les contrats implicites c'est bon pour se prendre des baffes dans la figure.
Ah mais si tu explicites tous tes contrats, on va être copains :ccool:. Le fait est que dans la vie réelle, on est déjà content quand on a de vagues infos sur les préconditions, alors les postconditions…
Mais aller contre les postconditions ou la sémantique « intuitives », « implicites », n’apportera que des problèmes. Tu peux le reprocher à l’utilisateur de ta classe, tu peux aussi faire en sorte qu’il n’ait pas de mauvaises intuitions. Le deuxième me semble plus productif ;).
c'est pas pour jouer les chieurs, mais lire le contrat pour les getters/setters est tout aussi important que pour les autres fonctions, ici on a un bon exemple, length pour une chaine de caractère, ça renvoit quoi? le nombre de caractère ou la taille de l'espace mémoire pour stocker cette chaine?
si la chaine est en utf8 par exemple, les caractères pouvant être stockés sur plusieurs octets, les 2 possibilités peuvent varier du simple au triple.
je serai de l'avis de germinolegrand, éviter les présomptions, même sur ce qui pourrait être une évidence.
Le problème, c'est que tu as beaucoup plus de contrats implicites que de contrats explicite.
Pour avoir des contrats explicites, il faut soit un cartouche au dessus de la fonction qui rend les contrats explicites (RTFM :D), soit que la fonction soit correctement nommée; l'idéal étant bien sur d'avoir les deux ;)
Et quand tu te trouves avec une fonction setXXX qui fait plus que ce qu'elle ne dit (définir la valeur de XXX à celle que tu indique) ou pire, qui ne le fait pas du tout (parce qu'elle divise la valeur indiquée par deux ou que sais-je), on ne peut déjà pas se baser sur le nom de la fonction.
Et comme un mutateur disposera rarement d'un cartouche ("c'est une fonction si simple, je vais pas perdre cinq minutes à écrire un commentaire pour cela" t'objecteront certains ;))... il devient difficile d'avoir un contrat explicite ;)
C'est là que le bât blesse : en fonction de ce que tu indiques. C'est une fonction !
Sinon, on n'a pas besoin de mutateur : on met un opérateur =.
Si tu as une fonction setY() qui modélise une fonction mathématique, tu ne t'attends pas à ce que setY(5) induise que Y = 5.
Encore faut il que le contrat soit explicité :aie:
Avec une fonction setXXX, le seul moyen, c'est de se raccrocher au bon vieux RTFM.
Le problème, c'est que certains (beaucoup :question: :aie:):
- ne mettront jamais un commentaire, meme en cartouche ("un commentaire non mis à jour est pire que pas de commentaire du tout" t'objecteront ils)
- ne "perdront quand meme pas de temps à écrire un cartouche pour une fonction si simple que setXXX"
- trouveront surement d'autres raisons pour ne pas expliciter le contrat
je suis d'accord, mais mettre "tout" à la poubelle à cause des mauvaises pratiques des dév, même si c'est la majorité, ça me reste en travers de la gorge :cry:
Non, c'est un comportement ou un service attendu / rendu par ton objet:D
J'ose en effet espérer que tu ne placeras un mutateur que lorsque tu as effectivement besoin de pouvoir faire varier une donnée parce que cela correspond à un comportement ou à un service attendu de la part de ton objet ;)
L'opérateur = n'est utilisable que lorsque tu veux assigner une valeur à une variable existante!Citation:
Sinon, on n'a pas besoin de mutateur : on met un opérateur =.
Mais si tu veux assigner une valeur à un membre de ton objet, tu ne peux pas utiliser l'opérateur =.
Tu imagines un peu le code
Ca ferait du dégât dans les chaumières, non :question:Code:
1
2
3 Button button(/* paramètres */); Font uneFont(/* paramètres*/); obj = uneFont;
Mais setY ne modélise pas une fonction mathématique, elle modélise un comportement :aie:Citation:
Si tu as une fonction setY() qui modélise une fonction mathématique, tu ne t'attends pas à ce que setY(5) induise que Y = 5.
Il y a clairement deux visions différentes ici :
- ceux qui pensent que l’utilisateur n’a qu’à lire la doc (le cartouche de la fonction).
- ceux qui pensent que l’utilisateur ne lit pas la doc, et que pour cette raison le code doit être le plus explicite possible, ce dès le nom de la fonction.
Mon expérience personnelle est que, quand on lit du code (en particulier quand on arrive sur un code qu’on ne connaît pas), on ne commence pas par lire pas la description de chaque fonction (beaucoup trop long), on présume de ce qu’elle fait en fonction du nom.
Mon autre expérience personnelle est que l’utilisateur lui-même ne lit pas la doc, et ne va pas se méfier des effets de bord. Que rien que lui faire lire un contrat du type « non, ma fonction n’accepte pas un pointeur null comme paramètre » est déjà difficile. Alors espérer qu’il se préoccupe d’effets de bord, de complexité des fonctions, etc, est largement au-delà de toutes mes espérances.
Après, si certains ont des expériences contraires, je serai ravi de les entendre. Mais j’ai du mal à comprendre comment certains peuvent trouver que des get/set non symétriques ce n’est pas un problème, alors que c’est seulement une source d’erreur supplémentaire dont on peut aisément se passer et que fondamentalement ça n’apporte rien comme plus-value.
Le seul contrat que j'offre en post-condition c'est que l'objet soit dans un état cohérent, mais je ne garantie pas plus. Donc pas de problème de contrat implicite :D
edit : bon sinon j'avoue je suis dans une optique de Read The Fucking Source Code.
oui, mais bon...
C'est une solution qui a tendance à tendre énormément les relations entre collègues.
Et qui, pour être applicable, doit etre appliquée dés le début du projet.
Lorsque tu arrives sur un projet qui est déjà composé de 2500 fichiers, dont certains ont été écrits par des types qui ne font même plus partie de l'équipe, tu as rarement l'autorité nécessaire (je cherche en fait un autre mot sur lequel je ne reviens plus) pour le faire, surtout quand tu débarques sur le projet ;)
Mon expérience personnelle est que la personne qui crée la fonction n'est pas la plus légitime pour déterminer si son nom est "auto-explicatif".
Il le sera pour cette personne, car elle baigne dans le contexte depuis plusieurs jours. Pour les autres, c'est loin d'être toujours aussi évident.
Ben, il sera beaucoup plus auto-commenté avec un nom qui indique (même de manière partielle) le résultat que l'on obtient qu'avec un simple setXXX :D
Pour autant que j'aie pu en juger dans les différents codes que j'ai parcourus, ma notion du set semble pourtant relativement partagée...
Mais peut etre pourrais tu exprimer ta notion de set, pour que nous puissions en discuter (et te faire changer de point de vue, qui sait ;))
Pour moi, setX(Y) signifie : donner une valeur à X en fonction de Y.
Le cas où X reçoit la valeur de Y est un cas particulier, qon'on pourrait, pour lever toute ambigüité, nommer ce dernier cas setXAs().
Surtout, éviter setTo (= prise de bec) ! :)
Fol que tu es ! :)
Mouais.
Enfin, les setters c'est généralement une double mauvaise pratique
- mise des données en avant au lieu des services, et autre viol de la loi de Déméter (certes, retour à l'argument GUI vs métier -- mais notre métier est-il d'écrire des GUI ?)
- et nom menteur car il ne correspond pas à ce qu'il se passe réellement
Alors je pose la question: Qui est assez naïf pour croire que le contrat d'une fonction au nom mal choisi sera explicité et juste ? Oui, c'est une troisième bonne pratique que d'expliciter correctement un contrat et de le maintenir à jour, mais c'est moins grave que le viol de la LoD (à mon avis), et plus cher à faire respecter qu'un nom juste.
Il n'y aurait pas comme de la mauvaise foi et un problème de priorités à revoir dans cette discussion ? Tout ça pour défendre une mauvaise pratique sur le principe qu'elle domine les bases de code existant ?
mon avis c'est que set ne ment pas, tu proposes une valeur et celui à qui tu fais ta soumission vérifie, traite ta donnée et garde le résultat ou rejette ta valeur en t'engueulant rtfm si tu respecte pas ce qui est demandé en prérequis.
l'important c'est que le destinataire ne rompe pas son propre contrat lors d'un set, sinon c'est que l'auteur n'a pas fait son boulot de ne faire confiance à personne.
la mise en avant des données, c'est aussi se cacher qu'il n'y a pas que les services dans la vie, il faut aussi avoir de quoi les nourrir.
quant à défendre les mauvaises pratiques, ne pas ou mal documenter un composant logiciel est pour moi pire que de mal nommer une fonction ou deux.
dans le cas d'un mauvais nommage, un wrapper et hop le problème est réglé à moindre coût et à notre gout ; par contre une mauvaise ou l'absence de doc entraine un try and die jusqu'à comprendre le bon fonctionnement du composant. et là le coût est très élevé.
Tout le code que j'ai pu croiser avec des set prenait plutôt le sens de assigner à X la valeur indiquée par Y (en utilisant ton propre exemple) ;)
C'est peut etre une assertion honteusement erronée, mais si tu poses à brûle pourpoint la question aux développeurs, tu auras vraisemblablement une réponse souvent similaire ;)
Quand on pense que le simple fait de donner un nom qui correspond au résultat observable permet de faciliter la vie de tout le monde, il est un peu dommage de ne pas le faire, non :question:
- Les services, c'est pour les interfaces publiques. Je ne vois pas en quoi un setter serait gênant pour une méthode privée.
- Je ne vois pas pourquoi donner une valeur à quelque chose ne pourrait pas être un service. Koala, dans sa doc, cite plusieurs cas où cela a un sens.
- Si vous êtes aussi sensibles au mensonge, c'est peut-être parce que vous donnez un sens trop restrictif au mot set.
Dans l'optique du Read The Fucking Source Code, je mets généralement mes mutateurs de type "SetXXX" en inline, extrêmement souvent sur une seule ligne, dans le .h (pas dans un .inl, un seul fichier à ouvrir).
Ca reste du "Set" donc affectation à la valeur fournie seulement, sinon je ne mets pas "Set".
De plus en plus je documente mes mutateurs, même de type Set, sait-on jamais, en plus ça fait plus joli dans une doc Doxygen qu'une fonction membre non documentée (je sais, c'est moche comme argument :aie:).
La majorité du code que j'ai croisé également. Mais pour une raison simple : c'est le moyen de faire la nique à l'encapsulation à moindres frais.
Les développeurs et les "créas" utilisent souvent "fonte" au lieu de "police" et inversement, les commerçants "achalandé" pour dire "bien approvisionné"... Ce n'est pas pour ça qu'ils ont raison. En fait, peu de gens s'interrogent sur le vrais sens des mots, y compris dans leur propre métier et leur propre langue.
A condition qu'on me donne un mot équivalent pour faire ce qui correspond à la définition que j'ai donnée.
Set est un mot anglais signifie fixer, définir.
J'ose espérer que "I set your salary to 100k€" signifiera bien que "your salary is now 100k€".
Autrement dit, pour la seule raison que j'ai appelé la fonction linguistique "oodini.setSalary(100k€)", j'espère bien que "oodini.getSalary()==100k€".
Après, libre à l'implémentation du sieur oodini de mentir, pour me dire que son salaire est bien celui que je lui ai assigné.
(je sais pas, je me sentais généreux, sur ce coup-ci)
L'idée, c'est que si je décide de fixer une valeur, par le biais de l'interface mise à ma disposition, et que je demande cette valeur, j'obtient bien ce que j'y ai mis (pour peu que la documentation n'indique pas une conversion explicite).
IIRC, À propos de contrat, c'est au client de le vérifier et balancer l'exception. Un non respect dans le code appelé, de l'undefined-behaviour est tolérable quand on reprend les articles/livre fondateurs.
Sinon,
- Un setter en privé, ne mérite pas vraiment que l'on s'attarde sur le sujet. Si violation de nom il y a, tant pis pour le développeur de la classe.
- Pour le service de taper dans des données, oui il arrive que cela soit valable. Mais majoritairement, c'est du mauvais design.
- Sommes-nous trop restrictifs pour le sens de set? Ou conscients qu'il existe quantité de verbes qui seront bien plus adaptés à chaque cas ?
Quant à aller bidouiller les données, j'insiste, c'est ça la mauvaise pratique. Un code que j'ai audité il y a peu avait une structure avec un champ pointeur public, un destructeur qui faisait le delete[], et des codes clients qui allaient modifier comme des sauvages le pointeur sans regarder ce qu'il y avait dedans avant. Plus une copie non gérée.
Certes ils aurait pu patcher avec un setBuffer(char *) qui fait le RAZ qui va bien. Et pourtant vous savez tous que cela eut été faux (car le delete[] et le new[] peuvent alors être incompatibles).
La solution que j'ai préconisée, un respect de la LoD avec un resize(size_t), ou un setData(char const*, size_t) -- et là je vois avec le recul que copyData() eut été une solution bien meilleure. (et un std::vector en interne)
C'est là que l'on n'est visiblement pas d'accord.
Le fait est que de nombreux codes que l'on croise ne font effectivement qu'assigner à un membre dont le nom est donné par le mutateur (au mépris de LoD et de ISP !!!!) la valeur fournie en paramètre, et que cela "doit être ainsi" dans "l'inconscient collectif".
On pourrait, éventuellement, considérer qu'un mutateur qui ne fait effectivement que cela "Et tant pis pour toi si la valeur indiquée est non conforme" ne ment effectivement pas à l'utilisateur, mais on se rend compte qu'il contrevient (comme je viens de le rappeler) à au moins une loi et un principe qui correspond à un des piliers de la programmation orientée objets, sans oublier la joie que cela va t'occasionner au débuggage :aie:
A coté de cela, tu as quelques mutateurs qui vont vérifier la cohérence, faire le café et embrasser la mariée.
A partir du moment où "l'inconscient collectif" estime qu'un mutateur a un comportement qui ne correspond pas à ce que fait le tien, il y a discordance entre ce que l'utilisateur comprend de ce qu'est sensée faire ta fonction et ce qu'elle fait effectivement, et l'on peut donc dire que ta fonction ment à l'utilisateur ;)
Non, il y a aussi des comportements.Citation:
la mise en avant des données, c'est aussi se cacher qu'il n'y a pas que les services dans la vie,
La distinction entre le comportement et le service est qu'un service est d'office publique (accessible depuis partout) alors qu'un comportement peut ne pas être publique et n'être qu'une partie "interne" d'un service rendu ;)Ben quoi, on sait les nourrir sans problème:Citation:
il faut aussi avoir de quoi les nourrir.
Mais:
- Avec membres de l'objet, pour commencer
- En leur fournissant des arguments ensuite
- Crois tu vraiment améliorer l'encapsulation en plaçant la donnée en accessibilité privée et en fournissant un mutateur :question:
- Ne crois tu pas que tu pourrais fournir un nom qui indiquera clairement le résultat que tu vas obtenir plutôt qu'un setXXX qui est la solution de fainéantise :question:
Je n'en suis pas persuadé.Citation:
quant à défendre les mauvaises pratiques, ne pas ou mal documenter un composant logiciel est pour moi pire que de mal nommer une fonction ou deux.
D'abord, parce que le premier réflexe de l'utilisateur n'est pas d'aller voir la doc, mais de se baser sur le nom des fonctions, en estimant "qu'elle fait ce qu'on attend d'elle" et en se basant sur sa propre lecture (du nom de la fonction) pour "déduire" ce qu'elle est sensée faire
Ensuite, bien que je ne partage pas ce point de vue, l'argument du "mieux vaut pas de commentaire qu'un commentaire non mis à jour" a malgré tout des accents de vérités.
Si tu ne peux pas demander au développeur de choisir des noms de fonctions explicites, n'essaye pas de lui demander de tenir un commentaire à jour :aie:
C'est parfois pas aussi simple :aie:Citation:
dans le cas d'un mauvais nommage, un wrapper et hop le problème est réglé à moindre coût et à notre gout ;
Que tu pourrais éviter si ta fonction portait un nom cohérent avec ce qui est fait ;)Citation:
par contre une mauvaise ou l'absence de doc entraine un try and die jusqu'à comprendre le bon fonctionnement du composant. et là le coût est très élevé.
Nous sommes d'accord.
Tout à fait.
Eh non, tu fais erreur : tu as, dans ce codage un peu trop conforme aux us et coutumes, oublié la préposition to pour conserver le sens introduit ci-dessus. La présence de ce mot n'est pas anodine, et a un rôle bien précis.
Je te laisse la liberté de jouer avec la langue.
Ce contentement t'a porté préjudice.
Il faut utiliser une fonction setTo(), ou setAs(), mais pas une fonction set().
...avec une fonction mal nommée
Un livre de grammaire peut également être utile.
En ce qui me concerne, je suis disposé à me conformer aux usages de la majorité, mais vous ne me ferez pas admettre que la majorité a raison.
Ah, commencerait on à converger :question:
Et, sincèrement, tu ne trouves pas embêtant de "faire la nique à l'encapsulation", pour reprendre tes propres termes :question:Effectivement, mais le débat ne porte ni sur l'utilisation de fonte ni sur celle de achalandé :DCitation:
Les développeurs et les "créas" utilisent souvent "fonte" au lieu de "police" et inversement, les commerçants "achalandé" pour dire "bien approvisionné"... Ce n'est pas pour ça qu'ils ont raison. En fait, peu de gens s'interrogent sur le vrais sens des mots, y compris dans leur propre métier et leur propre langue.
Et un nègre (au sens littéraire du terme, hein :D) pour écrire ton code, et une secrétaire pour faire ta paperasse en prime :question:Citation:
A condition qu'on me donne un mot équivalent pour faire ce qui correspond à la définition que j'ai donnée.
Ce que l'on te propose, et c'est déjà pas si mal :D, c'est d'essayer de trouver le terme qui convient ;)
Encore faut il voir de quelle majorité tu parles :aie:
Nous n'essayons très certainement pas de te convaincre que la majorité des développeurs (celle qui a fait la base de code existant) a raison, car il est clair pour nous qu'elle a tord :D
Par contre, si tu parles de la majorité des intervenants à cette discussion, soit, mais montre nous alors que nous faisons fausse route et que notre raisonnement est incorrect ;)
Ca, c'est le but ultime, on commence par te donner les outils pour y arriver ;)
yep. C’est aussi ce que j’ai appris.
C’est un cas qu’on avait oublié d’évoquer, tiens, le mutateur qui prend un pointeur. Quid de l’ownership ? Avec copyData, le sens est beaucoup plus clair :ccool:Citation:
La solution que j'ai préconisée, un respect de la LoD avec un resize(size_t), ou un setData(char const*, size_t) -- et là je vois avec le recul que copyData() eut été une solution bien meilleure. (et un std::vector en interne)
Bah... Dans 10 ou 20 ans, elle aura peut-être raison.
Les paradigmes de programmation sont mouvants.
Mon propos est simple :[*] le terme set est mal compris (mon diagnostic)[*] de là, il est souvent mal utilisé[*] de là, on lui reproche mille maux, souvent de manière injuste
Ce qui me frappe le plus, ce sont les dogmes : "il ne faut jamais faire ceci ou cela", "il ne faut pas violer telle règle ou telle règle".
Il faut bien comprendre que les règles sont faites pour se prémunir des mésusages, mais il faut garder son discernement, avoir un sens critique sur la situation, et s'adapter quand cela est nécessaire.
OUI, parfois on peut utiliser les pointeurs et des fonctions du C.
OUI, parfois on peut utiliser un dynamic_cast ou un goto.
OUI, on peut avoir à coder des choses sales pour que le code soit efficace, tout en sachant qu'il ne sera pas maintenable.
Si si tu lui interdit l'utilisation de "set" dans les règles de codage :D
Plus sérieusement, le mauvais développeur acceptera sans doute plus facilement la contrainte de "veux tu bien changer ce nom qui ne veut rien dire" que n'importe quelle contrainte portant sur des aspects qui ne lui semblent pas primordiaux ou risquant, à ses yeux du moins, de poser d'avantage de problèmes que cela n'apporte de solutions (comme un cartouche pour toute fonction déclarée "qui risque de ne pas être mis à jour").
Bien sur, un sérieux "écrémage" ne serait peut etre pas du luxe dans la profession, mais on risque d'attendre encore une ou deux générations avant qu'il ne survienne :cry: ;)
Tu oublies un aspect primordial, sur lequel tu as même fini par tomber d'accord :aie:
Oui, le terme est globalement mal compris, oui il est donc (oserais-je dire forcément :question: allez, j'ose :D) mal utilisé et oui on lui reproche mille maux.
Mais non, ce n'est pas pas injustifié: notre justification se trouve dans la base de code existante ;)Il ne me semble pourtant pas que quiconque ait été à se point dogmatique dans la discussion.Citation:
Ce qui me frappe le plus, ce sont les dogmes : "il ne faut jamais faire ceci ou cela", "il ne faut pas violer telle règle ou telle règle".
Bien sur, certaines raisons invoquées on trait à des principes reconnus, mais cela me semble normal, dans le sens où il y a effectivement lieu de mettre une pratique "habituelle" en relation avec des principes globalement admis, non :quesiton:
Oui, à un bémol près:Citation:
Il faut bien comprendre que les règles sont faites pour se prémunir des mésusages, mais il faut garder son discernement, avoir un sens critique sur la situation, et s'adapter quand cela est nécessaire.
S'il faut garder le sens critique au niveau de l'implémentation, la conception en elle-même a très fortement intérêt à être sans faille.
Le meilleur moyen d'avoir une conception sans faille est, quoi qu'on en dise, de ne prendre aucune liberté vis à vis des lois, principes et concepts que l'on doit appliquer.
Ou plutôt: tu auras tout à gagner à ne prendre aucune liberté sur le sujet, car cela ne fait qu'armer le pistolet qui finira par te tirer, tot ou tard, une balle dans le pied. La question n'étant pas de savoir SI il va tirer, mais QUAND, et avec quelles conséquence ;)
Toutes ces discussions ont déjà eu lieu, et, si tu fais une recherche sur le forum, tu te rendras compte que nous sommes tous d'accord avec cela, à un bémol près:Citation:
OUI, parfois on peut utiliser les pointeurs et des fonctions du C.
OUI, parfois on peut utiliser un dynamic_cast ou un goto.
OUI, on peut avoir à coder des choses sales pour que le code soit efficace, tout en sachant qu'il ne sera pas maintenable.
Cela doit se faire dans des circonstances dans lesquelles cela représente clairement la moins mauvaise solution (à défaut de représenter la meilleure :D), c'est à dire être clairement documenté et justifié ;)
Cela implique aussi que les cas où nous devrons le faire de la sorte se doivent de rester exceptionnels ;)
Mais, cela signifie donc qu'il faut de très bonnes raisons, imposée par des situations particulières pour décider de faire de la sorte.
Au final, il vaut mieux avoir un discours proche de "a priori, faite de la bonne manière (celle qui n'utilise ni pointeur ni fonction du C, celle qui évite les transtypages, celle qui n'utilise pas goto) et si (et uniquement si) vous n'en sortez réellement pas de la sorte, envisager l'alternative crado".
Ne crois tu pas que ce genre de discours est préférable à la bénédiction pure et simple quant au fait de recourir à une solution "crade" :question:
le set a quand même l'avantage d'exposer l'unicité de la cible, je ne connais pas de meilleur mot "clé" pour ça.
effectivement ça lui donnera moins de boulot, mais si je dois demander à l'auteur de changer quelque chose, c'est que je devrais faire confiance à ce qu'il a écrit, je préfère dans ce cas qu'il me documente sa chose avec le max de précision plutôt que de compter sur un choix de nommage.
avec une vraie doc, je pourrai démontrer que son code ne respecte pas le contrat qu'il a édicté, alors qu'un changement de nom sera toujours propice aux "mais tu n'as pas compris comment il fallait s'en servir".
la responsabilité devant revenir à l'auteur et non pas au client en cas de non respect d'un quelconque contrat, selon moi.
A priori, il faut quand même respecter OCP aussi, dont on n'a pas encore parlé ;)
L'idée est donc que l'on devrait nommer la fonction sur base du service qu'elle rend au moment où on l'écrit (ou lors de la revue de code qui précède un gros commit ;)).
Si, pour une raison ou une autre, il apparait comme nécessaire, après une évolution de renommer une fonction, c'est qu'on n'a, de toute évidence, "loupé quelque chose" en terme de respect du principe "ouvert fermé" ;)
Si tu préfères le point de vue opposé, on peut dire que, a priori, le nom de fonction sera relativement stable, une fois qu'il aura été choisi avec soin.
La nécessité de renommer une fonction n'apparait donc que dans quelques cas bien particulier, et est généralement mauvais signe, non :question: