L'une des utilité des designs patterns est d'avoir un langage commun entre les développeurs,
Le rôle principal d'un value object est d'encapsuler des données plutôt que de fournir un comportement.
Exemples
Prenons l'exemple d'une tâche désigné par l'objet Tache, dont l'intervalle d'exécution est représenté par l'objet Intervalle. L'objet Intervalle a deux attributs dateDebut et dateFin, et il est possible de retarder une tâche d'un certain nombre de jours grâce à la méthode retarder(int nbrJours).

L'objet Intervalle est un value object, car il est centré sur les données (dates de début et de fin de l'exécution de la tâche) et il n'a pas un vrai comportement.
Si je veux, par exemple, savoir si deux tâches ont le même intervalle d'exécution, j'écrirai de façon intuitive le code suivant :
Il y a des exemples connus de values object. On retrouve, hormis l'intervallede temps, un salaire, une Somme d'argent, une adresse, etc. Dans l'API standard de Java, les objets String, Integer et tous les objets représentant les types primitifs sont considérés comme des values objets.
Pour les values objects ces deux méthodes sont basées sur les valeurs de attributs de l'objet.
En parallèle, les méthodes equals() et hashcode() des entités métier persistantes sont basées sur les valeurs des attributs constituant la clé primaire.
A et B partagent une propriété x, si B modifie x alors cette modification se répercute sur l'objet A, ce qui provoque des effets indésirables. Voici un exemple concret repris de [1] :
La méthode retarder() permet de retarder une tâche un certain nombre de jours :
Quel est le problème dans le code suivant ?
En observant le code attentivement, on remarque que la tache1 a également été retardée de cinq jours, et ce de manière totalement inaperçue et involontaire!
Pour corriger l'exemple précédent, on interdit la modification des attributs de l'objet, et on créé à la place un nouvel objet avec les nouvelles valeurs. La méthode retarder() deviendrait :
On comprend maintenant pourquoi, par exemple, la classe java.lang.String est immuable. En effet, une fois l'objet créé il n'est plus modifiable, il peut être partagée sans aliasing et sans aucun problème de multi-threading car les méthodes telles que substring() ou concat() retournent toujours un nouvel objet.
L'origine de la confusion vient, en réalité, des premières versions des J2EE Core patterns de sun. En effet, en 2001 le DTO était appelé Value Object. Il ne l'est plus maintenant fort heuresement!
ce n'est malheureusement pas le cas pour le pattern Value Object qui est souvent utilisé dans des contextes différents,
le rendant ainsi sujet à diverses interprétations.Dans un contexte J2EE, Value Object est synonyme de Data Transfert Object,
alors que dans un contexte Programmation Orienté Objet, il a une tout autre signification.Le but de cet article est de faire la lumière sur les Value Objects en donnant une définition claire et non ambiguë et en expliquant l'origine de la confusion.
Dans un modèle de domaine reposant sur les Pojos, on retrouve les entités métiers qui sont caractérisées par leur identité, lorsque l'entité est persistée à l'aide d'un ORM tel que Hibernate ou JDO, son identité correspond généralement à la clé primaire. D'un autre coté, on retrouve aussi des objets, simples, qui sont cette fois-ci, caractérisés par leur valeur et non par leur identité : ce sont les Value Objects.le rendant ainsi sujet à diverses interprétations.Dans un contexte J2EE, Value Object est synonyme de Data Transfert Object,
alors que dans un contexte Programmation Orienté Objet, il a une tout autre signification.Le but de cet article est de faire la lumière sur les Value Objects en donnant une définition claire et non ambiguë et en expliquant l'origine de la confusion.
Quel est le rôle des Values Object dans le modèle objet ?
Comme je l'ai précisé plus haut, un value object est un objet qui est définit par la valeur de ces attributs, cela veut dire que deux instances qui ont les même valeurs sont égales et interchangeables.Le rôle principal d'un value object est d'encapsuler des données plutôt que de fournir un comportement.
Exemples
Prenons l'exemple d'une tâche désigné par l'objet Tache, dont l'intervalle d'exécution est représenté par l'objet Intervalle. L'objet Intervalle a deux attributs dateDebut et dateFin, et il est possible de retarder une tâche d'un certain nombre de jours grâce à la méthode retarder(int nbrJours).

L'objet Intervalle est un value object, car il est centré sur les données (dates de début et de fin de l'exécution de la tâche) et il n'a pas un vrai comportement.
Si je veux, par exemple, savoir si deux tâches ont le même intervalle d'exécution, j'écrirai de façon intuitive le code suivant :
if (tache1.getIntervalle().equals(tache2.getIntervalle())) {
faireQuelqueChose();
}
Il y a des exemples connus de values object. On retrouve, hormis l'intervallede temps, un salaire, une Somme d'argent, une adresse, etc. Dans l'API standard de Java, les objets String, Integer et tous les objets représentant les types primitifs sont considérés comme des values objets.
Propriétés des values objects
1 Un value object doit surcharger les méthodes equals() et de hashcode()
Les méthodes equals() et hashcode() permettent de dire si deux instances sont égales. Par défaut, elles sont calculées sur la base de l'adresse mémoire de l'objet.Pour les values objects ces deux méthodes sont basées sur les valeurs de attributs de l'objet.
En parallèle, les méthodes equals() et hashcode() des entités métier persistantes sont basées sur les valeurs des attributs constituant la clé primaire.
2 Un value object doit être immuable
Un object value doit être immuable et ce pour éviter le phénomène de « l'aliasing ». Un aliasing se produit dans le cas suivant :A et B partagent une propriété x, si B modifie x alors cette modification se répercute sur l'objet A, ce qui provoque des effets indésirables. Voici un exemple concret repris de [1] :
La méthode retarder() permet de retarder une tâche un certain nombre de jours :
void retarder(int nbrJours) {
this.intervalle.setDateDebut(this.intervalle.getDateDebut() + nbrJours);
}
Quel est le problème dans le code suivant ?
Tache tache1 = new Tache();
Tache tache2 = new Tache();
tache1.setIntervalle(new Intervalle("4 mars 2007", "29 mars 2007");
tache2.setIntervalle(tache1.getIntervalle());
tache2.retarder(5);
En observant le code attentivement, on remarque que la tache1 a également été retardée de cinq jours, et ce de manière totalement inaperçue et involontaire!
Pour corriger l'exemple précédent, on interdit la modification des attributs de l'objet, et on créé à la place un nouvel objet avec les nouvelles valeurs. La méthode retarder() deviendrait :
void retarder(int nbrJours) {Sachez enfin, que rendre un objet immuable a des propriétés intéressantes, notamment le partage du même objet entre plusieurs threads sans recourir à la synchronisation. Elles rendent le design robuste et améliorent les performances [2][3].
this.intervalle = new Intervalle(this.intervalle.getDateDebut() + nbrJours);
}
On comprend maintenant pourquoi, par exemple, la classe java.lang.String est immuable. En effet, une fois l'objet créé il n'est plus modifiable, il peut être partagée sans aliasing et sans aucun problème de multi-threading car les méthodes telles que substring() ou concat() retournent toujours un nouvel objet.
3 Un value object peut être persisté sous certaines conditions
Bien entendu, un value object peut être persisté. Cependant, il ne doit pas correspondre à une ligne entière dans une table [4]. Les colonnes qui correspondent à ses attributs, s'ajoutent aux colonnes d'une entité persistante. Hibernate offre cette possibilité via le mécanisme de component [5].Pourquoi la confusion entre un value object et un DTO
Pour rappel, un Data Transfert Object est utilisé dans les architectures distribuées, pour transporter les données entre la couche cliente et la couche métier (représentée par des EJB). Le but est de recevoir et d'envoyer un paquet de données (DTO) en un seul appel plutôt que des faire de multiples appels distants très coûteux en performance. Le seul point commun entre un value object et un DTO c'est qu'ils sont tous les deux centrés sur les données.L'origine de la confusion vient, en réalité, des premières versions des J2EE Core patterns de sun. En effet, en 2001 le DTO était appelé Value Object. Il ne l'est plus maintenant fort heuresement!