Published by

Il y a 15 ans -

Temps de lecture 3 minutes

JSR 294 – Les Superpackages

Lors de la revue de presse du début décembre, nous annoncions le passage en public draft de la JSR-294 (Improved Modularity Support). Cette JSR fait partie de la liste des évolutions potentielles proposées comme amélioration pour le JDK 7. Ce billet fait le point sur ce qu’elle propose.

Si vous développez en Java depuis plusieurs années, et avez eu l’occasion de travailler sur des bibliothèques réutilisables, vous avez peut-être été confronté au problème suivant : la publication sélective de classes ou de composants. En clair, vous auriez aimé, dans certaines situations, exposer certaines classes d’un package à celles d’un autre package – typiquement dans une relation de type fabriquant-fabriqué que l’on retrouve dans le pattern ‘Factory’. Or Java ne vous propose que 2 options pour exposer une classe : elle peut être publique – donc visible depuis n’importe quel autre package – ou « package private » – c’est-à-dire visible uniquement depuis les classes appartenant au même package. Pour contourner cette gêne, les concepteurs d’API recourent généralement à des stratégies de contournement :

  • Soit ils rendent certaines implémentations internes « publiques », en précisant dans la documentation que leur utilisation n’est pas garantie, et en indiquant les moyens « légaux » de les instancier et de les manipuler. C’est la philosophie adoptée notamment par les auteurs du framework Eclipse.
  • Soit ils simplifient la structure des packages pour regrouper les classes en question. Cette stratégie est plus simple et fiable, mais ne fonctionne pas vraiment avec les API de type SPI (Service Provider Interface), qui ont vocation à être étendues par des tiers.

La JSR 294 introduit la notion de « superpackage » pour s’attaquer à ce problème. Les superpackages sont destinés à permettre une meilleure organisation interne d’un composant en comblant un trou dans les différentes visibilités fournies par le langage. Il s’agit d’un moyen d’organiser un module lors de la phase de développement. Cette JSR est souvent associée avec la JSR-277 : Java Module System qui propose un nouveau mode de packaging et de déploiement des composants d’un projet. Les superpackages introduisent un nouveau type de visibilité : plus large que ‘default (package)’ mais plus faible que ‘public’.

Les spécifications de cette JSR sont coécrites par Andreas Sterbenz (membre du « Java SE Security Group » chez Sun) et Alex Buckley (responsable des spécifications du langage (JLS) et de la machine virtuelle java Java VM Specification). Elles sont téléchargeables à cette adresse et sont présentées sous la forme d’une mise à jour des chapitres de la JLS impactés par ces modifications.

Un superpackage est décrit dans un fichier spécial appelé super-package.java. Celui-ci se décompose en 2 parties distinctes :

  • Une liste de membres (packages, classes ou superpackages) qui le composent.
  • Une liste des membres qu’il rend visibles depuis l’extérieur.

On peut voir les superpackages comme un regroupement virtuel de classes dont tous les membres bénéficient d’une visibilité mutuelle. La déclaration d’un superpackage se conforme à la syntaxe générale du langage en introduisant 3 nouveaux mots clé :

  • superpackage : un superpackage est une collection d’un ou plusieurs package ou superpackage. Les packages ainsi liés peuvent accéder directement à leurs classes et interfaces ‘public’ respectives. Pour que ces mêmes classes soient accessibles aux packages extérieurs, les types doivent être exportés.
  • member : les membres d’un superpackage sont les packages ou superpackages composant celui-ci.
  • export : un type (classe ou interface) est accessible à l’extérieur d’un package s’il est déclaré ‘public’. Un type est accessible à l’extérieur d’un superpackage s’il est déclaré ‘plublic’ ET qu’il est exporté par son superpackage. Les types exportés par un superpackage fils (membre d’une autre superpackage) sont accessibles dans le superpackage père.
jsr 294 superpackage

Exemple d’utilisation

Nous désirons mettre à disposition une liste d’interfaces contenues dans le package « fr.xebia.jsr294.sample1 » tout en masquant ses implémentations contenues dans le package « fr.xebia.jsr294.sample1.impl ». Ce dernier nécessite lui aussi des classes contenues dans un autre package « fr.xebia.jsr294.sample1.impl.misc ». En plus de cela, nous voudrions exporter notre classe utilitaire préférée par ce qu’elle est bien codée et qu’en plus on a passé du temps à la tester et que l’on en a envie de montrer notre savoir-faire… Euh, disons plutôt que nous voulons l’exporter à titre d’exemple …

Le schéma suivant détaille le contenu des différents packages de cet exemple, toutes les classes sont déclarées ‘public’ :

jsr294 packages

Et voici le contenu des fichiers ‘super-package.java’ :

Fichier : fr/xebia/jsr294/sample1/super-package.java
superpackage fr.xebia.jsr294.sample1 {
	member package fr.xebia.jsr294.sample1;
	member package fr.xebia.jsr294.sample1.utils;
	member superpackage fr.xebia.jsr294.sample1.impl;

	export fr.xebia.jsr294.sample1.utils.MyBeautifulUtils;
	export package fr.xebia.jsr294.sample1;
}

Fichier : fr/xebia/jsr294/sample1/impl/super-package.java
superpackage fr.xebia.jsr294.sample1.impl member fr.xebia.jsr294.sample1 {
	member package fr.xebia.jsr294.sample1.impl;
	member package fr.xebia.jsr294.sample1.impl.misc;

	export  package fr.xebia.jsr294.sample1.impl;
}

Quelques remarques

  • Un superpackage père référence ses superpackages fils et inversement. Le père doit maîtriser ses fils pour interdire qu’une classe externe vienne s’ajouter au superpackage.
  • Tout superpackage ne précisant pas de père se retrouve dans un ‘superpackage virtuel’.
  • Toute classe n’appartenant pas à un superpackage est visible dans ce même ‘superpackage virtuel’ (ceux qui ont suivi comprendront que ce ‘superpackage virtuel’ correspond à ce qui existe aujourd’hui).
  • Il est possible d’exporter un sous-ensemble des membres d’un superpackage, dans cet exemple seule la classe fr.xebia.jsr294.sample1.utils.MyBeautifulUtils est exportée alors que tout le package fr.xebia.jsr296.sample1.utils est membre du superpackage.
  • Du fait de l’emplacement des fichiers super-package.java, il ne peut exister qu’une seule définition de superpackage dans un package. Par contre, un package peut-être membre de plusieurs superpackage.

Comme à l’accoutumée, cette JSR possède son lot de détracteurs. Certains proposent de répondre à ce même problème en retournant la solution : au lieu de masquer ce qui est visible par l’intermédiaire d’une nouvelle boîte construite par un suc syntaxique plus ou moins élégant, il s’agirait d’annoter les classes et méthodes pouvant s’exporter (comme le décrit ce post). D’autres proposent l’ajout d’un nouveau mot-clé pour créer un type de visibilité ‘package et sous-packages’. Toute classe présente dans un sous-package serait visible dans le package père. Il ne s’agit pas du même problème : la version officielle distingue la visibilité (portée par un objet) de la modularité (portée par un système). Pour conclure, je vous laisse découvrir ce commentaire dans lequel l’auteur utilise des ‘static inner-classes’ pour simuler un superpackage.

Published by

Publié par Erwan Alliaume

Passionné par les technologies Java/JEE depuis sa sortie de l'EPITA, Erwan Alliaume est aujourd'hui consultant chez Xebia. Il intervient depuis 2 ans sur des missions de développement et d'architecture pour l’un des leaders mondiaux de la production et de la distribution de contenus multimédia. Expert technique polyvalent, Erwan a été amené très tôt à prendre des responsabilités sur des projets de taille significative. Il a notamment développé des compétences clé dans la mise en place de socle de développement, la métrologie et les audits de performance et de qualité. Erwan participe également activement au blog Xebia ou il traite aussi bien de sujets d’actualités que de problématiques techniques.

Commentaire

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Nous recrutons

Être un Sapient, c'est faire partie d'un groupe de passionnés ; C'est l'opportunité de travailler et de partager avec des pairs parmi les plus talentueux.