Inférence d'un prédicat

58 views
Skip to first unread message

Henri Tremblay

unread,
Feb 11, 2015, 10:45:14 AM2/11/15
to lescast...@googlegroups.com
Je me pose une question existentielle et je me dis que quelqu'un doit avoir la réponse par ici.

(Remi? José?)

Si j'ai 

Predicate<? super String> lambda = -> t.isEmpty();


Comment le compilateur décrète que le t est une String. Il prend juste le meilleur type car rien ne l'empêche?

Merci
Henri

Remi Forax

unread,
Feb 11, 2015, 11:05:25 AM2/11/15
to lescast...@googlegroups.com
C'est quasiment ça, il prend String car c'est ce que dit la spec :)

L'inférence marche uniquement en regardant le type du prédicat et pas en regardant le contenu de la lambda
(donc l'inférence de t -> foobar() marche de la même façon que l'inférence de t -> t.isEmpty()).
Donc le type de t doit être un type compatible avec ? super String, lorsque qu'il y a plusieurs types possibles,
le mécanisme d'inférence prend toujours le type le plus précis, donc ici le type de t est entre [Object, ..., String],
donc String étant le plus précis, c'est String qui est choisi.

voilà, tu avais trouvé tous seul.

maintenant, j'en profite pour te dire qu'il y a une grande règle pour les '? extends' et '? super',
sauf cas particulier, tu ne devrais jamais écrire des '? super' ou des '? extends' dans le code utilisateur
(et en tant que type de retour) mais uniquement en tant que type de paramètres de méthodes,

donc le code suivant est ok
  void foo(Predicate<? super String> predicate) {
     ...
  }

mais
  Predicate<? super String> predicate = ...
ne l'est pas car la plupart du temps tu sais le type exacte donc il vaut mieux écrire
  Predicate<String> predicate = t -> t.isEmpty()
et pour le cas précis, tu peux même écrire
  Predicate<String> predicate = String::isEmpty;

bref, les ? extends/? super c'est pour faire du sous-typage donc c'est lorsque tu veux que ton code puisse être appelé avec différents Predicate, si tu veux un Predicate particulier, tu n'as pas besoin de la notation '? super'.



Merci
Henri


Rémi
Attention: l'usage abusif des '? super' peut bruler les yeux.

Henri Tremblay

unread,
Feb 11, 2015, 11:44:52 AM2/11/15
to lescast...@googlegroups.com
:-)

Ok. C'était logique et j'avoue que je ne voulais pas me tapper toute la spéc juste pour trouver la règle. Donc merci beaucoup de confirmer mon intuition.

Et oui, je sais que pour chaque "?" en valeur de retour, un bébé phoque meurt (on a d'ailleurs des chasseurs canadiens engagé par Oracle pour ça). Là c'était pour l'exemple.

D'ailleurs, ça me fait penser. J'ai eu un autre problème la semaine dernière. Avec la méchante API de Mockito ;-)

ArgumentCaptor<List<String>> captor = ArgumentCaptor.forClass(List.class); // ne compile pas évidemment

Normalement, la solution c'est de ne pas avoir de paramètre à forClass. Comme ça il infère et tu as la paix. Mais dans le cas présent, ils s'en servent du paramètre. La seule solution pour compiler semble être

ArgumentCaptor<List<String>> captor = (ArgumentCaptor<List<String>>) (ArgumentCaptor) ArgumentCaptor.forClass(List.class); 

C'est hideux.

Ma solution préférée serait d'avoir une méthode
public <T> Class<T> cast(Class<?> clazz) {
return (Class<T>) clazz;
}
Dans le JDK. Mais je l'ai pas trouvé (Class.cast est pas loin, mais c'est pas ça...)

Pour avoir:

ArgumentCaptor<List<String>> captor = ArgumentCaptor.forClass(cast(List.class)); 

Sinon, on peut aussi changer l'API avec un truc comme
public static <T> ArgumentCaptor<T> forClass(Class<? super T> clazz) {
return new ArgumentCaptor<T>(clazz);
}
Mais c'est honteux parce que maintenant un peu tout passe. Par exemple ça
ArgumentCaptor<String> argumentCaptor = ArgumentCaptor.forClass(Object.class);
 Quel serait ta solution?


--
Vous recevez ce message, car vous êtes abonné au groupe Google Groupes "lescastcodeurs".
Pour vous désabonner de ce groupe et ne plus recevoir d'e-mails le concernant, envoyez un e-mail à l'adresse lescastcodeur...@googlegroups.com.
Pour envoyer un message à ce groupe, envoyez un e-mail à l'adresse lescast...@googlegroups.com.
Visitez ce groupe à l'adresse http://groups.google.com/group/lescastcodeurs.
Pour obtenir davantage d'options, consultez la page https://groups.google.com/d/optout.

Nicolas Labrot

unread,
Feb 12, 2015, 4:06:08 AM2/12/15
to lescast...@googlegroups.com
Comme l'objectif semble être de vouloir autant avoir une inférence sur le type du retour que exploiter le type du type du generic, je ne connais que cette facon qui consisterait à passer par un mécanisme de sub class permettant d'accéder au généric @ runtime:

Par exemple:
ArgumentCaptor<List<String>> captor = ArgumentCaptor.forClass(new TypeReference<List<String>>(){});

Facon de faire tirée de jackson.



--
LilActu.fr Agrégateur de News
http://lilactu.fr

Remi Forax

unread,
Feb 12, 2015, 6:13:48 AM2/12/15
to lescast...@googlegroups.com

On 02/12/2015 10:06 AM, Nicolas Labrot wrote:
Comme l'objectif semble être de vouloir autant avoir une inférence sur le type du retour que exploiter le type du type du generic, je ne connais que cette facon qui consisterait à passer par un mécanisme de sub class permettant d'accéder au généric @ runtime:

Par exemple:
ArgumentCaptor<List<String>> captor = ArgumentCaptor.forClass(new TypeReference<List<String>>(){});

Facon de faire tirée de jackson.

Le problème est la non-reification des generics en Java.
Un object Class représente une classe Java à l'exécution, donc la classe d'une ArrayList de String
est Class<ArrayList> même si le type est ArrayList<String>
(il y a un bug dans la spec, cela devrait être Class<ArrayList<?>> mais bon c'est trop tard).
donc utiliser un object Class pour représenter un type en Java est peine perdue.

Donc effectivement, Mockito devrait avoir une autre méthode que forClass, un forType qui
prend en paramètre un type Java.
La façon la plus simple d'avoir un type en Java consiste à aller par reflection chercher le type
d'un truc (genre membres, classes, etc). En effet, le compilateur est obligé de garder les
types (les type arguments pour les generics et tout et tout) pour la compilation séparée. 

Un des problème de l'API de Jackson est qu'elle utilise un bug (qui est devenu une feature),
le new TypeReference<...>(){} est une classe anonyme donc il est possible de sniffer le type
qu'implante la classe anonyme. Le problème est qu'une classe anonyme par définition
c'est anonyme donc le compilo devrait pas générer d'information de type car la classe ne
peut pas être référencée dans une autre unité de compilation.

Pour la petite histoire, Eclipse ne générait pas cette info, ce qui est logique et le code du compilo
d'Eclipse a du être changé pour implanter cette 'feature' pour être compatible avec le bug de javac.

Rémi

Sebastien Bordes

unread,
Feb 12, 2015, 11:13:09 AM2/12/15
to lescast...@googlegroups.com
Pour une fois qu'un bug est utile !!!, il me semble que c'est aussi utilisé par Google Guice TypeLiteral et certainement par d'autres librairies (moi le premier) car c'est très pratique pour définir des contrats du style
WaveItemBase<List<JRebirthEvent>> EVENTS = new WaveItemBase<List<JRebirthEvent>>() {};
Ce qui permet de dire explicitement qu'on veut une liste d'event, pas de patates (et de stocker l'info quelque part).

Concernant les generics il y a de quoi se faire de sérieux nœuds au cerveau, un truc que j'ai jamais compris c'est pourquoi on ne peut pas réutiliser le type generic de la definition de la classe dans certaines méthodes utilisant le même type generic.

public interface Facade<R extends FacadeReady<R>> {
    R void register(final UniqueKey<R> uniqueKey, final R readyObject);
}
==> ne compile pas !
alors que
public interface Facade<R extends FacadeReady<R>> {
    <E extends R> void register(final UniqueKey<E> uniqueKey, final E readyObject);
}
==> compile bien mais c'est bien moche

Remi Forax

unread,
Feb 12, 2015, 1:21:05 PM2/12/15
to lescast...@googlegroups.com

On 02/12/2015 05:13 PM, Sebastien Bordes wrote:
Pour une fois qu'un bug est utile !!!, il me semble que c'est aussi utilisé par Google Guice TypeLiteral et certainement par d'autres librairies (moi le premier) car c'est très pratique pour définir des contrats du style
WaveItemBase<List<JRebirthEvent>> EVENTS = new WaveItemBase<List<JRebirthEvent>>() {};
Ce qui permet de dire explicitement qu'on veut une liste d'event, pas de patates (et de stocker l'info quelque part).

Concernant les generics il y a de quoi se faire de sérieux nœuds au cerveau, un truc que j'ai jamais compris c'est pourquoi on ne peut pas réutiliser le type generic de la definition de la classe dans certaines méthodes utilisant le même type generic.

public interface Facade<R extends FacadeReady<R>> {
    R void register(final UniqueKey<R> uniqueKey, final R readyObject);
}
==> ne compile pas !

normal, ton type de retour c'est R ou void, il faut choisir


alors que
public interface Facade<R extends FacadeReady<R>> {
    <E extends R> void register(final UniqueKey<E> uniqueKey, final E readyObject);
}
==> compile bien mais c'est bien moche

la seconde déclaration est équivalente à


public interface Facade<R extends FacadeReady<R>> {
    void register(UniqueKey<? extends E> uniqueKey, E readyObject);
}

et arrête de mettre des final sur les variables locales,
tu prends ton IDE préféré et tu le configure pour gueuler si tu assignes un paramètre,
  Preference > Compiler > Error & Warnings >  Code Style > Parameter Assignment (sous Eclipse)
et comme ça ton code reste lisible et ça plante tout autant si tu touches à un paramètre.

Historiquement, Java n'avait pas de mot-clé final sur les paramètres (et variables locales)
James Gosling voulait pas que le final de Java soit l'équivament du const en C++.
Lors de l'introduction des classes anonymes, d'autres personnes dont je ne citerais pas le nom
mais un est maintenant chef de la VM chez Oracle et l'autre designer en chef de Dart chez Google
ont craqué et ajouté final lorsque l'on veut capturer la valeur d'une variable locale dans une
classe anonyme. En Java 8, magiquement, cette contrainte a disparu, donc fait moi plaisir
arrête de mettre des 'final' sur les variables locales par contre ajoute un truc qui check ce genre
de rêgles en commit-hook de ton outil de gestion de source préféré.
Comme cela tu auras un code propre, lisible et forax compliant.

ah, et non, final sur les variables locales ne dit pas à la VM d'optimiser quoi ce soit,
car javac vire les finals sur les variables locales avant la génération de code.

Rémi.

Remi Forax

unread,
Feb 12, 2015, 1:39:37 PM2/12/15
to lescast...@googlegroups.com

On 02/12/2015 07:20 PM, Remi Forax wrote:

On 02/12/2015 05:13 PM, Sebastien Bordes wrote:
Pour une fois qu'un bug est utile !!!, il me semble que c'est aussi utilisé par Google Guice TypeLiteral et certainement par d'autres librairies (moi le premier) car c'est très pratique pour définir des contrats du style
WaveItemBase<List<JRebirthEvent>> EVENTS = new WaveItemBase<List<JRebirthEvent>>() {};
Ce qui permet de dire explicitement qu'on veut une liste d'event, pas de patates (et de stocker l'info quelque part).

Concernant les generics il y a de quoi se faire de sérieux nœuds au cerveau, un truc que j'ai jamais compris c'est pourquoi on ne peut pas réutiliser le type generic de la definition de la classe dans certaines méthodes utilisant le même type generic.

public interface Facade<R extends FacadeReady<R>> {
    R void register(final UniqueKey<R> uniqueKey, final R readyObject);
}
==> ne compile pas !

normal, ton type de retour c'est R ou void, il faut choisir

alors que
public interface Facade<R extends FacadeReady<R>> {
    <E extends R> void register(final UniqueKey<E> uniqueKey, final E readyObject);
}
==> compile bien mais c'est bien moche

la seconde déclaration est équivalente à

public interface Facade<R extends FacadeReady<R>> {
    void register(UniqueKey<? extends E> uniqueKey, E readyObject);
}

voir même avec les yeux en face des trous:

public interface Facade<R extends FacadeReady<R>> {
    void register(UniqueKey<? extends R> uniqueKey, R readyObject);
}

:)

yan bonnel

unread,
Feb 12, 2015, 1:48:55 PM2/12/15
to lescast...@googlegroups.com

Petite question, en quoi est ce vraiment mal de réutiliser un paramètre en tant que variable local? (Assigner une valeur à un paramètre)

++
Yan

Remi Forax

unread,
Feb 12, 2015, 2:01:17 PM2/12/15
to lescast...@googlegroups.com

On 02/12/2015 07:48 PM, yan bonnel wrote:

Petite question, en quoi est ce vraiment mal de réutiliser un paramètre en tant que variable local? (Assigner une valeur à un paramètre)

++
Yan


Juste quand tu debug, tu as tendance à savoir avec quelle valeur ta méthode est appelée et
tu oublies que la valeur a changé depuis.

C'est pas un gros problème mais tu peux facilement passer 1/2 heure à chercher pourquoi.

Le problème ressemble à la vaccination, si tous le monde commence à se vacciner,
quand une personne n'est pas vacciné, souvent la maladie est mal diagnostiqué par les medecins
car pas les symptones ne sont pas reconnu, pareil quand tu a l'habitude de ne jamais assigné
un paramètre, tu ne cherchera jamais cela comme cause de bug.

Rémi

Sebastien Bordes

unread,
Feb 12, 2015, 2:10:50 PM2/12/15
to lescast...@googlegroups.com
Alors moi aussi je me suis trompé dans l'explication et le bout de code :(

Le code qui pose problème est bien sur :

public interface Facade<R extends FacadeReady<R>> {
    void register(final UniqueKey<R> uniqueKey, final R readyObject);
}

(sans le R en trop)

Le problème n'est pas qu'il ne compile pas, c'est plutôt lors de l'appel de cette méthode depuis une classe avec une méthode qui prend un type Generique Model extends FacadeReady

par exemple:

public final <M extends Model> M register(final UniqueKey<M> modelKey, M model) {
     getUiFacade().register(modelKey, model);
}
==> et bien dans ce cas la ça ne compile plus avec la deuxième version de la méthode ! Pourtant Model est bien un FacadeReady !, idem à d'autres endroits dans le code en utilisant des Class<M>.

Donc la méthode la plus simple pour éviter de rajouter des cast tout moche partout a été de ruser avec <E extends R>

Bref je ne trouve pas que ce je voulais faire était fondamentalement faux mais ce n'est visiblement pas supporté... (le code est sur github si quelqu'un veut relever le défi...)


Concernant les final sur les paramètres, je suis innocent votre honneur ce n'est pas moi c'est le SaveAction de mon IDE, il fait automatiquement un cleanup de mon code...
Pour la lisibilité on s'y habitue et on évite aussi de mettre trop de paramètres sinon le Qube gueule aussi.
Je vais tester cette fonctionnalité car je ne la connaissais pas, mais vaut-il mieux ne pas dépendre d'une feature de l'IDE ?
De toute manière le code exécuté est le même donc le débat sur les final ca devient: lisibilité vs fonction IDE


--
Vous recevez ce message, car vous êtes abonné à un sujet dans le groupe Google Groupes "lescastcodeurs".
Pour vous désabonner de ce sujet, visitez le site https://groups.google.com/d/topic/lescastcodeurs/NJb9WO2EdI8/unsubscribe.
Pour vous désabonner de ce groupe et de tous ses sujets, envoyez un e-mail à l'adresse lescastcodeur...@googlegroups.com.

Pour envoyer un message à ce groupe, envoyez un e-mail à l'adresse lescast...@googlegroups.com.
Visitez ce groupe à l'adresse http://groups.google.com/group/lescastcodeurs.
Pour obtenir davantage d'options, consultez la page https://groups.google.com/d/optout.

Nicolas Labrot

unread,
Feb 13, 2015, 9:11:46 AM2/13/15
to lescast...@googlegroups.com
merci pour ces infos!

Nicolas Labrot

unread,
Feb 13, 2015, 9:17:40 AM2/13/15
to lescast...@googlegroups.com
2015-02-12 20:10 GMT+01:00 Sebastien Bordes <sebastie...@gmail.com>:
Alors moi aussi je me suis trompé dans l'explication et le bout de code :(

Le code qui pose problème est bien sur :

public interface Facade<R extends FacadeReady<R>> {
    void register(final UniqueKey<R> uniqueKey, final R readyObject);
}

(sans le R en trop)

Le problème n'est pas qu'il ne compile pas, c'est plutôt lors de l'appel de cette méthode depuis une classe avec une méthode qui prend un type Generique Model extends FacadeReady

par exemple:

public final <M extends Model> M register(final UniqueKey<M> modelKey, M model) {
     getUiFacade().register(modelKey, model);
}
==> et bien dans ce cas la ça ne compile plus avec la deuxième version de la méthode ! Pourtant Model est bien un FacadeReady !, idem à d'autres endroits dans le code en utilisant des Class<M>.

Donc la méthode la plus simple pour éviter de rajouter des cast tout moche partout a été de ruser avec <E extends R>

Bref je ne trouve pas que ce je voulais faire était fondamentalement faux mais ce n'est visiblement pas supporté... (le code est sur github si quelqu'un veut relever le défi...)


Concernant les final sur les paramètres, je suis innocent votre honneur ce n'est pas moi c'est le SaveAction de mon IDE, il fait automatiquement un cleanup de mon code...
Pour la lisibilité on s'y habitue et on évite aussi de mettre trop de paramètres sinon le Qube gueule aussi.
Je vais tester cette fonctionnalité car je ne la connaissais pas, mais vaut-il mieux ne pas dépendre d'une feature de l'IDE ?
De toute manière le code exécuté est le même donc le débat sur les final ca devient: lisibilité vs fonction IDE


Je mets les final dans le même sac que la programmation systématique par interface. La raison vient d'un autre age, maintenant oublié, mais qui perdure. Une sorte d'atavisme du développeur ;)
 

Emmanuel Lécharny

unread,
Feb 13, 2015, 9:25:03 AM2/13/15
to lescast...@googlegroups.com
Le 12/02/15 19:20, Remi Forax a écrit :
>
>
> ...et arrête de mettre des final sur les variables locales,
Putain, depuis le temps que ça me gonfle ces 'final' partout !!! Ils
nous prennent vraiment pour des const...

Merci Rémi !

Sebastien Bordes

unread,
Feb 13, 2015, 9:28:07 AM2/13/15
to lescast...@googlegroups.com
Dans le cas présent les interfaces sont utilisés comme des points d'extension modifiable au runtime voire à chaud (en fonction du contenu des libs).
C'est très utilise pour customiser des applications, comme par exemple pour faire du branding...
Pour les final, c'est plus facile que de fournir les fichier de config pour tous les IDE du marché.... ou de forcer l'utilisation de checker spécifique

Ce qui est marrant c'est de voir que les mêmes sujets lancent systématiquement les mêmes discussions sans fin.

--
Vous recevez ce message car vous êtes abonné à un sujet dans le groupe Google Groupes "lescastcodeurs".
Pour vous désabonner de ce sujet, visitez le site https://groups.google.com/d/topic/lescastcodeurs/NJb9WO2EdI8/unsubscribe.
Pour vous désabonner de ce groupe et de tous ses sujets, envoyez un e-mail à l'adresse lescastcodeur...@googlegroups.com.
Pour envoyer un message à ce groupe, adressez un e-mail à lescast...@googlegroups.com.

Visitez ce groupe à l'adresse http://groups.google.com/group/lescastcodeurs .
Pour plus d'options, visitez le site https://groups.google.com/d/optout .

Henri Tremblay

unread,
Feb 13, 2015, 9:44:18 AM2/13/15
to lescast...@googlegroups.com
Disons que le débat est assez simple:

Final: Sert à rien et nuit à la lisibilité: Out (Early optimisation is the root of all evil)
Interface: S'il n'y a qu'une seule implémentation: Out. Si tu as besoin de plusieurs implémentations -> Extract interface et tu ajoutes ta nouvelle implémentation (Early overdesign is the root of all evil)

:-)

--
Vous recevez ce message, car vous êtes abonné au groupe Google Groupes "lescastcodeurs".
Pour vous désabonner de ce groupe et ne plus recevoir d'e-mails le concernant, envoyez un e-mail à l'adresse lescastcodeur...@googlegroups.com.

Sebastien Bordes

unread,
Feb 13, 2015, 9:56:15 AM2/13/15
to lescast...@googlegroups.com
Pour les final ce n'est pas utilisé pour optimiser, juste pour éviter de faire des re-assignations de variable qui vont plus nuire à la lisibilité que les pauvre final dans la signature de la méthode. C'est un question d'habitude, le paramétrage de l'IDE que Rémi a mentionné est une bonne idée encore faut-il que tous les dev l'aient configurés

Pour les interfaces dans le cas présent ce n'est pas du overdesign c'est une feature de la librairie, moi aussi je suis contre des interfaces qui n'ont qu'une implémentation surtout pour un modèle métier (vous n'avez qu'à aller voir EMF, vous allez nous faire une crise d'apoplexie)

Vous recevez ce message, car vous êtes abonné à un sujet dans le groupe Google Groupes "lescastcodeurs".

Pour vous désabonner de ce sujet, visitez le site https://groups.google.com/d/topic/lescastcodeurs/NJb9WO2EdI8/unsubscribe.
Pour vous désabonner de ce groupe et de tous ses sujets, envoyez un e-mail à l'adresse lescastcodeur...@googlegroups.com.
Pour envoyer un message à ce groupe, envoyez un e-mail à l'adresse lescast...@googlegroups.com.

Visitez ce groupe à l'adresse http://groups.google.com/group/lescastcodeurs.
Pour obtenir davantage d'options, consultez la page https://groups.google.com/d/optout.

Manu

unread,
Feb 13, 2015, 10:02:19 AM2/13/15
to lescast...@googlegroups.com
Les interfaces, ça permet aussi de faire de l'AOP avec de simples Jdk dynamic proxy, non ?
Sinon ca veut dire weaving au chargement des classes ...

Cédric Champeau

unread,
Feb 13, 2015, 10:05:39 AM2/13/15
to lescast...@googlegroups.com
Je suis assez d'accord sur l'utilisation de final en variable locale que j'utilise de temps en temps pour m'assurer que personne ne fera de bêtise avec ma variable. En fait en Java c'est assez moche parce que tu vas devoir écrire:

final int x = blah();

alors que le type pourrait être inféré. L'idée n'est pas d'optimiser mais de s'assurer qu'on ne réaffecte pas une variable dans un algo. Je suis d'ailleurs en train d'implémenter l'inférence de variables finales en Groovy et tu pourras écrire:

final x = blah()

Et le compilo infère automatiquement le type de x, et s'assure qu'elle n'est pas réaffectée. Si tu écris simplement:

def x = blah()

ou

int x = blah()

Le compilo va aussi inférer que la variable est finale ou non, et s'en servira potentiellement plus tard pour optimiser (éviter du wrapping de variables dans les closures, mais c'est spécifique à Groovy).
-- 
Cédric Champeau
Groovy language developer
http://twitter.com/CedricChampeau
http://melix.github.io/blog

Emmanuel Lécharny

unread,
Feb 13, 2015, 10:13:35 AM2/13/15
to lescast...@googlegroups.com
Le 13/02/15 16:05, Cédric Champeau a écrit :
> Je suis assez d'accord sur l'utilisation de final en variable locale
> que j'utilise de temps en temps pour m'assurer que personne ne fera de
> bêtise avec ma variable.

Sauf que *personne* ne va modifier ta varibale, sauf à modifier le code
de ta méthode. Et celui qui modifie ta méthode est assez grand pour ne
pas faire n'importe quoi, sauf à se faire rattraper par un bon code
review. Et comme tes méthodes ne font pas 50 lignes - j'espère -, je
vois vraiment pas l'intérêt de foutre du final partout.

Ceinture, bretelle, velcro et épingle à nourrice, quand vous nous tenez...

Damien B

unread,
Feb 13, 2015, 10:17:41 AM2/13/15
to lescast...@googlegroups.com
Le 13/02/2015 16:13, Emmanuel Lécharny a écrit :
> Le 13/02/15 16:05, Cédric Champeau a écrit :
>> Je suis assez d'accord sur l'utilisation de final en variable locale
>> que j'utilise de temps en temps pour m'assurer que personne ne fera de
>> bêtise avec ma variable.
> Sauf que *personne* ne va modifier ta varibale, sauf à modifier le code
> de ta méthode. Et celui qui modifie ta méthode est assez grand pour ne
> pas faire n'importe quoi, sauf à se faire rattraper par un bon code
> review.

Les code review c'est bien, mais si tu mets le final c'est un problème
de moins à regarder :-)
Et puis un beau bloc de "final type nom" en début de méthode, c'est tout
de suite visible, donc lisible. Dans les habitudes répandues qui rendent
le code Java illisible, je ne suis pas sûr que ce soit les final sur les
variables locales qui soient le pire honnêtement :)

Damien B

Henri Tremblay

unread,
Feb 13, 2015, 10:27:52 AM2/13/15
to lescast...@googlegroups.com
Non, il n'y a pas de weaving. C'est un proxy avec cglib souvent. C'est pareil (et ça devrait être inclue dans le JDK d'ailleurs...)

Emmanuel Lécharny

unread,
Feb 13, 2015, 10:28:29 AM2/13/15
to lescast...@googlegroups.com
Le 13/02/15 16:17, Damien B a écrit :
Mais comme ça sert à rien, et qu'il n'y a aucune justification réelle à
l'utilisation de final dans ce cas là, pourquoi en fourrer partout ?
Parce que "tu peux" ? Parce que que comme ça tes règles checkstyle
passent avec zéro warnings et que ça donne la trique à ton manageur ou à
ton ingénieur qualité qui n'a plus codé depuis 1987 ?

Comme le dit si bien Rémi, final != const, alors arrêtez de l'utiliser
comme si c'était pareil !

/me se demande qui va atteindre le point goodwin sur 'final'... (grosse
perche)

Jeff MAURY

unread,
Feb 13, 2015, 10:51:41 AM2/13/15
to lescastcodeurs
Pour moi le débat vient surtout du débat valeur/référence. Et pour moi, final n'a rien à voir avec const donc ca ne me gène pas + que ca

A+
Jeff


--
Vous recevez ce message, car vous êtes abonné au groupe Google Groupes lescastcodeurs.
Pour vous désabonner de ce groupe et ne plus recevoir d'e-mails le concernant, envoyez un e-mail à l'adresse lescastcodeur...@googlegroups.com.
Pour envoyer un message à ce groupe, adressez un e-mail à lescast...@googlegroups.com.
Visitez ce groupe à l'adresse http://groups.google.com/group/lescastcodeurs .
Pour plus d'options, visitez le site https://groups.google.com/d/optout .



--
Jeff MAURY


"Legacy code" often differs from its suggested alternative by actually working and scaling.
 - Bjarne Stroustrup

http://www.jeffmaury.com
http://riadiscuss.jeffmaury.com
http://www.twitter.com/jeffmaury

Damien B

unread,
Feb 13, 2015, 10:56:30 AM2/13/15
to lescast...@googlegroups.com
Le 13/02/2015 16:28, Emmanuel Lécharny a écrit :
> Le 13/02/15 16:17, Damien B a écrit :
>> Le 13/02/2015 16:13, Emmanuel Lécharny a écrit :
>>> Le 13/02/15 16:05, Cédric Champeau a écrit :
>>>> Je suis assez d'accord sur l'utilisation de final en variable locale
>>>> que j'utilise de temps en temps pour m'assurer que personne ne fera de
>>>> bêtise avec ma variable.
>>> Sauf que *personne* ne va modifier ta varibale, sauf à modifier le code
>>> de ta méthode. Et celui qui modifie ta méthode est assez grand pour ne
>>> pas faire n'importe quoi, sauf à se faire rattraper par un bon code
>>> review.
>> Les code review c'est bien, mais si tu mets le final c'est un problème
>> de moins à regarder :-)
>> Et puis un beau bloc de "final type nom" en début de méthode, c'est
>> tout de suite visible, donc lisible. Dans les habitudes répandues qui
>> rendent le code Java illisible, je ne suis pas sûr que ce soit les
>> final sur les variables locales qui soient le pire honnêtement :)
> Mais comme ça sert à rien
Si, le compilo râle sur réaffectation. Ce n'est pas parce que le
contrôle est dupliqué ailleurs qu'il a disparu de javac, jdt ou jikes
(rions un peu).

> , et qu'il n'y a aucune justification réelle à
> l'utilisation de final dans ce cas là, pourquoi en fourrer partout ?
Parce que maintenant il faut des "justifications réelles" pour les
styles de code ? Arrêtons Java, tous en Forth !

> Parce que "tu peux" ? Parce que que comme ça tes règles checkstyle
> passent avec zéro warnings
Bouof, Checkstyle, c'est quand on a résolu tous les autres problèmes de
qualité et qu'on n'a pas de formateur de code sous la main.

> et que ça donne la trique à ton manageur ou à
> ton ingénieur qualité qui n'a plus codé depuis 1987 ?
C'est marrant cette incompréhension. On n'a pas le droit d'aimer final
sur ses variables locales quand on ne veut pas de réaffectation ? Et ne
pas mettre le final pour marquer explicitement qu'il va y en avoir ? On
est forcément débile, ou alors c'est qu'on est à la solde d'un n+1 qui
ne ferait plus parti du sanctuaire de ceux qui ont le droit d'écrire du
code ?

> Comme le dit si bien Rémi, final != const, alors arrêtez de l'utiliser
> comme si c'était pareil !
De toute façon parler de const sur un langage orienté objet qui ne
connaît pas l'immutabilité c'est un peu non-pertinent dès le départ
comme concept.

> /me se demande qui va atteindre le point goodwin sur 'final'... (grosse
> perche)
Moi j'ai le point goodwill, on te laisse l'autre :-)

Cédric Beust ♔

unread,
Feb 13, 2015, 12:24:53 PM2/13/15
to lescast...@googlegroups.com

2015-02-13 6:56 GMT-08:00 Sebastien Bordes <sebastie...@gmail.com>:

Pour les final ce n'est pas utilisé pour optimiser, juste pour éviter de faire des re-assignations de variable qui vont plus nuire à la lisibilité que les pauvre final dans la signature de la méthode.

Je suis de l’opinion inverse: j’ai dit à toutes mes équipes de ne jamais utiliser final dans les signatures ou les variables locales. Raisons :

  • Je n’ai jamais rencontré un bug causé par la réutilisation accidentelle d’une variable.
  • Tous ces final partout obscurcissent le code et le rendent plus difficile à lire.
-- 
Cédric

Rémi Forax

unread,
Feb 13, 2015, 12:46:25 PM2/13/15
to lescast...@googlegroups.com, Henri Tremblay
Il y a mieux :)
https://github.com/forax/proxy2

Rémi
>>>>>> .
>>>>>> Pour vous désabonner de ce groupe et de tous ses sujets, envoyez
>un
>>>>>> e-mail à l'adresse lescastcodeur...@googlegroups.com.
>>>>>> Pour envoyer un message à ce groupe, adressez un e-mail à
>>>>>> lescast...@googlegroups.com.
>>>>>> Visitez ce groupe à l'adresse
>>>>>> http://groups.google.com/group/lescastcodeurs .
>>>>>> Pour plus d'options, visitez le site
>>>>>> https://groups.google.com/d/optout .
>>>>>>
>>>>>
>>>>>
>>>>>
>>>>> --
>>>>>
>>>>> s...@jrebirth.org - www.jrebirth.org - Blog
><http://blog.jrebirth.org>
>>>>>
>>>>> --
>>>>> Vous recevez ce message, car vous êtes abonné au groupe Google
>Groupes
>>>>> "lescastcodeurs".
>>>>> Pour vous désabonner de ce groupe et ne plus recevoir d'e-mails le
>>>>> concernant, envoyez un e-mail à l'adresse
>>>>> lescastcodeur...@googlegroups.com.
>>>>> Pour envoyer un message à ce groupe, envoyez un e-mail à l'adresse
>>>>> lescast...@googlegroups.com.
>>>>>
>>>>> Visitez ce groupe à l'adresse
>>>>> http://groups.google.com/group/lescastcodeurs.
>>>>> Pour obtenir davantage d'options, consultez la page
>>>>> https://groups.google.com/d/optout.
>>>>>
>>>>
>>>> --
>>>>
>>> Vous recevez ce message, car vous êtes abonné à un sujet dans le
>groupe
>>>> Google Groupes "lescastcodeurs".
>>>
>>>
>>>> Pour vous désabonner de ce sujet, visitez le site
>>>>
>https://groups.google.com/d/topic/lescastcodeurs/NJb9WO2EdI8/unsubscribe
>>>> .
>>>> Pour vous désabonner de ce groupe et de tous ses sujets, envoyez un
>>>> e-mail à l'adresse lescastcodeur...@googlegroups.com.
>>>>
>>> Pour envoyer un message à ce groupe, envoyez un e-mail à l'adresse
>>>> lescast...@googlegroups.com.
>>>>
>>>> Visitez ce groupe à l'adresse
>>>> http://groups.google.com/group/lescastcodeurs.
>>>> Pour obtenir davantage d'options, consultez la page
>>>> https://groups.google.com/d/optout.
>>>>
>>>
>>>
>>>
>>> --
>>>
>>> s...@jrebirth.org - www.jrebirth.org - Blog
><http://blog.jrebirth.org>
--
Envoyé de mon téléphone Android avec K-9 Mail. Excusez la brièveté.

Henri Tremblay

unread,
Feb 13, 2015, 1:11:19 PM2/13/15
to Rémi Forax, lescast...@googlegroups.com
Mais ça proxy des classes?
Reply all
Reply to author
Forward
0 new messages