J'aime bien ce genre de raccourci de code, souvent moins lisible, mais avec l'habitude...
Version imprimable
J'aime bien ce genre de raccourci de code, souvent moins lisible, mais avec l'habitude...
C'est un raccourci de codeur de C, qui mettent tout un programme dans un for. Je ne l'utiliserai jamais, c'est une façon de comprendre la grammaire très différente, et à priori je ne vois pas pourquoi j'en empêcherai les autres.
Sauf qu'à trop faire ce genre de variance, je vais tirer la gueule le jour où il faudra débugguer le programme d'un collègue. Et dans le cadre des projets open-source, merci la sère-mi !
Donc contre.
J'avoue que l'idée est bonne mais manque de clarté dans sa "syntaxisation".
Autant que je me souvienne en Pascal il y a une syntaxe (avec le mot clé "with") qui permettait d'aboutir à se genre de simplification :
Notez qu'il reste à savoir quelle serait la porté de thing.Code:
1
2
3
4
5
6
7
8
9
10
11 class Builder { void setSomething(Something x) { } void setOther(Other x) { } Thing result() { } } with new Builder(){ setSomething(something); setOther(other); Thing thing = result(); }
Venant de faire de la maintenance de code sur un projet Delphi/Pascal la possibilité offerte avec le with donne du code illisible et c'est la galère pour bosser dessus...
C'est illisible, ça fout le bordel et merci les mals de cranes...
Est ce qu'on finira comme en java script hihi
CONTRE !
Ctrl C ctrl V c'est pas long
Comprendre le code d'un autre ca l'est par contre.
Est ce qu'une méthode avec void ne renvoie pas true ou 1 quand son process a fonctionné ?
Contre.
Après l'expérience des StringBuilders, l'apport est anecdotique. Au contraire il est plus facile de relire la répétition d'une variable qu'un chaînage.
Au pire, pour les grosses feignasses avec de longs chaînages on peut toujours mettre un bloc d'accolade pour utiliser un alias court de la variable.
Je ne vois pas trop en quoi ca apporte quelque chose au langage Java ?
On peut deja le faire (regardons StringBuilder), c'est juste un détail d'implémentation.
Si le question est faut-il généraliser cet emploi, j'avouerais que je suis plutot pour, genre certaines classe du JDK pourront supporter ces invocations chainées. Mais il faut que ca reste à la discretion du développeur.
La, on parle de toutes les methodes qui retournent void retourneraient plutot this, et ca de facon systematique ? Je trouve que c'est un peu bizarre, ca touche finalement aux interfaces que le developpeur fournit. Si il ne controle plus ses types de retour ou s'il veut empecher le chainage, comment va-il faire ?
L’exemple donné me laisse penser que cela peut s’appliquer avec un type de retour puisqu’il est présenté :
Or result() retourne bien un objet (a moins que je sois passé à côté de quelque chose).Code:
1
2
3
4
5 Thing thing = new Builder() .setSomething(something) .setOther(other) .result();
C’est là le seul point que je trouve beaucoup moins clair, et qui me laisse dubitatif.
Je ne suis pas fan des chaînages. Comme on l'a si bien dit avant moi, on est perdu et on ne sait plus quel objet on manipule au final.
Et puis, regardez la méthode add(Object) de Collection. Elle renvoie un boolean qui peut être très utile. Si on encourage le chaînage, on va chercher à renvoyer this (ou un void interprété comme un this) et perdre cette information utile.
Je dis « Non ! ».
C'est une sorte de bonne règle de programmation utilisés par certains pour optimiser la syntaxe. Plutot que de faire renvoyer void à une méthode ("rien", donc c'est inutile), autant renvoyer this à la place.
Néanmoins je suis assez d'accord avec toi. Autant présenté comme ça ça pourrait peut-être être utile, autant on ne peut pas nier que c'est bizarre, et comme je n'ai jamais vu de truc semblable dans un autre langage je serais plus enclin de voter contre.
J'ai voté contre car à mon humble avis c'est plus un problème de design d'une API plutôt qu'une feature à ajouter au niveau du langage lui même.
Si on veut ce genre de comportement, il suffit de retourner this sur les setter.
J'ai voté contre.
Comme évoqué précédemment, ceci peut être réalisé (et est fait dans de nombreux apis existants) en retournant this.
Je crois aussi que ceci prête à confusion...
Bref, je deteste un peu le fait que quelque chose ne se comporte pas exactement de la façon qu'elle était censé faire .. Une méthode qui retourne void est censée être appelé dans une instruction, et puis c'est tout !
Exactement !
Contre,
Je ne trouve pas ça très élégant.
- pas d'apport significatif
- bonjour le debug pas à pas ... même en étalant sur plusieurs lignes, c'est très pénible
[QUOTE=bassim;2781310]En Pascal , si je me rappelle bien on fait comme ça:
en java ça serait:Code:
1
2
3
4
5
6 with monObjet do begin setSomething(); setChose(); traitemant(); end;
Quand je me suis mis à Java, c'est l'une des premières choses que j'ai regrettées par rapport à Pascal/delphi. Je suis pour à 100%.Code:
1
2
3
4
5 with monObjet { setSomething(); setChose(); traitement(getChose()); }
J'ai voté oui mais il faudra revoir la syntax. Car ca va etre un peu illisible.
Personnellement j'opte pour deux solution :
- 1 : un mot clee genrs last ou self ( un peu comme le this)
- 2 : prendre en compte l'indentation (comme en python)
Pas fondammentalement utile, c'est la simple implémentation du design pattern Builder, qui a ses vertues mais aussi ses faiblesses. D'autant plus que réaliser un builder, c'est simplement retourner this sur les méthodes de fabrication.
Autant le mot clé ou un truc du genre pour marquer la différence et ne pas casser des méchanismes existants me parait une idée valable, autant l'indentaion et une très mauvaise idée car:
- C'est contraire à un pricipe de base du java. Rajouter des fonctionatilés ne dois pas ce faire à l'encontre des bases du language.
- Je trouve ça vraiment limitant. Je tiens absolument à rester maitre de l'indentation de mes programmes
Après y avoir davantage réfléchis à cette proposition, je pense qu'une bonne solution serait d'introduire un nouvel opérateur('..' me parait adapté) qui fonctionerait comme l'opérateur '.' mais retourant l'objet sur lequel il opère plutôt que le résultat de la méthode. On aurait donc:
Code:
1
2
3
4 Thing thing = new Builder() ..setSomething(something) ..setOther(other) .result();
- On ne change ainsi rien du comportement naturel du type void et de l'opérateur '.'
- Syntaxe immédiatement identifiable, aucune ambiguité possible.
- Pas vraiment plus verbeux que la proposition, beaucoup moins qu'un with.
Contre. Il suffit d'écrire son builder autrement:
Code:
1
2
3
4
5
6
7
8
9
10class Builder { Builder setSomething(Something x) { ...; return this; } Builder setOther(Other x) { ...; return this; } Thing result() { ... } } Thing thing = new Builder() .setSomething(something) .setOther(other) .result();
Sauf que le plus souvent, on souhaiterait utiliser ça sur des objets qui appartiennent a l'API JAVA ou à une bibliothèque que l'on ne maitrise pas. En plus les setter sont sencés retourner le type void.
Bref à par quelques rares objets comme les StringBuilders, c'est actuellement impossible de faire du chainage.
Contre !
Avec un truc comme cela on aurait vraismeblablement des méthodes de type void qui renverait implicitement des objets this en retour (et typé comment ?).
On ne manquerait pas alors d'avoir des codeur qui tulise les retour de méthode de type void dans el but non avoué de décroché le gros lot des concours de code les plus abscons.
Je trouve cela tres dangeureux.
En outre, je suis trés trés contre les longues séquence de code sur une seules lignes qui, quand elle plante ne permettent jamais de savoir qu'elle est la méthode source du soucis.
J'ai fait un petit exemple
l'idée est de simplifier l'écriture de main...j'ai choisi comme syntaxe de prendreCode:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 class Foo { int value; Foo(int value){this.value=value;} void add(int x){value+=x;} void doubble(){value*=2;} void triple(){value*=3;} int tripleAndGet(){value*=3;return value;} int getValue(){return value;} } public static void main(String[] args) { Foo f1=new Foo(1); f1.doubble(); f1.triple(); Foo f2=new Foo(f1.getValue()); f1.doubble(); f1.tripleAndGet(); // on n'est pas obligé d'assigné le retour! f2.add(f1.getValue()); f2.double(); System.out.println("result:"+f2.getValue()); } }
les accolades et de dire que si l'on ouvre des accolades avant la fin d'un statement, on applique toutes les méthodes sur l'objet désigné avant la première accolade (il n'y a pas d'ambiguité, le constructeur est orthogonal et peu êtrre utilisé récursivement...)
plus concis mais pas vraiment plus clair (quel nombre imprime le proramme :DCode:
1
2
3
4
5
6
7
8
9
10
11
12
13 public static void main(String[] args) { Foo f1=new Foo(1){ .doubble(); .triple(); }; System.out.println("result:"+ new Foo(f1.getValue()) { .add(f1{.doubble; }.tripleAndGet()): .double(); }.getValue(); );
j'ai bien aimé:
-le with de ludosoft (comme {})
-les .. comme nouveau symbol
le with de ludosoft me manque aussi mais il est source d'ambiguite.
Après reflexion:
- 100% pour la syntaxe: je trouvais qu'il manquait un with dans Java, mais le chainage est bien plus moderne, plus lisible si on le présente bien (comme tout le reste d'ailleurs) et existe déjà dans Java (StringBuilder, etc.)
- 100% contre les méthodes qui retournent void, c'est nimporte quoi! Le 100% pour ci-dessus ne va que pour un type Toto dont les méthodes retournent une valeur de type Toto !
j'étais plutôt pour jusqu'à cet argument
Si on est seul à travailler sur son code, je ne vois aucun pb. C'est rarement le cas. Comme ça a été dit par la suite, bonjour l'ambiguïté.Citation:
Pour lire (et comprendre) un chainage de ce type en mixte (avec et sans void) il faudrait connaitre par cœur la déclaration de chacune des méthodes .. personnellement j'en suis incapable et même avec un IDE ça peut être pénible a voir.
oui je suis d'accord mais il ne faut pas voir non plus uniquement que ce qui est bien ;) il faut justement peser le pour et le contre.Citation:
En fait, comme dans d'autres proposition, il faut essayer (et c'est parfois dur pour moi aussi) de ne pas penser à ce que ça pourrait permettre de pire mais de bien peser le pour et le contre.
Pour un apport en lisibilité, je trouve qu'on peut beaucoup y perdre en temps de compréhension de code.
Bof moi je m'en serai remis. Venant du monde c++, le manque de template ou la liste variable de paramètres, jusqu'à l'arrivée de Tiger, m'a beaucoup plus gêné. C'est pas l'opérateur qui est le plus conseillé pour faire un if. Bien utilisé ça peut apporter mais ça reste très léger comme gain.Il est très souvent utilisé "pour montrer qu'on sait l'utiliser" plus que par nécessité. Cet opérateur n'est pas un plus dans les concepts du langage, n'apporte pas un plus au niveau de la façon de coder, .... le gain est vraiment léger. Donc si cette proposition est du même niveau que cet opérateur alors je suis 2x plus contre cette proposition et qu'ils investissent de leur temps dans d'autres propositions plus intéressantes.Citation:
Car sinon, on n'aurait jamais eu l'opérateur ternaire "? :" en Java !!!
Moi je suis plutôt contre les apports "esthétiques" si ils n'apportent pas un réel plus. Ou alors, les mettre tout en bas de la pile de priorité.
edit : éventuellement une différenciation comme pour le coup du ".." pour marquer la différence
Je trouve la proposition de départ vraiment pas claire. Avec le with myString {...} ou plus simplement myString{....}, on arrive à quelque chose de mieux.
Le problème de with, bah c'est pour les programmeurs qui ont utilisés with comme nom de variable. Pas cool pour eux !
Contre!
Comme tous les "opposant" je pense qu'avoir indiqué explicitement void en retour d'une methode doit continuer de vouloir dire "void" et pas un this implicite.
Si le besoins se fait sentir libre au développeur de modifier les méthodes pour qu'elles renvoient l'objet en cours.
En lisant tous ces post sur les "void",
Cela m'a fait pensé que la notion de signature de la méthode n'est pas claire.
Dans java, seuls les paramètres servent à oter les ambiguités en cas de surchage de nom de méthode. le paramètre de retour n'est pas utilisé.
Le paramètre de retour est utilité seulement si il est assigné ou recepteur d'une nouvelle méthode.
On peut toujours donc "jeter" le paramètre de retour.
dans le petit exemple suivant, pour utiliser les chainages dès maintenant, j'ai remplacer void par la classe elle même, et je retourne l'objet (this). Ce qui permet de chainer les appels et ca marche.
Son utilisationCode:
1
2
3
4
5
6
7
8 public class Foo { int value; Foo(int value){this.value=value;} Foo add(int oper1){value+=oper1; return this;} Foo mult(int oper1){value*=oper1; return this;} int getValue(){return value; }
Alors ?Code:
1
2
3
4
5
6
7
8
9
10
11
12
13 public static void main(String[] args) { Foo f1=(new Foo(1)) .add(3) .mult(4) .add(6); Foo f2=new Foo(f1.add(3) .add(4) .getValue()); f2.add(1) // on jette la valeur retournée !! .mult(4); System.out.println(f2.getValue()); }
Et quel est le gain ? C'est surtout ça qu'il faut voir..
- Est-ce que cela permet de faire quelque chose d'impossible auparavant ? Non, on ne chainait pas mais c'est juste du sucre syntaxique, juste une nouvelle manière d'écrire les appels aux méthodes.
- Est-ce que c'est plus lisible: Non si une méthode ne retourne pas void au milieu de l'enchainement on va appeler une méthode sur un autre objet en cours de route.
- Est-ce plus maintenable: Non en cas d'exception il y a je ne sais pas combien d'appels sur la même ligne, attention a ne pas se planter lors de l'analyse du chainage qui a provoqué l'exception.
- Est-ce plus rapide a écrire: oui on économise le nom de la variable, quelle fête..
- Est-ce que cet avantage vaut le coup d'introduire tout ces inconvénients sachant que ça ne permet rien de nouveau au final ?
Lorsque j'étais encore a la fac et qu'on nous farcissait la tête de conseils pour écrire du code propre, il y avait ce petit conseil parmi d'autre, genre aéré votre code, pas plus d'une instruction par ligne ... pour moi la il y a conflit avec la proposition.
Et aller a la ligne pour chaque chainage n'est pas beaucoup plus propre car il manquera une info sur la ligne, la variable, qu'il faudra aller chercher je ne sais pas combien de lignes plus haut..
Bien souvent on n'écrit le code qu'une fois mais on le relit plusieurs, je préfère perdre du temps une fois si ça m'en fait gagner plusieurs fois par la suite..
Bulbo ;)
Je suis plutot contre.
Dans le livre de Deitel comment porgrammer en Java j'ai vu que l'invcation de methodes chaines on la gere avec les set en renvoyant this.
class Builder {
Builder setSomething(Something x) { … return this;}
Builder setOther(Other x) { … return this;}
}
Builder builder = new Builder();
builder.setSomething(something).setOther(other);
On aurait comme ca une invocation des methodes chaines.
Le problème, c'est que ca marche plus aussi facilement lorsqu'on a une autre classe qui étend Builder et qui rajouterait juste une méthode, setSubMethod().
Et on ne pourrait pas alors écrire
Car setSomething et setOther sont définis comme retournant Builder.Code:
1
2 SubBuilder subbuilder = new SubBulder(); subbuilder.setSomething(something).setOther(other).setSubMethod(otherthing);
Avec la proposition suivante, on est sûr que la méthode retourne toujours bien l'objet courant. Et donc on peut vraiment écrire
builder.setSomething(something).setOther(other).setSubMethod(otherthing);
sans aucun problème.
Vincent
contre
des expressions dont la sémantique implicite serait
"[delete, close, … ](someObject).do_something_on_supposed_still_alive_object()"
seraient possibles…
(ou comment indiquer qu'une méthode "void" "invalide" un objet ou son contenu et implicitement retourne null plutôt que this…)
+ quelques craintes quant aux implications subtiles sur l'AOP…