L’article que je vous propose aujourd’hui est un petit état des lieux sur l’intérêt des classes utilitaires dans nos projets.
Il n’est pas rare, voir même courant, de trouver dans les projets sur lesquels nous développons, tout un tas de classes utilitaires adressant, en règle générale, les problématiques suivantes :
– Conversion de date
– Manipulation de chaine de caractères
– Vérification de la nullité ou non d’une référence d’un objet
– Traitement sur des collections
– etc
Le nommage des classes est souvent suffixé par les termes suivants :
– Util(s)
– Tool(s)
et se trouve dans le meilleur des cas dans des packages nommés de la façon suivante :
– **.**.**.utils
– **.**.**.tools
Le nom des packages peut varier selon si les classes utilitaires sont liées à un contexte fonctionnel.
Généralement, ces classes sont composées de plusieurs méthodes traitant sensiblement un contexte commun (manipulation de chaine).
Le pour : Ce que ces classes peuvent nous apporter
Elles ont vocation à factoriser un algorithme ou un traitement générique, que d’autres pourront réutiliser à volonté.
La démarche est intéressante en terme de coût de conception, de maintenance, de gain de temps.
Même si ces arguments sont tout à fait valables et incontournables dans le paradigme objet nous allons voir dans la section suivante des contre-exemples mettant en cause ce type de classe.
Le contre : Ce qu’elles peuvent générer
Dans cette section, je vais noircir le tableau en listant les points négatifs concernant l’existence de telles classes au sein de nos projets.
1 – La confusion
Au début, une classe utilitaire à un sens précis et adresse un domaine spécifique.
Avec le temps, le domaine adressé peut dévier et la classe se voit enrichie de méthodes sortant du périmètre initial et peu à peu cela devient une classe fourre-tout. La sémantique exprimée par le nom de la classe se perdra doucement.
A contrario, les classes utilitaires peuvent pulluler sur le projet et l’on se retrouvera avec du code dupliqué.
2 – Tests unitaires supplémentaires
Une bonne couverture de code est essentielle dans un projet. Ceci implique qu’il faudra créer l’ensemble des tests unitaires pour cette partie du code. Bien que la démarche soit bonne, cela aura pour conséquence d’allonger un peu plus le temps de build de notre application. Ce qui n’est pas une bonne chose…
_3 – Documentation pauvre = Redondance _
La documentation : le parent pauvre d’un projet informatique.
Lorsque l’on est en train de développer une fonctionnalité et que l’on a besoin de savoir si un utilitaire est disponible (par exemple : transformer une liste de String en une chaine de caractère contenant l’ensemble des occurrences de la liste séparées par une virgule), on commence à rechercher dans le code puis on tente de voir dans la documentation projet si une telle classe existe. Après une recherche infructueuse, on finit par la développer soit-même.
En fait, un mois plutôt, votre collègue, qui est parti depuis, l’avait déjà fait mais pour une autre fonctionnalité (il avait nommé la classe en la préfixant par le nom de la fonctionnalité et en la suffixant de Tools).
Conclusion, l’utilitaire a été développé deux fois selon deux approches différentes => nous avons de la redondance.
4 – Et les libs disponibles
Il y a quelques années, au début de Java, le nombre de libs était limité. Aujourd’hui, il est difficile de ne pas trouver une librairie adressant les problématiques récurrentes de nos projets. Avec les moyens de recherche à disposition, il est plus facile de trouver sur internet une lib répondant à notre besoin, plutôt que de retrouver vainement du code dans l’application.
De plus, le code de ces libs est éprouvé et plus sûr.
Ci-dessous, quelques librairies adressant les problèmes les plus courants :
– Google Guava
– Commons Jakarta
– Joda
– etc.
5 – PermGen
Une problématique plus bas niveau concerne la taille de la zone mémoire PermGen.
Cette zone stocke l’ensemble des fichiers .class du projet.
Dans un projet classique géré par Maven, un certain nombre de dépendances (transitives) sont ajoutées au projet. Bien souvent, les libs évoquées ci-dessus sont incluses donc disponibles.
Le fait d’ajouter des classes utilitaires dans le projet ne fait qu’augmenter l’espace occupé dans la zone mémoire PermGen. Réduire le recours à des classes utilitaires permet de ne pas charger un peu plus cette zone de la JVM. Je conviens que cet argument est à relativiser.
Mais doit-on renoncer aux classes utilitaires dans les projets ?
Je pense que la réponse n’est pas aussi catégorique que ça.
– Les classes utilitaires doivent être utilisées dans des cas précis pour adresser des problématiques purement fonctionnelles. Par exemple, la transformation d’un objet métier (issue du domaine), la réalisation d’un calcul lié au métier du projet, etc. Dans ces cas, aucune librairie ne saura répondre à votre problème vraiment spécifique au métier sous-jacent.
– Il peut arriver, malgré tout l’écosystème à disposition, que l’on ne trouve pas chaussure à son pied.
Même si ces cas existent, je reste persuadé que dans 90% des cas, on trouve ce que l’on cherche.
Trop de librairies tue la librairie
Maintenant on peut prendre le problème à l’envers et se trouver confronté à plusieurs librairies répondant à mon problème.
Pour départager les finalistes, il faut regarder plusieurs critères :
– âge de la librairie : détermine sa pérennité
– la documentation : la facilité pour la prise en main
– l’activité sur le projet : si des bugs sont détectés, seront-ils corrigés ?
En conclusion, je pense qu’il est important de bien connaitre l’écosystème dans lequel nous évoluons. D’avoir une bonne connaissance des outils existants afin de les exploiter et ne pas réinventer la roue.
Aussi de savoir limiter son esprit créatif et de chercher au lieu de réinventer.
En adoptant cette démarche, nous garderons aussi toute notre énergie pour se concentrer sur le code métier.
N’hésitez pas à réagir dans les commentaires, dans un sens ou dans l’autre, afin d’enrichir le contenu de cet article par diverses expériences.
#java #utilitaire #tool #api