J'ai implémenté quelques applications Java maintenant, seules des applications de bureau jusqu'à présent. Je préfère utiliser des objets immuables pour transmettre les données dans l'application plutôt que d'utiliser des objets avec des mutateurs (setters et getters ), également appelés JavaBeans.
Mais dans le monde Java, il semble qu'il soit beaucoup plus courant d'utiliser JavaBeans, et je ne comprends pas pourquoi je devrais les utiliser à la place. Personnellement, le code semble meilleur s'il ne traite que d'immuable objets au lieu de muter l'état tout le temps.
Les objets immuables sont également recommandés dans Item 15: Minimize mutability, Effective Java 2ed .
Si j'ai un objet Person
implémenté comme JavaBean il ressemblerait à:
public class Person {
private String name;
private Place birthPlace;
public Person() {}
public setName(String name) {
this.name = name;
}
public setBirthPlace(Place birthPlace) {
this.birthPlace = birthPlace;
}
public String getName() {
return name;
}
public Place getBirthPlace() {
return birthPlace;
}
}
Et le même Person
implémenté comme un objet immuable:
public class Person {
private final String name;
private final Place birthPlace;
public Person(String name, Place birthPlace) {
this.name = name;
this.birthPlace = birthPlace;
}
public String getName() {
return name;
}
public Place getBirthPlace() {
return birthPlace;
}
}
Ou plus proche d'un struct
en C:
public class Person {
public final String name;
public final Place birthPlace;
public Person(String name, Place birthPlace) {
this.name = name;
this.birthPlace = birthPlace;
}
}
Je pourrais également avoir des getters dans l'objet immuable pour cacher les détails de l'implémentation. Mais comme je ne l'utilise que comme struct
, je préfère ignorer les "getters" et rester simple.
Simplement, je ne comprends pas pourquoi il vaut mieux utiliser JavaBeans, ou si je peux et dois continuer avec mes POJO immuables?
La plupart des bibliothèques Java Java semblent avoir un meilleur support pour JavaBeans, mais peut-être que plus de support pour les POJO immuables devient plus populaire au fil du temps?
J'ai été surpris que le mot Thread n'apparaisse nulle part dans cette discussion.
L'un des principaux avantages des classes immuables est qu'elles sont intrinsèquement plus sûres pour les threads en raison de l'absence d'état mutable partagé.
Non seulement cela facilite votre codage, mais cela vous donnera également deux avantages en termes de performances comme effet secondaire:
Moins de besoin de synchronisation.
Plus de possibilités d'utilisation des variables finales, ce qui peut faciliter les optimisations ultérieures du compilateur.
J'essaie vraiment d'aller vers des objets immuables plutôt que vers des classes de style JavaBean. L'exposition des entrailles des objets via des getters et setters ne devrait probablement pas être le choix par défaut.
Eh bien, cela dépend de ce que vous essayez de faire. Si vous travaillez avec une couche persistante et que vous récupérez une ligne de la base de données dans un POJO et que vous souhaitez modifier une propriété et la sauvegarder, l'utilisation du style JavaBean serait préférable, surtout si vous avez beaucoup de propriétés.
Considérez que votre personne a beaucoup de domaines comme le prénom, le deuxième prénom, le nom de famille, la date de naissance, les membres de la famille, l'éducation, l'emploi, le salaire, etc.
Et cette personne se trouve être une femme qui vient de se marier et a accepté de changer son nom de famille, et vous devez mettre à jour la base de données.
Si vous utilisez POJO immuable, vous récupérez un objet Person qui la représente, puis vous créez un nouvel objet Person auquel vous transmettez toutes les propriétés que vous n'avez pas modifiées telles qu'elles sont, et le nouveau nom de famille, et enregistrez-le.
S'il s'agissait d'un bean Java bean, vous pouvez simplement faire setLastName () et l'enregistrer.
C'est "Minimiser la mutabilité" et non "ne jamais utiliser d'objets mutables". Certaines situations fonctionnent mieux avec des objets mutables, c'est vraiment à vous de décider si rendre un objet mutable conviendra mieux à votre programme ou non. Vous ne devriez pas toujours dire "doit utiliser des objets immuables", voyez plutôt combien de classes vous pouvez rendre immuables avant de commencer à vous faire du mal.
Résumant d'autres réponses, je pense que:
get(id): Client
et save(MutableClient)
, MutableClient étant un descendant de Client.S'il y avait un point intermédiaire (créer, définir des propriétés, rendre inmutable), les frameworks encourageraient peut-être davantage une approche inmutable.
Quoi qu'il en soit, je suggère de penser aux objets immuables comme "lecture seule Java Beans"), soulignant le fait que si vous êtes un bon garçon et ne touchez pas à cette dangereuse méthode setProperty, tout ira bien.
Depuis Java 7, vous pouvez avoir des beans immuables, le meilleur des deux mondes. Utilisez l'annotation @ConstructorProperties sur votre constructeur.
public class Person {
private final String name;
private final Place birthPlace;
@ConstructorProperties({"name", "birthPlace"})
public Person(String name, Place birthPlace) {
this.name = name;
this.birthPlace = birthPlace;
}
public String getName() {
return name;
}
public Place getBirthPlace() {
return birthPlace;
}
}
Pour être honnête, je ne pense pas que les objets immuables deviennent si populaires.
Je vois les avantages, mais les frameworks comme Hibernate et Spring sont actuellement très en vogue (et pour une bonne raison aussi), et ils fonctionnent vraiment mieux avec les beans.
Je ne pense donc pas que l'immuabilité soit mauvaise, mais cela limiterait certainement vos options d'intégration avec les frameworks actuels.
MODIFIER Les commentaires m'invitent à clarifier un peu ma réponse.
Il y a très certainement des problèmes où l'immuabilité est très utile, et est en effet utilisée. Mais je pense que la valeur par défaut actuelle semble être modifiable car c'est ce qui est généralement attendu, et immuable uniquement si cela a un avantage clair.
Et bien qu'il soit en effet possible d'utiliser des constructeurs avec des arguments dans Spring, cela semble être conçu comme un moyen d'utiliser du code hérité et/ou tiers avec votre beau code Spring flambant neuf. C'est du moins ce que j'ai retenu de la documentation.