ça dépend des langages, ça, en COBOL, le CONTINUE ne fait juste rien...![]()
ça dépend des langages, ça, en COBOL, le CONTINUE ne fait juste rien...![]()
Et je viens de me rendre compte que je n'ai pas fait une règle de base du code sale : j'ai utilisé des parenthèses !
Allez, combo avec les règles des booleans incompréhensibles, de l'indentation naze et des noms de méthode qui veulent dire l'inverse de ce qu'elles font (parce qu'une méthode qui renvoie quelque chose qui s'appelle "set", c'est aussi assez terrible)
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 for (MonObjet o : maListe) {if (o.set42()^true?false:true) continue; // plein de code}
Ça me rappelle quand j'étais étudiant, la première fois que j'ai fait du Delphi.
J'avais besoin de programmer l'équivalent d'une boucle (while) avec un "switch" dedans.
Dans pas mal de langages (C, C++, Java, javascript...) quand on a un switch-case, il faut mettre un "break", sinon le programme exécute le "case" suivant (=fallthrough).
Pas en Delphi.
En Delphi, pas besoin de "break" dans un "case".
Le "break" sort de la boucle... (il m'a fallu un moment pour comprendre ce qu'il se passait...)
Quand on y pense, c'est très logique.
Le problème, c'est quand on a été exposé à d'autres langages qui forcent l'usage du "break".
Exemple de syntaxe en Delphi :
http://www.delphibasics.co.uk/RTL.asp?Name=Case
Le C#, lui, a choisi une solution un peu bâtarde : comme en Delphi, on ne peut pas faire de "fallthrough" car c'était source d'erreurs, par contre il faut impérativement mettre un "break" sinon le compilateur n'est pas content...![]()
"On en a vu poser les armes avant de se tirer une balle dans le pied..."
-- pydévelop
Derniers articles:
(SQL Server) Introduction à la gestion des droits
(UML) Souplesse et modularité grâce aux Design Patterns
(UML) Le Pattern Etat
Autres articles...
On a parlé du code sale en général, mais il faut savoir qu'on peut faire du SQL sale aussi...
Si vous utilisez MySQL, il y a trop de moyens de faire des trucs sales... Parce que le parseur est tellement laxiste que vous pouvez mettre à peu près tout et n'importe quoi et ça marche
Oui, il n'y a rien derrière le where, mais il s'en fout, il considère que tout va bien.
Code : Sélectionner tout - Visualiser dans une fenêtre à part delete * from mytable where
Structure des données
Si vous le pouvez, nommez vos tables et vos colonnes avec des noms réservés... Quel plaisir de nommer une table "Table", ou "Drop"... Une colonne "delete", ou "select", Un ID nommé "Sequence"...
Vous avez aussi le droit d'utiliser des accents (surtout les majuscules accentuées si votre base de données vous le permet), et des espaces dans les noms !
Requêtage
Si vous pouvez ne pas mettre d'espace pour séparer vos instructions, faites le ! La requête sera nettement moins lisible !
Comme pour les règles générales du mauvais code, n'oubliez pas de mettre des faux commentaires, une indentation pourrie...
Code : Sélectionner tout - Visualiser dans une fenêtre à part select *from myTable where column1=445and name<>'name'
Dès que possible, utilisez de sous-select dans la clause where !
Plutôt que d'écrire
écrivez
Code : Sélectionner tout - Visualiser dans une fenêtre à part select * from matable where myDate > to_date('01-01-2015','dd-MM-yyyy' )
D'ailleurs, vu qu'on formate une date, faites le correctement...
Code : Sélectionner tout - Visualiser dans une fenêtre à part select * from matable where myDate > (select to_date('01-01-2015','dd-MM-yyyy') from dual)
Abusez des conversion de type !
Code : Sélectionner tout - Visualiser dans une fenêtre à part select * from matable where myDate > (select to_date('01201501','ddyyyyMM') from dual)
Code : Sélectionner tout - Visualiser dans une fenêtre à part select * from matable where id = (select to_number(to_char(to_date('05201406','MMyyyyDD'), 'yy')) from dual)
Avec des commentaires foireux et une indentation pourrie, ça pourrait donner un truc comme ça
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 select * -- je connais pas le nom des colonnes from matable where id--hy o = (select--ion to_number(to_char--commentaire (to_date('05201406'--nombre d'or ,'MMyyyyDD'--legende ancienne ), 'yy')-- il manque une parenthèse ) from dual)
L'étape ultime, ça serait de créer des procédures stockées qui ont à peu près le même nom que les fonctions existantes, mais qui ne font pas du tout ce qui est demandé. Du genre un trime(valeur) qui rajoute un espace avant et après...
Si vous avez une fonction to_date(chaine, pattern), créez une fonction todate(chaine, pattern) avec les mêmes paramètres qui permet de déterminer la taille de la chaîne passée dans le deuxième paramètre.
Bon, je viens de tomber à l'instant sur un requête SQL qui s'approche de beaucoup des conseils que je donne
Sachant que la colonne datdt_date est de type DATE, saurez-vous dire ce qu'est censé faire la requête?
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 update DCODAT set DATST_SEMAINE_DERNIERE = 1 where (to_char(datdt_date,'YYYY') || to_char(datdt_date,'IW'))= (select ((select to_char((select (select trunc(sysdate)-7 from dual ) from dual),'YYYY')from dual) || ( select to_char((select (select trunc(sysdate)-7 from dual ) from dual),'IW') from dual)) from dual)
(et je me rends compte que j'ai des maîtres en matière de code pourri)
Dès fois tu peux remplacer du code "compréhensif" "compréhensible" avec des listes, des boucles, etc. par 1 seule requête SQL![]()
Exemple:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 request->SQL->Clear(); request->SQL->Add(L"SELECT (first_id." + key + "+1) AS start_id, MIN(last_id." + key + ")-1 AS stop_id"); request->SQL->Add(L"FROM (" + table + " AS first_id LEFT JOIN " + table + " next_id ON (first_id." + key + "+1)=next_id." + key + ")"); request->SQL->Add(L"LEFT JOIN " + table + " last_id ON first_id." + key + " < last_id." + key); request->SQL->Add(L"WHERE (next_id." + key + " IS NULL) AND (last_id." + key + " IS NOT NULL)"); request->SQL->Add(L"GROUP BY first_id." + key + ", next_id." + key);
Pas besoin d'aller plus loin. Rien que d'utiliser MySQL, c'est sale...![]()
C'est vrai qu'on peut faire des trucs moches en SQL (indenter de manière complètement aléatoire, tout mettre sur une ligne, faire des jointures avec un cross-join et la condition dans le WHERE, utiliser des alias incompréhensibles, etc.) mais MySQL, c'est le fond du trou.
Il n'y a qu'à demander à sqlpro ce qu'il en pense :
http://blog.developpez.com/sqlpro/p9...oudre_aux_yeux
Mais en plus, maintenant, MySQL s'amuse à nous troller de manière régulière, lorsqu'on recherche de la documentation sur une fonctionalité d'Oracle et qu'on tombe sur... la doc de MySQL (parce qu'Oracle a hérité de MySQL en rachetant Sun).![]()
"On en a vu poser les armes avant de se tirer une balle dans le pied..."
-- pydévelop
Derniers articles:
(SQL Server) Introduction à la gestion des droits
(UML) Souplesse et modularité grâce aux Design Patterns
(UML) Le Pattern Etat
Autres articles...
Moi aussi, des fois, j'aimerais tomber sur du code compréhensif; du code qui réalise à quel point on galère et qui viendrait nous aider, nous montrer la marche à suivre...
Mais non, ça n'existe pas. Au mieux, on peut parfois tomber sur du code compréhensible, mais c'est rare (et ce n'est pas l'objet de ce tutoriel).
![]()
"On en a vu poser les armes avant de se tirer une balle dans le pied..."
-- pydévelop
Derniers articles:
(SQL Server) Introduction à la gestion des droits
(UML) Souplesse et modularité grâce aux Design Patterns
(UML) Le Pattern Etat
Autres articles...
Je me suis auto trollé aujourd'hui avec du code bien sale que je croyais propre. Soit une date java placée sur le 15 du mois. On veux reculer a peu près d un mois. Seul le mois nous intéresse, une erreur de quelques heures est sans conséquence.
je vous spoile pas essayez de deviner le résultat à partir du 15 juin...
Code : Sélectionner tout - Visualiser dans une fenêtre à part date = new Date (date.getTime () - 1000 * 60 *60 * 24 *30);
Sinon en java:
4 5 annotations imbriquées en début de classe suivies de 4 5 déclarations de constante histoire qu'il faille 10 minutes pour trouver les interfaces implémentées...
Ne pas hésiter a créer des effets de bords dans des aspects
Accéder par introspection à un champ privé d'une classe de la jre et en modifier la valeur.
Et une surprise pour demain si j'arrive à la finaliser.
Ben quoi ? Il est où le problème ? Il est bien spécifié qu'on peut se permettre une erreur de "quelques" heures.
Si on dit que "quelques" = 24, alors on est bon, non ?
Non, là où ça devient vraiment intéressant, c'est plutôt autour du 1 ou 2 Mars...
Sinon, pour rendre ton code vraiment crade, on peut faire plusieurs choses.
Par exemple on peut embrouiller les gens en déclarant une constante "MONTH" qui aura (faussement) la valeur d'un mois.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 public static final int MONTH = 1000 * 60 *60 * 24 *30; ... date = new Date ( date.getTime() - 1 * MONTH );
Le problème avec cette approche, c'est qu'il devient trop facile de rechercher la constante "MONTH" pour savoir où on utilise la formule fautive.
Pour coder salement, il ne faut pas utiliser de constantes (ou le moins possible, et uniquement comme leurre...).
À la place, il faut disséminer les mêmes formules (ex : 1000 * 60 *60 * 24 *30) un peu partout dans le code, et si possible en les réécrivant de manière léggèrement différente à chaque fois, afin de compliquer la recherche textuelle.
Mais surtout, pour coder salement, il faut bien choisir son langage.
En effet, la même chose en C# c'est beaucoup trop simple :
Code : Sélectionner tout - Visualiser dans une fenêtre à part date.AddMonths( -1 );
Je suis d'accord, les effets de bords, c'est l'enfance de l'art !
"On en a vu poser les armes avant de se tirer une balle dans le pied..."
-- pydévelop
Derniers articles:
(SQL Server) Introduction à la gestion des droits
(UML) Souplesse et modularité grâce aux Design Patterns
(UML) Le Pattern Etat
Autres articles...
Le vrai problème, c'est que 1000 * 60 * 60 * 24 * 30, ça tient pas dans un int :p
Du coup, ça fait un nombre négatif. Du coup une date - un nombre négatif -> POUF on va dans le futur !
Tout le temps...
Tu voulais pas "reculer" d'un mois ? :p
Je te conseille la correction illisible suivante
date = new Date (date.getTime () - 1800*1440l*1000);
Le not est très pratique pour remplacer un cast int -> bool, ça peut servir à rendre son code plus court (et donc plus lisible)
Et ça compile quand même ?
Code c++ : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 int i = 42; float f0 = 10.f; if (i) { f0 += 2.3f; } float f1 = 10.f + !!i * 2.3f; // 1 ligne au lieu de 4 assert(f0 == f1);
Vu comme Java est chiant avec le respect des types (genre while(1) qui compile pas), c'est étonnant oO.
Oui, parce que de base, tu essayes de faire des opérations sur des valeurs qui ont le bon type. Le compilateur ne vérifie pas si l'opération en question ne va pas provoquer un débordement (parce qu'il y a des fois où il ne peut pas savoir, du genre si les valeurs sont des variables...).
Si tu essayes directement de lui affecter un nombre qui ne tiendra pas dans la variable, il te le dira : int i = 2592000000; par exemple, il te dira que tu es moche
D'où l'importance dans un code moche d'abuser de ce genre de choses histoire de bien masquer des problèmes potentiels !
"On en a vu poser les armes avant de se tirer une balle dans le pied..."
-- pydévelop
Derniers articles:
(SQL Server) Introduction à la gestion des droits
(UML) Souplesse et modularité grâce aux Design Patterns
(UML) Le Pattern Etat
Autres articles...
"Soit une date java placée sur le 15 du mois" No mais ho, c'est une chose de faire crade, ça veux pas dire qu'il faut ignorer la condition de départ, c'est pour ça qu'on se tappe d'une ou deux jours de décalage, ça reste dans le même mois
Et comme promis, une pépite de code sadique qui fait exactement son travail correctement mais va laisser le dev pantois
et son alternative qui compile pas tu sais pas pourquoi?
![]()
Mais il n'y a aucune différence entre
Code Java : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 long foo(); long l = foo() - 2592000000; // et long l2 = foo() - 60 * 60 * 24 * 30 * 1000;
"60 * 60 * 24 * 30 * 1000" est une constante de compilation, le calcul est fait durant la compilation et non durant l’exécution.
Enfin ça marche comme ça en C++, c'est différent en Java ?
Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 std::uint64_t foo(); std::uint64_t l = foo() - 1000 * 60 * 60 * 24 * 30; // warning C4307: '*' : dépassement de constante intégrale std::uint64_t l2 = foo() - 1000u * 60 * 60 * 24 * 30; // pas de problèmes, 2.592 milliards tient dans un unsigned
Essayez le code suivant pour vous en persuader !
Résultat aujourd'hui : Tue Jul 07 07:41:30 CEST 2015
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 public static void main(String[] args) { Date date = new Date(); date = new Date (date.getTime () - 1000 * 60 *60 * 24 *30); System.out.println(date); }
On est bien dans le futur !
Parce que l'opération de multiplication est faite en premier sur des ints (priorité de la multiplication sur la soustraction), dépassement de capacité du int --> int négatif, puis soustraction avec un long --> on est dans le futur !
Et non, en Java, les calculs, même s'ils peuvent être fait par le compilateur sont toujours fait à l'exécution. Effectivement, ils pourraient proposer une optimisation là-dessus en précompilant le résultat, mais ça irait à l'encontre du principe de rétrocompatiblité ascendante (ce qui est évité si possible dans les différentes évolutions) : du vieux code ne compilerait plus... Empêchant le vieux code crade de compiler... Ou pire, provoquant des erreurs parce que dans un programme précis, on VOULAIT un dépassement de capacité de l'integer...
@tchize_ donne mon ton outil, je dois le mettre en place dans les applications autour de moi, en urgence :p
Partager