et tu sors de la boucle en faisant un break ;Citation:
Envoyé par ®om
Note du modérateur : ces messages proviennent d'un autre message ( Thread, Arrête toi je le veux !) et ont été déplacé car ils étaient Hors-Sujet
Citation:
Envoyé par Kikito
Version imprimable
et tu sors de la boucle en faisant un break ;Citation:
Envoyé par ®om
Note du modérateur : ces messages proviennent d'un autre message ( Thread, Arrête toi je le veux !) et ont été déplacé car ils étaient Hors-Sujet
Citation:
Envoyé par Kikito
pfiou... C'est pas propre :)Citation:
Envoyé par schniouf
break est réservé aux switch :)
Non, pas du tout, break peut être utilisé partout où on a besoin de sortir prématurément d'une boucle (while, for), pas seulement les switchCitation:
Envoyé par ®om
Oui, java le supporte...Citation:
Envoyé par manblaizo
Après, ça n'est pas parce que ça marche que c'est correct...
(c'est une des premières choses qu'on apprend en cours de java, ne surtout pas utiliser break et continue, sauf break dans un switch)
C'est quoi ta méthode pour sortir d'un boucle (for ou while) alors ?Citation:
Envoyé par ®om
Bah, la condition d'arrêt :)Citation:
Envoyé par schniouf
donc si je comprend bien pour une boucle for de i=1 à i=10, tu fais i=11, et pour while tu t'arranges pour que la condition soit fausse.Citation:
Envoyé par ®om
C'est bien, mais dans ce cas là :
Instructions 2 est exécuté quand même. L'avantage du break c'est qu'on sort de la boucle tout de suite. Ou alors j'ai mal compris ta méthode :aie: .Code:
1
2
3
4
5
6
7 for( int i=0 ; i<=10 ; i++ ) { ... // Instructions 1 if( condition ) i = 11 ; ... // Instructions 2 }
Tu es sûr de ne pas confondre avec un autre langage ? Parce que ça, je l'ai jamais lu nulle part, même pas dans la spécification.Citation:
Envoyé par ®om
Si tu as besoin de faire ça, c'est que tu as mal conçu ton algorithme...Citation:
Envoyé par schniouf
En gros, si tu veux par exemple parcourir un tableau et t'arrêter quand tu trouves le résultat recherché, tu fais:
Si tu as des "//instructions 2" comme dans ton exemple (ce qui ne se présente que dans des cas particuliers - souvent tu peux réorganiser pour faire différemment-), il faut refaire un if(condition) { //instructions 2 } où condition est équivalente à la condition de ton while/for...Code:
1
2
3
4
5
6
7
8 int i = 0; boolean contains = false; while(i < tab.length && !contains) { if(tab[i].equals("tachaine")) { contains = true; } i++; }
ça n'est pas spécifique au Java, c'est les "bases" de l'algorithmique, que l'on doit appliquer en Java, en C, etc...Citation:
Envoyé par manblaizo
Mais tu sais que tous les mots clé n'ont pas toujours la même signification d'un langage à un autre, et justement en Java, break et continue permettent de sortir d'une boucle sans avoir à exécuter les instructions suivantes dans la boucle. C'est ce qui est fait aussi dans un switch, s'il n'y a pas de break, toutes les instructions "case" suivantes sont exécutées jusqu'au premier break rencontré. Donc en principe ce comportement n'est pas lié à l'algorithmique mais bien à l'implémentation propre de chaque langage de programmation.Citation:
Envoyé par ®om
Justement, en algorithmique, il est impossible d'exprimer un break/continue. Donc il ne "faut pas" les utiliser non plus dans les langages.Citation:
Envoyé par manblaizo
Sinon, break/continue, quelque soit le langage, à ma connaissance ça a le même sens...
Citation:
Envoyé par ®om
Ca marche très bien et je ne vois pas en quoi ce n'est pas propre. Après c'est vrai que j'ai appris à programmer de la manière dont tu le dis, mais bon. Le truc que je trouve vraiment dégueu c'est les goto :mouarf:Code:
1
2
3
4
5
6
7
8
9
10 public boolean contient() { int i = 0; while(i < tab.length) { if(tab[i].equals("tachaine")) return true; i++; } return false ; }
EDIT : on est en train de lui pourrir son post avec nos théories, vaudrait mieux arrêter ou bien ouvrir un nouveau post :lol:
Là ça va, c'est un return, c'est pas un break... C'est moins correct qu'en le mettant à la fin, mais c'est plus acceptable qu'un break...Citation:
Envoyé par schniouf
Voilà pourquoi... Un élément essentiel dans le développement de logiciels, c'est la maintenance. Et là, imagine tu dois modifier la méthode, pour traiter le résultat (plutôt que de le retourner), tu vas être obligé de modifier ta boucle (tu vas me dire, sur cet exemple, c'est pas coûteux), alors que si tu fais le return qu'à la fin, bah tu laisses ta boucle telle quelle...
Le problème du break/continue est aussi un problème de maintenance...
Imagine tu dois faire un traitement particulier...
Et en fait plus tard, tu veux rajouter une boucle "interne"...Code:
1
2
3
4
5
6 for(int i = 0; i < tab.length; i++) { if(isOK(tab[i], 5) { //isOK caractéristique quelconque dépendante de l'entier passé en paramètre, qui renvoie un booléen break; } }
Et bien tu es obligé de refaire totalement ta boucle, car le break s'applique maintenant sur la boucle en j...Code:
1
2
3
4
5
6
7
8 for(int i = 0; i < tab.length; i++) { for(int j = 0; j < tab2.length; j++) { if(isOK(tab[i], j) { //isOK caractéristique quelconque dépendante de l'entier passé en paramètre, qui renvoie un booléen break; } } }
Dans ce cas j'suis d'accord. Je m'incline :mrgreen:.
Je reviens à l'histoire du break/continue, même si on peut trouver ça moins propre, je leur trouve des utilités:
- sortir ou continuer la boucle sur un evenement bloquant sur lequel on ne veut pas lever d'exception, je ne trouve pas ça terrible de transformer ces boucles for dont le nombre d'itérations est voulu à une boucle while
- dans les boucles complexes où on gagne beaucoup en lisibilité et en maintenance ( que tu cites dans l'autre sens ), car avec tous les if else que ça peut rajouter ça devient vite illisible.
devient :Code:
1
2
3
4
5
6
7
8
9
10
11 for (int i=0;i<10;i++){ toto = fonction(tab[i]); if (toto < 5){ toto2 = fonction2(toto); if (toto2 == 0){ break; } fonction4(toto2); } fonction3(toto,toto2); }
La c'est encore relativement simple, mais avec des boucles plus complexes les break/continue font vraiment gagner en lisibilité Et en maintenance.Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 int i=0; boolean b = true; while (i<10 && b){ toto = fonction(tab[i]); if (toto < 5){ toto2 = fonction2(toto); if (toto2 == 0){ b = false; } else{ fonction4(toto2); } } if (b){ fonction3(toto,toto2); } i++; }
Qu'en penses les autres rédacteurs/modérateurs java ?
J'ajouterai :
1) Les break/continue sont utilisés de manière assez importante dans les sources java (et pas que pour les switch)
2) Pour rom le break casse les deux boucles dans ton exemple, et il est possible de mettre un label à tes itérations et c'est également pas mal utilisé dans les sources java ( ça je ne le fait pas mais c'est juste pour la petite histoire ) :
Voici readline de BufferedReader par exemple (et y en a beaucoup beaucoup d'autres) :
Code:
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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62 String readLine(boolean ignoreLF) throws IOException { StringBuffer s = null; int startChar; boolean omitLF = ignoreLF || skipLF; synchronized (lock) { ensureOpen(); bufferLoop: for (;;) { if (nextChar >= nChars) fill(); if (nextChar >= nChars) { /* EOF */ if (s != null && s.length() > 0) return s.toString(); else return null; } boolean eol = false; char c = 0; int i; /* Skip a leftover '\n', if necessary */ if (omitLF && (cb[nextChar] == '\n')) nextChar++; skipLF = false; omitLF = false; charLoop: for (i = nextChar; i < nChars; i++) { c = cb[i]; if ((c == '\n') || (c == '\r')) { eol = true; break charLoop; } } startChar = nextChar; nextChar = i; if (eol) { String str; if (s == null) { str = new String(cb, startChar, i - startChar); } else { s.append(cb, startChar, i - startChar); str = s.toString(); } nextChar++; if (c == '\r') { skipLF = true; } return str; } if (s == null) s = new StringBuffer(defaultExpectedLineLength); s.append(cb, startChar, i - startChar); } } }
Dommage que ce sujet n'intéresse personne, j'aurais bien aimé avoir l'avis d'un certain nombre de développeurs concernant l'utilisation des break/continue.
Moi je suis pour :mouarf: !!!Citation:
Envoyé par Kikito
Je ne sais pas quelles sources tu regardes... mais elles ne doivent pas être très propres...Citation:
Envoyé par Kikito
Point de vue personel :
Je pense que ce genre de méthode ( break, continue etc. ) n'est pas propre dans la mesure ou ça casse la logique d'un algorithme fait à la main, mais surtout sa lisibilité et sa compréhension.
Maintenant, toutes les entreprises recherchent les performances, et des fois ces instructions permettent de gagner en rapidité ( d'exécution ou d'écriture du code ). Alors dire que les sources java sont sales, je n'irais pas jusque là. Du moment ou l'utilisation du code compilé est à la fois sûr et performant, peut-importe la gueule du source.
Pour continuer la discussion,
1) Pourquoi ne pourrait-on pas incorporé des break dans un algo fait main ?
2) Pour la lisibilité et la compréhension, si tu prends mes 2 bouts de code en haut de cette seconde page, trouves-tu le second plus lisible que le 1er ?
3) Pour les 'throw' qui fonctionnent de la même manière, vous les sortez aussi des boucles avec des booléens pour ensuite lancer l'exception ?
Petite question bête : comment s'utilise le continue ?? Il n'apparaît dans aucun de vos exemples...
Sinon, personnellement, je n'ai rien contre les break. Je ne les utilise que très rarement, mais c'est simplement parce que je n'y pense pas. :mrgreen:
Mais du coup, il est vrai que je ne rends pas contre du coup de la maintenance de code contenant des break.
Tout à fait d'accord. Je dirais même qu'il m'est arrivé de me prendre la tête sur une condition d'arrêt dans une boucle rédigée de manière "conventionnelle" (sans penser à utiliser un break). Il me semble que parfois les break collent mieux à la conception "humaine" d'une boucle. Les conditons d'arrêt peuvent être définies DANS le corps de la boucle, plutôt que dans la définition même de la boucle.Citation:
Envoyé par Kikito
Je suis d'accord sur le fait qu'avec un algo bien conçu, les conditions d'arrêt des boucles ne devraient pas poser de problèmes lors de l'écriture du code. Dans la pratique, le break peut simplifier le travail...pourquoi s'en priver ?
De la même manière que les break sauf que cela passe à l'itération suivante au lieu de quitter définitivement la boucle.Citation:
Petite question bête : comment s'utilise le continue ?? Il n'apparaît dans aucun de vos exemples...
Code:
1
2
3
4
5
6
7 for (int i=0;i<tableau.length;i++){ //on ne gère que les éléments différents de 0. if (tableau[i] == 0){ continue; } traitement(tableau[i]); }
OK, merci. ;)Citation:
Envoyé par Kikito
Je ne connaissais pas...
Perso, je vois pas d'autres manieres pour gerer les boucles infinies.
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14 while(true) { Integer i = getNextInteger(); // ignore la valeur null if (i==null) continue; // sort si negatif if (i.intValue()<0) break; // traitement des entiers positifs ou nuls ... }
Bien que j'utilise moi même les breaks/continues tu pourrais faire un truc du genre :Citation:
Envoyé par pseudocode
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 boolean end = false; while(!end) { Integer i = getNextInteger(); // ignore la valeur null if (i != null){ // sort si negatif if (i.intValue()<0){ end = true; } else{ // traitement des entiers positifs ou nuls ... } } }
Heu, oui mais bon, heu.., pour avoir un peu plus de lisibilité dans le code je suis adepte des techniques suivantes:
- le retour au plus tot
- l'indentation minimum
alors bon je vais garder ma technique, si ca ne derange personne ;)
Je ne disais pas qu'il fallait faire comme la seconde solution, mais qu'on pouvait, car je suis d'accord avec toi, même si tout est biensûr important (il est important de connaitre les complexités des collections...) je privilégie également énormément la lisibilité/maintenance, car ce qui compte je pense dans les applis java pros c'est le travail d'équipe, la productivité et la maintenance beaucoup plus plus que le gain de performance de 2.4% ou les précepts old school disant que les instanceof, les return hors fin de fonction, les continue ou les breaks ne sont pas à utiliser.Citation:
Envoyé par pseudocode
Totalement d'accord. :chin:
Donc on peut conclure par:
Citation:
Utilisez les break et les continue si cela ameliore la lisibilité du code. Sinon, laissez tomber.
qui disait "appuyez vous sur vos principes!... ils finiront bien par céder!"?8-)
on peut toujours exhiber des utilisation algorithmiques vraiment pas propres de break .... mais on peut aussi en exhiber des correctes quand dans le corps de la boucle on calcule un résultat qui, pour un raison ou une autre, est inaccessible au test haut (ou au test bas dans le cas d'un do ...while()). On pourrait certes rajouter des tas de booléens invraisemblables mais là on rend le code hyper pas clair.
On peut avoir des codes tout à fait correct algorithmiquement avec des breaks (l'analyse physique du cheminement des branches du code est juste plus compliquée).... si on pousse trop loin nos besoins (légitimes) de pureté je signale que l'affectation est aussi considérée comme nuisible à la santé algorithmique :D
Supprimons les algos. Toutes les valeurs en dur, avec duplication du code et un gros switch/case. :mouarf:Citation:
Envoyé par professeur shadoko
tu rigoles : mais j'ai vu du code Java généré automatiquement à partir de "vieux" langages de gestion et c'était exactement ça! terrifiant!:aie: tu prends une usine à gaz et tu remplaces chaque tuyau par un switch!Citation:
Envoyé par pseudocode
En ce qui me concerne, les break et autres continue c'est vraiment en dernier recours.
La lisibilité, ce n'est pas une mesure absolue. Mais en ce qui me concerne, quand j'ai une boucle, le reflexe est réellement de voir où elle démarre ou elle s'arrête et comment on évolue dedans. Une fois que c'est fait, je suis alors dans la boucle et le fait que la boucle existe n'a plus aucune influence sur ma compréhension.
Quand on utilise des break et des continue (enfin surtout des break), on ne peut absolument pas réfléchir de la même manière, en considérant qu'on est simplement en train de traiter un cas et oublier la boucle environnante (et si on parle de boucles imbriquées c'est encore pire).
Donc d'accord avec le phrase "break et continue quand ça améliore la lisibilité" mais à mon sens ça n'arrive que rarement.
voyons avec un exemple (sans try/catch pour simplifier)Citation:
Envoyé par chtig
objet: réécrire ce code (pas très pertinent je le concède) sans break et sans variable interne à la boucle déclarée à l'extérieur de la boucle.Code:
1
2
3
4
5
6 for(int ix = 0; ix < tb.length; ix++) { int lu = System.in.read() ; if( (lu == -1) || (lu == '\n') || (lu == '\r')) { break ;} tb[ix] = lu ; }
C'est possible certes...
après du goût et des couleurs on peut discuter....
Bonjour
Je préfère ça :
Et je préfère encore ça (mais apparement tu ne le veux pas) :Code:
1
2
3
4
5
6
7
8 for(int ix = 0, int lu = System.in.read() ; ix < tb.length && !lectureTerminee(lu) ; ix++, lu = System.in.read()) { tb[ix] = lu ; } private static boolean lectureTerminee(int lu) { return (lu == -1) || (lu == '\n') || (lu == '\r'); }
J'aurai même préféré un while en fait.Code:
1
2
3
4
5
6
7
8
9
10 int lu = System.in.read(); for(int ix = 0; ix < tb.length && !lectureTerminee(lu) ; ix++) { tb[ix] = lu ; lu = System.in.read(); } private static boolean lectureTermine(int lu) { return (lu == -1) || (lu == '\n') || (lu == '\r'); }
Code:
1
2
3
4
5
6
7
8
9
10
11
12 int indiceCourant = 0; int lu = System.in.read(); while (!lectureTerminee(lu) && indiceCourant < tb.length) { tb[indiceCourant] = lu; indiceCourant++; lu = System.in.read; } private static boolean lectureTerminee(int lu) { return (lu == -1) || (lu == '\n') || (lu == '\r'); }
J'ai du mal avec ta notion de "variable interne à la boucle" ....
En quoi tu considères que ta variable lu ne peut pas être déclarée à l'extérieur ?
Effectivement, la lisibilité c'est très subjectif. Si ça se compte en nombre de lignes et nombre d'indentations, que penses tu de ça ? :
Code:
1
2
3 for (int ix=0;ix < tb.length && (int lu=System.in.read())!=-1 && lu!='\n' && lu!='\r'; ix++) tb[ix] = lu ;
Ce qui est moins "subjectif" ce sont les metriques, comme par exemple la "cyclomatic complexity Number (CCN)" de McCabe:Citation:
Envoyé par chtig
Citation:
CCN is also know as McCabe Metric. There exists a much hyped theory behind it based on graph theory, but it all comes down to simply counting 'if', 'for', 'while' statements etc. in a method. Whenever the control flow of a method splits, the "CCN counter" gets incremented by one.
Each method has a minimum value of 1 per default.
For each of the following keywords/statements this value gets incremented by one:
- if
- for
- while
- case
- catch
- &&
- ||
- ?
Note that else, default, and finally don't increment the CCN value any further. On the other hand, a simple method with a switch statement and a huge block of case statements can have a surprisingly high CCN value (still it has the same value when converting a switch block to an equivalent sequence of if statements).
Oui effectivement il existe des métriques, mais comme le signale l'auteur lui même, elles ont de très nettes limitations, et il est rare de pouvoir réellement en tirer une appréciation réelle de la lisibilité du code.
C'est clair. a chacun de definir ce qu'il appelle "lisibilité".
Exemple avec le celebre STRCOPY
Code:
1
2
3
4
5
6
7
8 strcpy(char s1[],char s2[]) { int x,len; len=strlen(s2); for (x=0; x<=len; x++) s1[x]=s2[x]; }
Code:
1
2
3
4
5
6
7
8
9
10 strcpy(char *s1,char *s2) { while (*s2 != '\0') { *s1 = *s2; s1++; s2++; } }
Code:
1
2
3
4
5
6 strcpy(char *s1,char *s2) { while (*s2) *s1++ = *s2++; }
Code:
1
2
3
4
5 strcpy(char *s1,char *s2) { while (*s1++ = *s2++); }