juillet
2009
Salut
Java World vient de publier un article intéressant remettant en cause certaines pratiques existantes nommé « Four harmful Java idioms, and how to fix them », c’est à dire « Quatre pratiques Java pénalisantes et comment les corriger ». En voici un bref résumé.
Une des idées essentielles est « comment privilégier la lisibilité du code », donc le premier point se base sur l’exemple suivant :
if (! (arg instanceof Range)) return false;
Range other = (Range) arg;
return start.equals(other.start) && end.equals(other.end);
}
Quelles sont les variables locales ? Les attributs ? Les arguments de méthode ? Bien sûr, l’exemple est simpliste, mais on voit bien où l’auteur veut en venir : dur de savoir la portée des variables rencontrées au fil du code. L’auteur propose d’utiliser les préfixes suivants :
* par a les arguments de méthode,
* par f les attributs (field) d’une classe,
* rien de spécifique pour les variables locales.
Le deuxième point est celui des « paquets par couche », entre les com.blah.dao, com.blah.model et autres com.blah.util. En effet, cela oblige à parcourir de nombreux paquets différents pour atteindre les éléments d’une même logique. De plus, argument encore plus convaincant, cela vint à l’encontre du package private par défaut des classes Java. Là, tout est très rapidement public pour que n’importe quel autre paquet (celui en model par exemple) puisse y accéder. N’est pas aberrant ?
L’auteur de proposer de découper par « aspect » : com.blah.peinture, com.blah.auction et ainsi de suite. Et du coup, le package private par défaut de Java reprend tout son sens. Et pour supprimer un de ces aspects, il suffit de supprimer le paquet en question (et les appels y afférant) et… here you’re ! Les bénéfices de la chose, dixit l’auteur :
* Les paquets ont une bien plus grande cohésion et modularité. Le couplage entre les paquets est minimisé.
* Le code est nettement plus auto descriptif. Le lecteur peut appréhender le domaine fonctionnel rien qu’en lisant les noms des paquets.
* Ce modèle conserve l’idée de la séparation des couches, simplement au moyen de classes séparées au sein de chaque paquet.
* Les éléments corrélés sont à la même place : nul besoin de naviguer à travers tout un arbre de paquets pour trouver des éléments pourtant proches.
* Les éléments du paquet sont effectivement package private par défaut, comme ils le doivent. Et si un élément doit être vu de l’extérieur, alors il devient effectivement public.
* supprimer un aspect revient simplement à supprimer un dossier.
* il y a moins d’éléments par paquets et l’architecture globale évolue plus naturellement. Un paquet devenant trop large peut ainsi aisément être découpé. Plus de paquet *Dao avec une foultitude de classes diverses et non corrélées.
L’auteur s’en prend ensuite aux Java Bean. En effet, ces derniers interdisent, par définition, d’avoir des éléments « non changeant » (immutable), du fait du constructeur sans argument par défaut. Et comme le dit Joshua Bloch dans Effective Java, les objets immutables ont les bénéfices suivants :
* simplicité
* thread safe et sans besoin de synchronisation
* peuvent être partagés sans inquiétude
* n’ont pas besoin d’être copiés défensivement
* ignorent également les constructeurs de copie ou la méthode clone()
* bons éléments de base pour construire d’autres classes
* font de bonnes clés de map et d’ensembles
* enfin, ils sont échouent de façon atomique : ils ne peuvent pas être laissés dans un état invalide lorsqu’une erreur arrive.
(A noter que l’auteur ne propose pas de solution « concrète » à la chose, dommage… quelqu’un connait un framework de DAO récupérant des objets immuables de la base de données ??).
Enfin, l’auteur s’en prend à élément d’une bien moindre importance : pourquoi déclarer les éléments privés en haut des classes ? L’ordre naturel devrait plutôt être public, protected puis seulement private, afin de ne pas surcharger le lecteur avec des détails de l’implémentation sensés être encapsulés. (A noter que je pense ce point bien moins intéressant que les autres).
J’espère que cette rapide traduction vous aura interpelé, j’suis preneur de vos avis !
++
Joseph
Cool un débat/troll
Concernant le premier point, je dois dire que je n’apprécies pas vraiment les préfixes ou autres suffixes sur les noms de variables. Non seulement ce n’est pas forcément plus clair mais cela peut gêner les outils intégrer au compilateur (générateur de getter/setter par exemple).
Je préfère de loin un code avec des variables bien nommées (c’est à dire avec des noms bien explicite et clair).
Par contre j’avoue que j’aime bien précéder mes attributs d’instance par this, même si ce n’est pas obligatoire (et que mon gentil EDI me les affiche dans une autre couleur).
En ce qui concerne les packages, je trouve également que ce n’est pas forcément évident de faire un bon découpage. Mais je pense que le salut viendra de la notion de module qui devrait être intégré à Java 7, et de la nouvelle visibilité « module » qui permettra de rendre visible un élément à un ensemble fixe de package (ce ne sera plus du tout ou rien comme actuellement).
Concernant les objets immuables, c’est vrai que leur utilisation apporte plein d’avantage… mais dans bien des cas cela peut nécessiter également un objet « Builder » supplémentaire : qui voudrait utiliser des données qui ne changent JAMAIS !
Enfin, pour le private je suis d’accord cela a peu d’intérêt : si un développeur rentre dans le code c’est justement pour les détails de l’implémentation, sinon il regarde la javadoc !
a++
Pour le premier point je dis « Ho my God!!!!!! », C’est la pire sugestion que j’ai vue depuis un moment. Les préfixes sont une horreur je ne veux surtout pas me retrouver au temps de l’API Win32 de base avec un code vraiment surchargé et moche.
Personellement je n’ai jamais eu le moindre problème à distinguer attributs, champs et variables locales. J’ai des collèges qui ont pour habitude pour cela d’utiliser systématiquement les attribut avec « this.monAttribut » pour les différencier, je trouse ça vraiment plus clair même si a mon avis, c’est peu utile.
Je suis par contre entièrement d’accord avec le 2eme point.
Pour le 3eme, je dis peut-être une connerie, mais je ne vois pas vraiment ou est le problème. Pourquoi un bean sans setter ne serait pas immuable?
Enfin pour le 4eme, ça dépends. J’ai pour habitude de mettre mes variables de propriété de mes beans tout en haut car c’est plus lisible qu’un empilement de getter/setter.
Mais les autre privates sont en bas de programme et la plupart des personnes que je connais font aussi cela.
Salut
Merci c.tranquille pour tes liens, je ne connaissais pas cette revue presse, je l’ai lue avec attention. A noter qu’ils y signalent particulièrement la 2eme proposition.
Blaise1, je suis d’accord que certains arguments sont légers, mais je ne suis pas certain que cela doive conduire à rejeter le tout. Concernant les déclarations en fin de classe des attributs privés, je pense que cela peut avoir de l’intérêt pour ceux qui accèdent directement aux classes, sans passer par la javadoc. Personnellement, pour les classes internes à une entreprise, j’ai d’ailleurs rarement vue une javadoc générée et consultée. Maintenant mon expérience n’est pas définitive, loin de là
++
Personnellement, je met mes variables privées en bas du fichier car je trouve cette manière de faire plus logique. De même que pour une question de lisibilité, je préfère aligner mes accolades contrairement aux conventions de Sun.
Concernant les noms des variables, je ne ressens pas le besoin exprimé.
Les variables locales sont bien visible puisque les méthodes sont en générale d’une bonne longueur (visible en entier sans scroller).
Quand au autres, ce sont les variables d’instances et de classes. Ces dernières étant d’une autre couleur dans l’éditeur que j’utilise (eclipse).
Les conventions, c’est utile mais de là à les suivre aveuglément … Bon, après, c’est sûr, lorsqu’on travaille en équipe, il faut savoir faire des compromis.
Ceci étant dis, ce n’est qu’une question de choix, et comme tout choix, cela se fait pour certaines raisons au détriment d’autres. Il n’y a pas de solution unique.
Ainsi, découper son projet fonctionnellement ou techniquement apporte chacun leur lot d’avantages et d’inconvénients comme souligné par l’auteur et le commentateur.
Cette traduction m’interpelle oui. Depuis bien longtemps les conventions ont été acceptée et utilisé et commencent (enfin) à être prises en comptes par certains « développeurs ». En inventer d’autre risque d’amener d’autres soucis.
Ceci ressemble plus à un troll qu’a une réelle discussion constructive, pour le prouver voici deux réponses qui pourrons déjà alimenter le débat.
> « supprimer un aspect revient simplement à supprimer un dossier. » Oui surement mais récupérer une couche d’un projet à un autre reviens à fouiner dans une multitudes de packages. De plus Je pense que si on se contentais de supprimer un dossier on aurais droit à une flopée de « ClassNotFoundException » & co
> « pourquoi déclarer les éléments privés en haut des classes ? .. afin de ne pas surcharger le lecteur.. »
Si le lecteur ne veux pas être surchargé par les détails de l’implémentation, il n’a pas à aller dans les sources.
Concernant la récupération d’object immuable de la base de données, Hibernate peut très facilement le gérer.
Exemple: SELECT NEW samples.ProductImmutable(p.name, p.code, p.price) FROM samples.Product p
Pour plus de détails: http://blog.xebia.fr/2008/08/04/revue-de-presse-xebia-68/#comment-6667
La version JPA: http://blog.xebia.fr/2008/08/04/revue-de-presse-xebia-68/#comment-6684
Nicolas