oui et c'est justement quasiment un contre-exemple à ne pas suivre...![]()
oui et c'est justement quasiment un contre-exemple à ne pas suivre...![]()
??? Ca dépend des langages sans doute, parce que la résolution est généralement statique, et donc le surcoût est... nul.
On va dire que ça ne s'applique pas aux langages qui ne permettent pas al surcharge. Autrement, ça ne change strictement rien dans les langages où la performance est importante.
disons que justement un des problèmes majeurs de bons - longs projets en informatique c'est que tu n'as plus les documents (aucun). Ou, bien que tu ne sais pas si tu peux t'y fier (documents datant de quelques à qualques dizaines d'années, avec une longue histoire de modification depuis).
J'aimerais bien voir (ce que je n'ai pas encore vu) un outil de rétro-ingéniérie correct pour un gros projet complexe...
Je n'affirme rien, je parle juste par expérience..
Je dis juste qu'il est essentiel d'avoir de bons commentaires (comme on l'a spécifié plus haut) dans le code, de différentes natures à différents endroits (documenter le code, documenter le but et les entrées/sorties de la fonction, documenter son algo et sa source, documenter le but global du module, etc etc).
Ceux qui ne le font pas préparent des maux de tête carabinés à leurs successeurs, et ceux qui ne le font pas du tout indiquent simplement que l'on mettra leur code à la poubelle dans le futur..
Concernant le code à plusieurs return ...
c'est une question de point de vue,
Je pense que faciliter la lisibilité n'est pas un principe d'unicité de caractéristique,
au contraire, la complexité nait par le cumul d'un non respect de plusieurs règles :
plusieurs return, dans une fonction qui n'excède pas une 50 aine de lignes, et où le nombre de if imbriqué n'implique pas des conditions complexes, ne pose pas problème,
d'un autre côté, lorsque j'audite du code (ce qui m'arrive fréquemment) de nombreuses cause d'inlisibilité et donc d'erreur proviennent d'une combinaison de ces éléments là.
Car à tout moment, une personne reprenant un code pondu ya un moment va swapper un return et devra y mettre plus que du sien pour pouvoir comprendre la fonction.
Après tout dépends du contexte...
Dans la théorie. En pratique, on va toujours se placer dans le cas concret où on travaille. La surcharge est un outil utile.
50 lignes, des boucles if imbriquées -> c'est un bon candidat au refactoring.
Ce qui est certain, c'est que c'est plus difficile de lire, pour moi, un code qui oblige à avoir un seul return (parce qu'en général, il y a aussi tropd e lignes de code, je pense notamment à l'implémentation C de JXTA qui est une horreur à ce niveau).
Ca se voit, non ? Tu trouves pas ? Le code est plus propre oui. Aussi performant j'en sais rien mais plus propre sans aucun doute.
Ca m'intéresserais d'en savoir plus. Sur quel base dites vous cela. Avez-vous vérifié par vous même ou est ce encore un de ces nombreux mythes de performances ?
De toute façon peut importe. Programmer proprement ne va pas toujours dans le sens des performances. Au contraire, pour des questions de performance parfois on se permet un court circuit, une astuce, quelques chose d'un peu moins propre mais nettement plus efficace. Je dit pas que c'est bien, ni mal, juste que c'est moins propre.
Pour moi bien programmer, programmer proprement c'est avant tout programmer objet. L'objet c'est la surcharge des méthodes entre autre. Si c'est pour ne pas l'utiliser alors c'est que vous vous trompez de langage.
Ou alors on peut brûler tout les livres d'apprentissages...
Pour reprendre l'exemple utilisé plus tôt :
À corriger en :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 // Math.sqrt() replacement using Newton-Raphson algorithm private double SquareRootApproximation(n) { r = n / 2; while ( abs( r - (n/r) ) > t ) { r = 0.5 * ( r + (n/r) ); } return r; }
S'il n'y a pas ces informations (en particulier, la précondition), le code ne saurait être qualifié de "propre". On ne sait même pas comment l'utiliser correctement sans rentrer dans le détail de l'implémentation.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 /// Math.sqrt() replacement using Newton-Raphson algorithm /// @pre n >= 0 /// @post return >= 0 private double SquareRootApproximation(n) { r = n / 2; while ( abs( r - (n/r) ) > t ) { r = 0.5 * ( r + (n/r) ); } return r;
Amen.
exemple cobol(mais que tout le monde comprendra j'espère.....y'a que des booléens)
sera 2 fois plus rapide, environ, que
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14 IF PAIEMENT-A AND TIP-AUTORISE SET COURRIER-TIP TO TRUE ELSE IF PAIEMENT-B SET COURRIER-PRELEVEMENT-AGENT TO TRUE ELSE IF PAIEMENT-C SET COURRIER-PRELEVEMENT-SIEGE TO TRUE ELSE SET COURRIER-CHEQUE TO TRUE END-IF END-IF END-IF
Pourtant, c'est la seconde solution que j'ai choisie - avec l'assentiment de ma hiérarchie(on a pas mal discuté de cet aiguillage, y'avait des conséquences un peu partout(et puis j'ai simplifié la condition réelle)).
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11 EVALUATE TRUE WHEN PAIEMENT-A AND TIP-AUTORISE SET COURRIER-TIP TO TRUE WHEN PAIEMENT-B SET COURRIER-PRELEVEMENT-AGENT TO TRUE WHEN PAIEMENT-C SET COURRIER-PRELEVEMENT-SIEGE TO TRUE WHEN OTHER SET COURRIER-CHEQUE TO TRUE END-EVALUATE
Cette solution a surtout l'avantage de se lire exactement comme la spécification :
==>si c'est un paiement TIP et que celui-ci est autorisé, alors on fait un courrier TIP
==>Si c'est un prélevement agent.....(blablabla)
(.../...)
==>dans tous les autres cas, on envoie le courrier "chèque"
le jour ou la spec change(genre on crée un nouveau courrier pour les gens qui devaient payer par TIP mais n'y sont pas autorisés), le premier code devient illisible, avec une imbrication de plus, alors que le second, y'a juste à rajouter
Et ça reste parfaitement lisible(enfin, à mon sens, peut-être certains ici auront des remarque astucieuses à faire).
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 WHEN PAIEMENT-A AND NOT TIP-AUTORISE SET COURRIER-TIP-ALTERNATIF TO TRUE
C'est vrai que sur une doc qui a un peu vécu, il arrive un moment où on ne sait plus si la doc est fiable (surtout si le code semble faire autre chose que la doc).
J'ajouterais également, que malheureusement, c'est la même chose avec les commentaires dans le code. Dès que le code a un peu vécu, tu finis aussi par te demander si les commentaires sont encore fiables.
Tu as des états vraisemblablements exclusifs dans ton code (à priori, on aurait soit PAIEMENT_A, soit PAIEMENT_B, mais jamais les deux à la fois) mais ça ne se voit pas clairement, il n'y a aucun moyen d'en être sûr.Et ça reste parfaitement lisible(enfin, à mon sens, peut-être certains ici auront des remarque astucieuses à faire).
Le choix d'utiliser des booléens est donc mauvais à mon sens, une énumération aurait sûrement été préférable (après, je ne connais pas Cobol, peut-être n'est-ce pas possible).
Sauf erreur de ma part, il y a un coût de résolution des méthodes uniquement à la compilation, deux surcharges d'une méthode étant considérées comme des méthodes différentes par la suite. Ce qui n'est pas très gênant à mon avis.
En C#:
En MSIL:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13 static void Main() { GetUserData(0); GetUserData("name"); } private static string GetUserData(string name) { return "data by name"; } private static string GetUserData(int ID) { return "data by ID"; }
En assembleur:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13 .method private hidebysig static void Main() cil managed { .entrypoint .maxstack 8 L_0000: nop L_0001: ldc.i4.0 L_0002: call string ConsoleApplication1.Program::GetUserData(int32) L_0007: pop L_0008: ldstr "name" L_000d: call string ConsoleApplication1.Program::GetUserData(string) L_0012: pop L_0013: ret }
Method invocations sur MSDN:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 GetUserData(0); 00000022 xor ecx,ecx 00000024 call FD2FB000 00000029 nop GetUserData("name"); 0000002a mov ecx,dword ptr ds:[02292088h] 00000030 call FD2FAFF8 00000035 nop
http://msdn.microsoft.com/en-us/libr...56(VS.71).aspx
Tu te rends compte de ce que tu dis ? documenter un algo dans le code source c'est parfait pour un tutoriel ou un livre (pour apprendre)pour rendre plus dense, un éditeur de code n'est pas ce qu'il y a de mieux pour documenter.
Aussi, j'ai écris des programmes où chaque caractère d'un commentaire compte comme un octet. Le programme n'est pas chargé en mémoire vive puisque c'est embarqué sur du matériel électronique et ma rom ne fait pas 9pétaoctets pour embarquer le commentaire de l'algorithme de wxy. Bref, cela ne me semble pas généralisable comme approche encore spécifique..
Cela mets en évidence à quel point la difficulté de gérer la documentation et que le code est le document de programmation pas d'architecture, de conception, d'algorithmes tout cela vous devriez le manifester ailleurs sur un blog par exemple
Non bien sur. Mais moi quand je compile du code embarqué, ca me génère un binaire sans commentaires et généralement optimisé pour réduire la taille.
Après on range quelque part les sources du code, le binaire et sa signature md5. Ca permet d'identifier les sources a partir d'une flash, pour peu que la flash soit lisible.![]()
Pour les téléphones ou les consoles j'ai également un doute. Enfin, le code embarqué en fait c'est du pascal et chaque ligne de commentaire compte comme une ligne de programme d'ailleurs c'est toujours le cas avec les delphis 6 chaque ligne de commentaire est compilé
Mais c'est quoi l'histoire ? La terre explose la flash reste lisible des extra-terrestre l'insére dans leur super-extra mégatechnologie puis execute un programme dont le matériel ne se vends plusAprès on range quelque part les sources du code, le binaire et sa signature md5. Ca permet d'identifier les sources a partir d'une flash, pour peu que la flash soit lisible.![]()
En même temps techniquement cela me dépasse et la signature intégre aussi une fonction qui valide les commentaires ?![]()
en fait, c'est presque ça(si j'ai bien compris les énumérations), c'est des "niveaux 88". on a une variable "TYPE_PAIEMENT", et un booléen qui s'active automatiquement suivant la valeur :
J'ai une moulinette qui me calcule le type de paiement - sur un seul caractère. Plutôt que dire IF TYPE-PAIEMENT = 'A', je préfère dire IF PAIEMENT-A(avec un vrai libéllé plus long et plus explicite, mais que je ne peux pas donner ici).
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 01 TYPE-PAIEMENT PIC X(1). 88 PAIEMENT-A VALUE 'A'. 88 PAIEMENT-B VALUE 'B'. 88 PAIEMENT-C VALUE 'C' 88 PAIEMENT-AUTRE VALUE 'D' THRU 'Z'
Mais je ne sais pas si j'ai bien compris ton message. Et je suis toujours preneur d'améliorations(surtout de gens venant d'autres langages, il peuvent avoir des idées que les habitués ne verront même pas). Le code totalement propre, ça n'existe pas, il y a toujours de la place pour s'améliorer.
Là, je crois que c'est ma méconnaissance totale de COBOL qui joue.
En C++ (mais ça vaut aussi pour Ada, C#, Java, etc...), je ferais quelque chose du genre :
puis, toujours :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 enum TypePaiement { PaiementA, PaiementB, PaiementC, ... };
C'est très lisible, et en plus, le compilateur est capable de me donner un warning ou une erreur si j'ai oublié un cas dans mon switch (très utile lorsqu'on rajoute un type de paiement).
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 switch(typePaiement) case PaiementA: .... case PaiementB: ....
Cela dit, je viens de regarder rapidement ce que sont des "Niveaux 88", et effectivement, ma remarque initiale ne s'applique pas ici (par contre, le mécanisme même des niveaux 88 me semble plutôt contre intuitif).
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