IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

API standards et tierces Java Discussion :

Equaliz : Créer des méthodes equals, hashcode et clone (et bientôt toString) facilement


Sujet :

API standards et tierces Java

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 15
    Par défaut Equaliz : Créer des méthodes equals, hashcode et clone (et bientôt toString) facilement
    Hello,

    J'ai créé une petite librairie en LGPL qui permet de créer ces méthodes de base java en évitant de coder des règles parfois complexe et souvent rébarbatives.

    L'idée est de d'écrire en premier lieu ce qu'est une égalité pour un type d'objet. et après d'écrire en un ligne ces méthodes.

    Plus d'info su http://code.google.com/p/equaliz/

    Qu'en pensez vous ? Aimeriez vous participer à ce projet ?

  2. #2
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 586
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 586
    Par défaut
    Ça a l'air très bien mais bon... Eclipse et NetBeans le font déjà, il me semble. C'est à utiliser dans quel contexte ?
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  3. #3
    Membre Expert
    Avatar de professeur shadoko
    Homme Profil pro
    retraité nostalgique Java SE
    Inscrit en
    Juillet 2006
    Messages
    1 257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 77
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : retraité nostalgique Java SE

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 257
    Par défaut
    comme en témoigne les discussions sur le net l'écriture de equals est complexe et dépend de pleins d'options qui dépendent des propriétés que l'on veut donner aux objets..... Quelle stratégie pour écrire un code qui fasse plaisir à tout le monde?

  4. #4
    Membre émérite Avatar de Heimdal
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    549
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2006
    Messages : 549
    Par défaut
    Eclipse et netbeans te génère des méthodes toutes moches après avoir choisi les attributs à prendre en compte... Ça ne passe ni checkstyle, ni pmd, c'est verbeux. Par contre le contrat est bien rempli.

    Le plus comparable c'est les EqualsBuilder, HashCodeBuilder, ToStringBuilder de apache commons-lang.

    Démarche intéressante cela dit meme si j'aime bien les méthodes equals et hashcode de Object.

  5. #5
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Salut,

    Tu sors quand même l'artillerie lourde non ?
    • Une Map en static qui contient toutes la configuration.
    • Beaucoup de reflection...
    • Des Proxy, qui de plus neccessite une librairie annexe (les Proxy standards ne suffisent pas ?)




    Pour equals/hashCode tu peux faire quelques choses de très simple en utilisant un tableau et les méthodes Arrays.deepHashCode() et Arrays.deepEquals().


    Exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    public class MyObject {
     
    	private String str;
    	private Date date;
    	private int value;
    	private double dbl;
    	private int ignored;
     
    	/**
             * Méthode privé renvoyant l'identité de l'instance courante,
             * et qui servira à générer les hashCode et vérifier les égalités :
             */
    	private Object[] identity() {
    		// On retourne uniquement les attributs à utiliser
    		// pour identifier l'instance courante :
    		return new Object[]{str, value, date, dbl};
    	}
     
    	@Override
    	public int hashCode() {
    		return Arrays.deepHashCode(identity());
    	}
     
    	@Override
    	public boolean equals(Object obj) {
    		if (obj == this)
    			return true;
    		if (obj instanceof MyObject) {
    			MyObject other = (MyObject) obj;
    			return Arrays.deepEquals(this.identity(), other.identity());
    		}
    		return false;
    	}
     
    }

    a++

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 15
    Par défaut
    Hello,

    Citation Envoyé par adiGuba Voir le message
    Salut,

    Tu sors quand même l'artillerie lourde non ?
    • Une Map en static qui contient toutes la configuration.
    • Beaucoup de reflection...
    • Des Proxy, qui de plus neccessite une librairie annexe (les Proxy standards ne suffisent pas ?)
    Sur la map en static ce n'est clairement pas optimal, on pourrait evisager une instance equalize par classe. un peu comme les logger de log4j. C'est effectivement nettement mieux.

    La reflexion je ne vois pas trop comment l'éviter.

    les proxy standard ne suffisent pas puisque qu'il ne proxy que les interfaces.


    Citation Envoyé par adiGuba Voir le message
    Pour equals/hashCode tu peux faire quelques choses de très simple en utilisant un tableau et les méthodes Arrays.deepHashCode() et Arrays.deepEquals().

    Excellent, je ne connaissais pas



    Merci pour ces points de vue je sens que je vais faire quelques mises à jour

  7. #7
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 483
    Par défaut
    Citation Envoyé par adiGuba Voir le message
    Salut,

    Tu sors quand même l'artillerie lourde non ?
    +1, ça risque d'etre très lent, ce qui est dommage quand on considère que les méthodes equals et hashcode doivent être rapides si on veux des collections performantes.


    Exemple :
    Que je me permet de corriger:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    protected Object[] identity()
    Sinon tu aura des incohérence dans la méthode equals si tu compare un MyObject avec un MyObjectChild qui l'étends, sans compter que tu aura besoin de recoder equals et hashcode dans chaque fille

  8. #8
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par tchize_ Voir le message
    Sinon tu aura des incohérence dans la méthode equals si tu compare un MyObject avec un MyObjectChild qui l'étends, sans compter que tu aura besoin de recoder equals et hashcode dans chaque fille
    Non le private est volontaire pour éviter de partager les références.


    Tu n'as pas besoin de recoder equals/hashCode à moins de vouloir changer les règles d'égalités. Et dans ce cas tu casses la notion de symétrie que devrait respecter la méthode equals(), car a.equals(b) ne sera plus forcément équivalent à b.equals(a) selon le type exact de a & b...


    a++

  9. #9
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 483
    Par défaut
    Citation Envoyé par adiGuba Voir le message
    Non le private est volontaire pour éviter de partager les références.


    Tu n'as pas besoin de recoder equals/hashCode à moins de vouloir changer les règles d'égalités. Et dans ce cas tu casses la notion de symétrie que devrait respecter la méthode equals(), car a.equals(b) ne sera plus forcément équivalent à b.equals(a) selon le type exact de a & b...


    a++
    C'est ce que je dit. Avec ton code, si je crée une fille à ton objet, fille qui aura des attributs en plus, je vais devoir recoder hashcode et equals dans la fille pour prendre en compte les attributs supplémentaires. Et lorsque je compare une instance de la fille (a) avec un instance du père (b), pour lequel les attributs père sont identique (mais pas les attributs enfants), on aura a.equals(b) à false (la fille vois que c'est pas instanceof Fille) mais on aura aussi b.equals(a) à true, d'où problème de symmétrie. Qu'on a plus en rendant la méthode protégée (la fille y rajoute juste ses attribut et hop, le tour est joué).

  10. #10
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par tchize_ Voir le message
    Qu'on a plus en rendant la méthode protégée (la fille y rajoute juste ses attribut et hop, le tour est joué).
    Non tu conserverais le même problème.
    A partir du moment où tu modifies les règles de l'égalité tu perds la symétrie (à moins de rajouter une contrainte plus forte sur le type de la classe).

    Mais dans tous les cas tu devras recoder hashCode() et equals()...

    Et en passant la méthode identity() en protected, tu risque de partager des champs privées

    a++

  11. #11
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 483
    Par défaut
    Citation Envoyé par adiGuba Voir le message

    Mais dans tous les cas tu devras recoder hashCode() et equals()...

    Et en passant la méthode identity() en protected, tu risque de partager des champs privées
    je suis pas d'accord sur le recodage. Et en la gardant privée, quand tu ajoute le fils, tu va devoir recoder le parent, ce qui viole un peu les principes objet à mon avis

  12. #12
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par tchize_ Voir le message
    je suis pas d'accord sur le recodage. Et en la gardant privée, quand tu ajoute le fils, tu va devoir recoder le parent, ce qui viole un peu les principes objet à mon avis
    Heu... non !? Il n'est pas question de recoder le parent mais le fils...


    Quoi qu'il arrive lorsque tu ajoutes un fils avec de nouvelles propriétés pour l'identité, tu casses le principe de symétrie.

    A moins de limiter l'égalité aux types de la même classe, c'est à dire en ignorant les classes filles et en remplaçant
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if (obj instanceof MyObject)
    par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if (obj.getClass()==MyObject.class)

    a++

  13. #13
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 15
    Par défaut
    Citation Envoyé par tchize_ Voir le message
    +1, ça risque d'etre très lent
    Oui et non, bien sûr c'est nettement plus lent qu'une référence directe (de l'ordre de 4 fois et améliorable avec quelques bonnes idées pour limiter les beanutils)

    Mais on est pas toujours obligé de stocker dans des maps/set.

    - De manière générale, si notre règle d'égalité est simple c'est bête d'utiliser mon api (on écrit une méthode ad hoc et c'est réglé)
    - Si la performance compte c'est également idiot d'utiliser mon api.

    Qu'est que l'on appelle lent ? tout dépend de l'application derrière non ?

    M'enfin l'idée principale de cette api est de dépasser l'idée d'égalité par le code mais de l'imposer par sa définition. Quand le domaine métier est complexe ça a du sens.

    L'exemple avec les arrays n'est qu'une vison un peu différente du equalsBuilder et companie ; On ne gère qu'au premier niveau de l'objet. (si j'ai un objet qui en compose un autre il faut que je fasse des tests de nullité)


    Maintenant que j'y pense, il y a sans doute plus performant :
    Faire du code génération de classe implémentant les méthodes d'Equaliz.
    En gros je définie l'égalité (quelque soit le moyen dsl comme actuellement ou annotations mais j'aime moins) et après je génère dur code à la volée (ce que fait CGlib que tout le monde utilise). Ca me créé des sous classes d'Equaliz qui possède les bonnes méthodes sans reflexion. Le problème c'est que je dois peut être me taper la génération de bytecode à la mimine (quoi que javac est il me semble appellable directement dans le code)

    La permgen n'explosera pas puisque seule une nouvelle classe sera créée par définition de classe

    Vous en pensez quoi ?

  14. #14
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 483
    Par défaut
    Citation Envoyé par adiGuba Voir le message
    Quoi qu'il arrive lorsque tu ajoutes un fils avec de nouvelles propriétés pour l'identité, tu casses le principe de symétrie.
    Ben non justement, faut l'éviter, et mettre la méthode en protégé le permet, le fils n'a qu'à la surcharger, et la méthode equals se comportera correctement, sans devoir la réécrire:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public class Parent{
        // ....
        protected Object[] identity() {return new Object[]{a,b,c};}
        // on recopie ton equals / hashcode de tout à l'heure
    }
     
    public class Fils extends Parent{
       // attributs supplémentaires
       @override
       protected Object[] identity(){return  new Object[]{super.identity(),e,f,g};}
       // et c'est tout, pas de redefinition de equals / hashcode.
    }

  15. #15
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Ah oui en effet... Je raisonnait toujours en private avec 2 version différentes de la méthode



    Par contre je trouve quand même que le passage en protected n'est pas très propre, puisqu'il permet de donner accès à des membres private

    a++

  16. #16
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 483
    Par défaut
    Citation Envoyé par adiGuba Voir le message
    Par contre je trouve quand même que le passage en protected n'est pas très propre, puisqu'il permet de donner accès à des membres private

    a++
    Tout a fait d'accord avec toi, il y a surement moyen de faire plus propre, mais j'ai pas envie de chercher là

Discussions similaires

  1. Réponses: 2
    Dernier message: 18/11/2011, 17h57
  2. Réponses: 4
    Dernier message: 02/05/2011, 15h48
  3. Equaliz 0.2 : Des methodes equals et hashcode orienté métier
    Par benjamalin dans le forum API standards et tierces
    Réponses: 0
    Dernier message: 16/08/2010, 15h49
  4. Réponses: 3
    Dernier message: 22/01/2009, 22h05
  5. Réponses: 0
    Dernier message: 26/11/2007, 16h47

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo