Une alternative à Java EE 5 : Essential Java


Pourquoi des
frameworks en Java ?

Le développement d’applications
d’entreprise en Java reste aujourd’hui une tâche complexe, nul besoin de le
nier. La cause profonde de cette complexité reste encore mal comprise et est
sujette à débat [1]. On peut toutefois, sans grand risque d’erreur, évoquer deux
raisons principales
:

  • A l’origine Java se veut une réponse globale à la
    grande hétérogénéité des contextes techniques et logiciels dans lesquels une
    application d’entreprise est susceptible d’être déployée. Inévitablement un
    coût en abstraction en résulte, puisqu’il s’agit de définir au moyen d’API les
    points communs entre catégories de systèmes (bases de données, moniteurs
    transactionnels, systèmes d’annuaires etc.…)
  • Ensuite, on remarquera que sur l’échelle de
    l’abstraction, une grande distance sépare la description d’un système
    d’information
    (en langage naturel ou en UML) du langage informatique utilisé
    pour le construire
    : Java en l’occurrence. Pour combler cette distance
    conceptuelle, de nombreuses API on été conçues depuis une décennie, chacune
    ayant son propre niveau d’abstraction et un champ d’application spécifique. Prise
    individuellement, chaque API reste simple. Cependant leur accumulation menace à
    terme de tuer la plateforme Java par excès d’obésité. Sun reconnaît d’ailleurs cet
    état de fait puisque l’objectif déclaré de la dernière spécification Java EE 5 était
    précisément d’en faciliter l’appréhension par le développeur néophyte. Cette nouvelle mouture de J2EE a-t-elle fait la preuve de sa simplicité ? En ce début 2008, rien n’est moins sûr.

Pour maîtriser cette complexité,
dans la communauté Java l’approche traditionnelle et a priori intellectuellement
séduisante procède typiquement en trois étapes. Pour mieux les critiquer, commençons par les rappeler.

 

  1. Une étape d’encapsulation du savoir-faire
    des experts en conception objet sous forme de design patterns
    ou d’algorithmes. Le résultat de cette démarche pour la technologie Java est le
    catalogue des J2EE Core Design Patterns [2].
  2. Ensuite l’implémentation de ces designs
    patterns ou des algorithmes dans des frameworks. Par ce terme
    on désigne un ensemble de classes Java, un ensemble de contrats à respecter
    ainsi que des fichiers de paramétrages. On peut concevoir un framework comme un
    canevas pour le développement d’une application ou pour une seule couche de
    l’architecture. Les plus répandus aujourd’hui sont probablement Struts
    (une implémentation du pattern MVC 2), Hibernate (une implémentation d’algorithmes de
    mapping Objet Relationnel), Spring (une implémentation du pattern d’injection de
    dépendance + une quicaillerie de composants hétéroclites). Le paramétrage des framework se fait dans un ou plusieurs fichiers
    XML.
  3. Enfin, cerise sur le gâteau, la construction d’éditeurs et d’assistants intégrés aux IDE sensés faciliter le paramétrage des framework, la construction
    des artéfacts et assurer le respect des différents contrats.

Les arguments couramment avancés
pour la mise en place de frameworks sont : réduction des coûts de
développement, simplification du développement pour les développeurs débutants,
augmentation de la qualité du code, facilité de maintenance due à l’uniformité
du code.


Les grandes idées à
l’épreuve de la réalité

Venons en au fait : l’expérience
montre que la réalité des projets J2EE vient souvent battre en brèche les
arguments théoriques que je viens d’évoquer ainsi que les espoirs mis dans les frameworks.
Ceci en dépit du talent et des excellentes intentions initiales de leurs concepteurs. A
cela, une raison principale à mon avis : l’absence de pérennité des
solutions.

Considérons à ce titre deux
exemples : les implémentations du pattern MVC et les solutions de
persistance.

Du côté MVC pour l’instant
aucun framework ne s’impose véritablement, ni Struts, ni JSF, ni Velocity, ni Shale
etc… Si le pattern MVC semble un concept naturel, stable et simple en revanche,
pour l’instant, aucune implémentation ne sort véritablement du lot.

En ce qui concerne les
solutions de persistance : ni les EJB entités 2.0 (avec ou sans XDoclet),
ni Hibernate, ni JDO, ni Toplink, ni probablement les EJB 3 (même muni des
annotations Java 5) ne constituent la panacée comme solution de persistance. En
revanche le pattern Data Access Object ainsi que les 3 ou 4 stratégies
standards de mapping O/R sont quant à elles stables depuis des lustres.

Mon propos ici n’est pas de
faire un constat pessimiste d’échec. Toutes ces expériences méritaient d’être
faites. Certaines ont d’ailleurs aboutis à des produits d’excellente qualité
comme Hibernate. Mon objectif est plutôt d’inciter à une prise de recul et de
susciter la réflexion, ceci douze ans après le lancement de Java.

D’aucuns prétendront qu’il faut
patienter encore quelques années, le temps que le darwinisme fasse son œuvre
dans le microcosme des API et des frameworks Java. Quant à moi, je pense qu’il est
temps de tirer les conséquences du fait que dix ans d’effort intensifs n’ont
pas suffit à faire émerger de solutions naturelles et universellement acceptées
à des problèmes élémentaires et récurrents de l’informatique de gestion tels que :

  • Comment
    gérer la persistance de grappes d’objets, je l’ai déjà évoqué.
  • Comment
    gérer les accès concurrents durant des transactions longues qui portent sur
    plusieurs pages web.
  • Comment
    assurer l’homogénéité des pages d’un site web et leur maintenabilité.

Un argument couramment invoqué
est que les problématiques telles la gestion des transactions, les accès
concurrents, le mapping objet relationnel sont des questions excessivement
complexes et relèvent d’une expertise pointue. Cette prétendue complexité m’apparaît
largement exagérée, j’y reviendrais. Ce qui est effectivement excessivement
complexe est la conception et le paramétrage d’une solution globale à un large
ensemble de problématiques. L’exemple caricatural de cette approche est celle
adoptée par les conteneurs d’EJB qui ambitionnent de résoudre simultanément
les problèmes de persistance, de sécurité, de transaction, d’accès concurrents
et de distributions des objets. Or il s’avère que la solution simultanée de
tous ces problèmes n’est que rarement requise dans la réalité.

En définitive, pour les
serveurs d’application comme pour la plupart des frameworks, l’intention initiale
de simplification globale se solde, pour le développeur, par un réseau complexe
et mouvant de contrats à respecter et, dans une moindre mesure, par la
construction d’une pléthore de fichiers de XML de paramétrage. Force est de
constater que, tout compte fait, le bilan de complexité de ces solutions apparaît bien souvent négatif. Le prix à payer pour respecter les contrats excède trop souvent la complexité encapsulée.

Plusieurs points viennent
renforcer ce constat.

Convenons qu’une condition
préalable à une productivité significative est la constitution d’une véritable
expertise technique. En effet pourquoi l’industrie du logiciel serait-elle
dispensée d’une règle commune à tous les domaines techniques et scientifiques ?
Envisageons donc la tâche consistant à assimiler un ensemble réaliste de
technologies. Pour fixer les idées disons : J2EE + Spring + Hibernate + Struts. A l’évidence cette
tâche n’est pas inhumaine mais elle nécessite, même pour une tête bien faite,
plusieurs années de pratique quotidienne. On le constate, cette durée excède de
loin la durée des dites technologies. Dans ces conditions le sempiternel
argument de réutilisation n’est plus qu’un leurre. De surcroit l’énergie investie
pour résoudre les incompatibilités et les subtiles différences entre les versions successives d’API, de
frameworks, d’assistants, l’est en définitive au détriment du développement
d’une saine intuition
des systèmes d’information.

L’immaturité chronique des IDE
avec leurs cortège d’assistants, éditeurs et vérificateurs de structure de
plus en plus complexes avec leur lot d’incompatibilités vient encore accroître la
lourdeur du développement. Cette complexité conduit inévitablement le
développeur à ne maîtriser qu’une infime fraction des fonctionnalités
disponibles (disons 10-20%) et à faire du bricolage.

La complexité induite par
un framework est particulièrement flagrante lorsque les développements sont
faits « en interne » et qu’une documentation technique appropriée

(JavaDoc digne de ce nom) fait défaut. Loin de simplifier quoi que ce soit, la
seule présence d’un framework induit alors un mode de transmission oral du
savoir-faire d’un ou deux experts transformés de fait en petits gourous. Mode
de transmission qui s’avère souvent redondant, confus et inefficace. Dans ces
cas de figure, le travail du concepteur d’une application s’apparente d’avantage
à celui d’un archéologue que celui d’un ingénieur.

L’utilisation aveugle de
frameworks présente d’autres effets plus sournois et trop souvent mésestimés. Je
pense par exemple à la perte de maîtrise d’un savoir-faire élémentaire de la
part des ingénieurs trop confiants dans l’encapsulation de toute complexité ou encore
à l’impossibilité pratique d’effectuer un choix en conscience parmi un éventail
de solutions. En effet, une comparaison objective de plusieurs frameworks relève
carrément de l’impossible lorsqu’ils sont déjà complexes individuellement. Dans
ces conditions un choix rationnel est difficile. Dans le meilleur des cas, des
considérations commerciales objectives l’emportent. Plus souvent l’idéologie et
le conformisme intellectuel naturel à l’esprit humain prennent le dessus.

 

Une alternative :
Essential Java

Trèves d’analyses
critiques, passons aux propositions. L’approche Essential Java que je
préconise est basée sur les conséquences que je tire de l’analyse précédente.
Les 5 principes de Essential Java sont les suivants :

Principe 1 :
Prenons au pied de la lettre l’argument de la
réutilisation.
Mais faisons le
de manière lucide en réutilisant ce qui est stable et donc justement
réutilisable. L’IoC, le MVC et le DAO sont de bons principes de conception
? Appliquons les explicitement ! Sans la béquille d’un framework. Ce qui
est stable ce sont quelques patterns, quelques algorithmes et quelques API Java
à choisir judicieusement. Ce ne sont certainement pas les frameworks avec leurs assistants et leur lot d’incompatibilités. « Essential Java
= zéro framework ».

Principe 2 : Reconnaissons objectivement que beaucoup de
problèmes récurrents
(la gestion des transactions, la persistance,
l’organisation d’un MVC) possèdent des solutions raisonnablement simples
et documentées qu’il est possible de coder explicitement sans
introduire de couche d’abstraction supplémentaire.

Principe 3 :
Constituons une librairie d’exemples explicites
pour chacun de ces problèmes. Un code de qualité
exemplaire et parfaitement commenté devra être fourni par les experts. Un
exemple de ce que j’ai à l’esprit est incarné par les excellents livres de
David Flanagan : [3, 4]. A la différence des frameworks qui sont
essentiellement des boites noires ces morceaux de code seront des boites
blanches adaptables.

Principe 4 :
Enonçons un ensemble
d’API Java,
de design patterns et de savoir-faire que tout le monde
s’accordera à considérer comme incontournables. Je vous
proposerai mes propres suggestions ci-dessous.

Principe 5 : Enfin, faisons davantage confiance au développement
progressif d’une expérience, d’un savoir faire plutôt qu’à la foi naïve selon
laquelle l’encapsulation de la complexité constitue la solution définitive à
tous les maux de l’informatique.

Les esprits chagrins considèreront
peut-être une telle approche comme antinomique avec le principe fondamental de
la réutilisation. Bien au contraire ! La réutilisation sera alors enfin
possible grâce à la stabilité. Un point central d’Essential Java est
qu’il est conçu pour être maîtrisable à 100% par chaque développeur. Ceci favorisera
parmi ses adeptes l’émergence d’une authentique culture de la qualité qui
replacera à mon sens avantageusement la culture gadget-plugin.

Essential Java est définit par trois catégories d’exigences.

API essentielles

Le principe 1
interdit l’utilisation de tout framework autre que les API Java du J2SE ainsi qu’une courte sélection d’API J2EE incontournables. Je
propose de figer le SDK au niveau J2EE 1.4 pour deux raisons. D’une part
ni Java EE 5 ni J2SE 5.0
n’apportent pas d’améliorations significatives et aucune simplification.
D’autre part J2EE 1.3 ne possède aucune API pour la construction de
WebServices.

Le principe 4 me
conduit à proposer la liste suivante d’API :

L’API des Servlets (javax.servlet.http). Elle constitue naturellement le fondement
indispensable à la construction d’un contrôleur du pattern MVC ainsi que la
notion incontournable de session utilisateur dans une application web.

Les pages JSP (javax.servlet.jsp) permettent de construire les pages en contient la
quincaillerie pour confectionner des librairies de balises personnalisées.

La librairie
« Core » de la JSTL
(http://java.sun.com/jsp/jstl/core) qui contient la logique conditionnelle (tests
« if » et boucles « for ») commune à tout langage de
programmation.

Les 2 API JDBC et
JNDI
dont la justification
est à peine nécessaire. La première permet l’accès aux SGBDR, la seconde fait
partie du fondement de l’architecture J2EE et donne accès aux systèmes d’annuaires.

Le modèle de sécurité
J2EE
avec les notions de
Principal, de rôle J2EE et de permission. La sécurité est un sujet
authentiquement délicat et complexe qui ne doit en aucun cas être réinventé.
Paradoxalement, cet aspect de Java reste encore trop souvent méconnu alors
qu’il s’agit d’un véritable atout de la plateforme J2EE [5]

Enfin JAX-RPC (javax.xml.rpc) pour la construire de clients de WebServices. Il
s’agit d’une API rudimentaire intégrée aux API J2EE 1.4 qui remplacera
avantageusement les API propriétaires.

Un code source Java qui se
conforme pleinement à cette liste d’API peut être estampillé 100% Essential
Java
conçu comme un label de qualité applicable à tout ou partie d’un code.

Savoirs essentiels

Le pattern MVC,
les patterns factory, le pattern DAO. Il
s’agit la de principes organisationnels incontournables et pérennes.

Les 3 principales stratégies
de mapping objet/relationnel [6 chap. 8].

Le principe de séparation
des couches
de présentation, métier et de persistance. Là encore il
s’agit d’un principe qui n’est guère remis en question depuis des années.

Un mécanisme pour garantir l’uniformité
des pages
. Quelle application professionnelle saurait s’en
passer ? [7 chap. 9]

La notion d’accès concurrents
caractérise l’informatique d’entreprise. Les deux stratégies de gestion
optimiste et pessimiste des accès concurrents
sont indispensables à
connaître [6 chap. 10].

L’utilisation du pattern
Decorator pour gérer explicitement un contexte transactionnel.
[6 chap. 10].

Un mécanisme de lazy
loading
. C’est un mécanisme à la base qui permet la solution des
problèmes de performances due aux longues listes d’objets.

Outils essentiels

Cette dernière catégorie
d’exigence est plus délicate à formuler pour
la simple raison qu’actuellement aucun IDE J2EE ne sort du lot. Une note
d’optimisme est toutefois permise dans la mesure ou la plateforme Eclipse
est à la fois bien conçue, robuste et flexible. En conséquence je préconise
l’utilisation d’outils adaptés à la tâche raisonnablement simple qui consiste à
éditer des fichiers Java, XML et JSP ainsi qu’un outil d’intégration continue

comme Maven. C’est tout !

 

Conclusion

Il y a quelques années j’ai
personnellement souscrit pleinement à l’approche par framework. Cependant la
réalité des projets J2EE dans lesquels j’ai été impliqué m’a incité à remettre en cause cette conviction. Mon intention ici n’est pas la polémique mais plutôt de
susciter un débat qui me semble opportun plus de dix ans après la création de Java.

Loin de moi l’idée d’arrêter
la marche du progrès, quelle horreur ! Mais plutôt d’en proposer une
nouvelle définition. Tout du moins dans le domaine de la conception
d’applications d’entreprises à l’aide des technologies J2EE.

D’autres approches plus radicales que celle proposée dans ces lignes sont sans doutes envisageables. L’une d’elle pourrait consister à redéfinir un ensemble approprié d’abstractions nouvelles (DSL), enfin libérés de ce qui est devenu un forme de pensée unique : « la programmation objet ». A cette approche radicale, du ressort d’un cellule R & D d’un grand éditeur ou d’un labo de recherche de l’INRIA, celle que je propose dans ces lignes présente à mes yeux l’avantage d’être applicable immédiatement dans la réalité des projets.

Ma conviction est que dorénavant le
progrès dans notre métier résidera moins dans la course sans fin à l’encapsulation qu’à la
réhabilitation de certains principes trop longtemps oubliés par la communauté Java :
la sobriété, la concision et la maîtrise complète d’un nombre limité de savoir-faires
incontournables. Tel un artisan, au sens noble du terme, qui maîtrise pleinement son métier, le concepteur pourrait alors enfin se concentrer sur sa
tâche essentielle : construire des systèmes d’information qui répondent
aux besoins des utilisateurs.

 

Bibliographie

[1] Envisioning a New Language, Victoria Livschitz, décembre 2005 :
http://java.sun.com/developer/technicalArticles/Interviews/livschitz2_qa.html
[2] J2EE Core Design Patterns : http://java.sun.com/blueprints/corej2eepatterns/index.html
[3] Java Examples in a Nutshell, David Flanagan, O’Reilly 2004.
[4] Java Enterprise in a Nutshell, David Flanagan, O’Reilly 2005.
[5] Sécurité des Architectures Web, G. Plouin, J. Soyer, M.-E. Trioullier, Dunod 2004.
[6] J2EE Design Patterns, William Crawford, Jonathan Kaplan, O’Reilly 2003.
[7] Java Enterprise Best Practices, The O’Reilly Java Authors, O’Reilly 2003.