À propos de cet article
L’immuabilité est un concept large et a de nombreux angles. L’immuabilité est un ensemble de pratiques susceptibles de réduire le nombre de bogues dans votre application. En conséquence, ce sujet invoque la confusion. Ici, nous l’examinons sous un autre angle. Je vais expliquer les aspects les plus importants de l’immuabilité dans un langage clair.
Exemples de problèmes de mutabilité
Avant de commencer, examinons deux exemples. Ils sont assez artificiels mais expliquent les problèmes potentiels avec le code mutable :
Les données sont modifiées lorsqu’elles sont transmises à une fonction
Dans cet exemple, nous passons l’objet logItem à la fonction printLogItem. S’attendant à ce qu’il soit juste imprimé, nous découvrons plus tard que le contenu de notre objet logItem a été modifié.
Le rapport de génération est devenu incohérent en raison d’un changement d’objet interne
Dans cet exemple, nous avons créé un rapport en supposant que les données internes (objet Météo) ne seront pas modifiées. Plus tard, nous avons imprimé un rapport et constaté qu’il devenait incohérent (en raison d’un changement d’objet interne).
Vous pourriez dire « Quels exemples stupides ! »
Les exemples fournis peuvent sembler extrêmement idiots. Qui écrirait un tel code ? Eh bien, le code semble évident simplement parce qu’il est petit. Dans de vrais projets avec une centaine de classes complexes, vous pouvez manquer de tels problèmes.
Correction des exemples fournis
Le problème central des exemples mentionnés est que le l’objet qui ne devrait pas être modifié a été modifié. Maintenant, lorsque nous identifions le problème, nous pouvons le résoudre. Mais comment? Il y a plusieurs façons. Commençons par le plus évident :
Finaliser les champs
Tout d’abord, si nous oublions de mettre privé visibilité, alors les données seraient toujours accessibles. Pour le rendre immuable, nous devons le rendre final
comme ci-dessous :
Retrait du setter
Le moyen le plus simple de conserver le même état est de supprimer le setter. Serait-ce suffisant ?
Passer un clone au lieu d’une instance réelle
Si nous voulons garder l’ancienne implémentation et le setter en vie, nous pouvons le résoudre de 2 côtés :
- On peut passer un clone de l’objet.
- Nous pouvons cloner les objets passés dans la fonction printLogItem.
Primitives immuables en Java
Par défaut en Java, il existe quelques primitives telles que int, long et char. Toutes les primitives ne peuvent pas changer leur valeur à moins que vous ne les réaffectiez. Par conséquent, les avoir marqués comme final
les rendra parfaitement immuables.
Chaîne immuable en Java
La chaîne en Java est la même que toutes les autres primitives. Une fois créé, il ne peut pas changer sa valeur. Pour le rendre immuable, il suffit de le faire final
. Peasy facile.
Classe immuable en Java
La classe en Java n’est rien d’autre qu’un modèle. Une fois qu’une classe a une implémentation, elle devient un objet. Par conséquent, dire « Classe immuable » n’est pas précisément correct. Mais en général, cela signifie que toutes les instances de cette classe seraient immuables.
D’accord, alors quels sont les critères d’immuabilité de classe ?
- Chaque champ de cette classe doit être immuable.
- Chaque champ et classe doit également être immuable.
Créer une classe Java immuable
Selon les règles expliquées précédemment, nous pouvons créer une classe immuable simple :
Collections immuables en Java
Les collections sont aussi des objets, donc si elles suivent les exigences expliquées, elles sont immuables. En pratique, cela signifie qu’ils ne sont initialisés qu’une seule fois et pour toujours. Toutes les modifications sont désactivées ou feront face à des exceptions levées.
Dans l’exemple suivant, je montrerai comment créer une collection immuable à l’aide de l’API Java publique (java.util.Collections.*) :
Utiliser Lombok pour générer du code immuable
Lombok est un framework qui fournit des annotations qui vous permet de générer des classes Java à l’aide d’annotations. Lombok fournit des options pour les classes immuables (mais vous devez prendre en compte toutes les exigences d’immuabilité : par exemple, tous les champs internes doivent également être immuables).
Lombok @Value Annotation: Haricot chaudron immuable
Pour générer rapidement un bean Java immuable avec des champs finaux et un hashcode/égal, vous devez utiliser l’annotation @Value :
De plus, l’annotation @Value fournit une option avec la méthode d’usine statique :
Le singleton est-il immuable ?
Non. Le modèle Singleton définit que pour une classe donnée, une seule instance peut exister. Si cette classe respecte toutes les exigences d’immuabilité, elle peut être immuable.
Enum est-il immuable ?
Cette question est assez similaire à la précédente. Enum est une classe qui a un nombre prédéfini d’instances. À l’intérieur de chaque enum, nous pouvons avoir des données mutables, mais si les champs internes de enum sont immuables, alors enum est également immuable.
Principaux avantages des pratiques d’immuabilité
Parmi tous les aspects positifs existants de l’immuabilité, il y a deux avantages principaux :
- L’application devient plus prévisible et ne sera pas confrontée à des incohérences (pour les données immuables).
- Les parties immuables de l’application seront Thread Safe (C’EST TRÈS VALEUR !).
Conclusion
La pratique décrite n’est pas obligatoire et vous pouvez toujours écrire des applications fiables sans astuces immuables. Cependant, les recommandations expliquées ne sont pas seulement un « bon ton », mais un moyen pratique de créer des applications stables et moins boguées. Dans un monde d’entreprise avec d’énormes applications, sa pratique devrait être obligatoire. Merci d’avoir lu!