Antéo TIS du 06/07/2012

Vendredi 6 juillet a eu lieu notre rendez-vous quasi mensuel d'échange et de partage au sein de l'équipe Antéo : Antéo TIS (Team Improvement Session).

Cette journée d'échange est l'occasion pour tous les consultants Antéo de se retrouver tout d'abord autour d'un café 😉 puis le reste de la journée autour d'une table pour échanger autour de différents sujets comme le métier consultant, les méthodologies ou des sujets plus techniques.

SI international ENERGY POOL – Témoignage client

Opérateur en modulation d'électricité (Demand Response), Energy Pool agrège les gros consommateurs d’énergie pour valoriser leur capacité à moduler leur consommation à des heures critiques pour le réseau électrique grâce à ses centrales de modulation. Société Française, Energy Pool pilote aujourd’hui une centrale de modulation de 1000 MW de capacité (1er opérateur européen) et se déploie actuellement à l’international.

Modélisation des besoins et MOA

Le premier billet sur la modélisation a voulu démythifier cette activité mal perçue dans le monde informatique. Ce deuxième billet se focalise sur l’activité essentielle du développement logicielle qu’est l’expression du besoin et met en perspective comment la mauvaise compréhension de l’acte de modélisation lui est fortement préjudiciable.

Démythifier la modélisation

Au cours de mes expériences en tant  qu’architecte, qu’AMOA ou au sein de département méthode, j’ai été frappé par la mauvaise perception que l’on a de la notion de modélisation dans les équipes informatiques.

Pour beaucoup la modélisation est une activité à part qui fait peur (on pense que c’est une activité difficile réservée à des experts) et qui apporte un surcroît de travail pour obtenir un hypothétique gain en qualité dans le développement des systèmes informatiques.

Eclipse 3.7 « Indigo » : Vos voeux seront-ils exaucés ?

Comme tous les ans à la même époque, la nouvelle version d'Eclipse vient de sortir. Son  nom de code : "Indigo".

Cette année, Eclipse met l'accent sur trois axes que sont le développement Java d'une part, la modélisation d'autre part et enfin l'intégration (outils surtout axés ALM [Application Lifecycle Management] cette année).

Du côté de Java, on trouve des avancés intéressantes et significatives :

  • WindowBuilder un édtieur d'IHM (Swing, SWT, RCP, XWT et GWT) : Eclipse tente de rattraper son retard au niveau du design d'IHM client riche/web comparé à d'autres IDE comme Netbeans et surtout IntelliJ d'IDEA.
  • Un outil pour réaliser des Tests Fonctionnels : Jubula. Une preuve que les tests de non régression et aussi le développement piloté par les tests d'acceptance sont des mouvances actuelles.
  • Développement RIA (RAP) avec Reina 3.0. Dans la droite ligne du dernier séminaire ANTEO sur les RIA (voir ici), il est clair que cette technologie succite l'intérêt de la communauté RIA.

Du côté des outils et de l'Application Lifecycle Management, Eclipse n'est pas en reste :

  • Intégration de Maven, qui était très attendue, comme en témoigne le forum du plugin M2eclipse. Ce plugin est désormais intégré dans Eclipse mais le résultat est décevant. En dehors du fait qu'il n'est pas intégré dans la version Java EE d'Eclipse, il y a encore du chemin à parcourir sur ce plan avant d'être à la hauteur de nos attentes.
  • Intégration de Git au travers du plugin EGit 1.0. Concurrent avéré de SVN, les développeurs/sociétés qui souhaitent passer de SVN/CVS à git seront ravis.
  • Un outil de revue de code Gerrit, très utile d'autant plus qu'il est très bien intégré avec la notion de revue bloquante/non bloquante. Complémentaire ou opposé à la notion de Pair Programming des méthodes agiles, à vous de juger (voir cet article).
  • Intégration de Mylyn 3.6La toute dernière version de Mylyn clairement orientée ALM, apporte elle aussi son lot de nouveautés (une meilleure gestion des contextes (consultation, modification, merge..), une intégration avec Hudson,Bugzilla ou encore Gerrit).
  • Le support des bases de données NoSQL

Du côté de la Modélisation, c'est surtout EMF qui bénéficie des dernières évolutions :

  • Support des langages DSL via Xtext 2.0
  • EMF 2.7, nouvelle version du framework de modélisation et de génération
  • EMF Compare 1.2 (comparaison de modèles EMF)
  • EMF Facet pour étendre les méta-modèles

En conclusion, vous bénéficierez de quelques précieuses nouveautés mais c'est clairement une déception quant à Maven avec l'intégration "inachevée" de M2Eclipse, ce qui en fait une limite majeure d'Eclipse comparé à Netbeans ou IntelliJ pour les développeurs Java EE !

Estimation pilotée par les modèles

L'estimation du coût logiciel reste une question importante de gouvernance du SI, puisqu'il s'agit de calculer une charge prévisionnelle avec précision.

La vraie question de décision n'est pas cependant dans l'estimation brute d'un chantier monolithique, mais plutôt dans la capacité d'évaluer les variations de charge en fonction des options du projet. Dans une approche itérative, l'estimation d'une charge pour chaque version successive représente également un véritable élément de décision pour choisir le meilleur chemin d'avancement et mieux maîtriser les risques par les coûts.

En conséquence de quoi, la possibilité d'évaluer les impacts d'évolution ainsi que la traçabilité entre les choix d'un projet et ses charges pondérées représentent un prérequis au pilotage agile des évolutions de son SI.

Back to basics : l’état stable du SI, épisode 1

En programmation orientée objet (POO), la conception d’un système d’information se ramène à la définition d’objets et de leurs interactions. Les langages informatiques objet actuels sont principalement basés sur un modèle de classe/instance (par exemple java ou C#...) ou sur un modèle de prototype (javascript).

Nous nous placerons dorénavant dans la perspective d’une implantation de type classe/instance.

Depuis 1994, l’utilisation d’une méthode standardisée de modélisation : UML (Unified Modeling Language) s’est généralisée. UML permet la modélisation statique et dynamique d’un système d’information.

En théorie, développer une application consisterait simplement à mapper cette modélisation sur une infrastructure technique (et plus généralement sur un modèle de classe/instance).

En réalité, la modélisation est généralement soit incomplète, soit inutilisée (ou simplement pas mise à jour au cours du projet : l’implantation et la modélisation initiale sont alors désynchronisés). Cela est d’ailleurs encore plus vrai pour la modélisation dynamique. Ainsi, si UML comporte un langage spécifique, l’Object Constraint Language (OCL) pour modéliser les comportements dynamiques (les méthodes), il reste très peu utilisé. OCL permet pourtant de définir des préconditions et postconditions sur des méthodes et même de modéliser les calculs effectués par ces méthodes.

En ce qui concerne la modélisation statique du système, elle reste tout de même la plus utilisée, plus précisément sous sa forme des diagrammes de classes. Les diagrammes de classes UML représentent l’état statique du système qu’ils modélisent sous forme la forme de définition des classes, de leurs attributs et de leurs relation. Ces diagrammes sont couramment utilisés pour définir l’implantation « statique » des classes (attributs simple et dérivés, associations…).

Lorsqu’on conçoit l’implantation, il est nécessaire de s’interroger sur les moments où les contraintes portées par la modélisation statique sont vérifiées. En effet, il est rare de pouvoir assurer à chaque instant le respect de toutes les contraintes portées par le modèle. Ce problème se pose en effet durant tout le cycle de vie de l’objet comme le montrent les exemples suivants.

Considérons une classe Personne, comportant les champs obligatoires nom, prénom, sexe, date de naissance

Exemple 1 : instanciation et attributs obligatoires

Pour respecter la contrainte statique concernant le caractère obligatoire de ces champs, il est nécessaire de renseigner tous ces champs obligatoires dès l’instanciation de l’objet.

Dans un langage objet à constructeurs, comme java, il serait donc nécessaire que le constructeur comporte comme argument l’ensemble des valeurs des champs obligatoires. Dans une application interactive, par exemple une application web, cela impliquerait de ne pouvoir créer une instance de Personne qu’après la saisie de toutes les valeurs permettant d’initialiser ces champs. Par ailleurs, cela impliquerait immédiatement de ne pas respecter la convention javabean concernant les constructeurs sans argument.

Exemple 2 : instanciation et contraintes sur les associations

Si la modélisation de la classe Personne comporte une relation de composition obligatoire (cardinalité 1..1) vers une instance d’Adresse (modélisant « toute personne possède obligatoirement une et une seule adresse »). Il serait nécessaire que le constructeur de la classe Personne prenne également comme argument une instance d’Adresse déjà créée.

Exemple 3 : instanciation et contraintes sur des références formant un cycle

Imaginons que la classe Personne définisse une association enfants et une association parents, comment pourrait on initialiser correctement le cycle formé par les parents et leurs enfants pour respecter une contrainte statique du type « si une Personne p1 possède un enfant, cet enfant a p1 comme parent » ?

Exemple 4 : modification de l’objet et maintien de sa validité

soit une classe dont la modélisation statique comporte :

  • un attribut situationMaritale pouvant prendre des valeurs telles que « marié », « célibataire », « pacsé »,
  • une association « conjoint ».

La modélisation peut légitimement imposer que « si situationMaritale est "marié" ou "pacsé", l’association conjoint doit être obligatoirement renseignée ». Dans ce cas, même si l’objet personne est dans un état valide avant, l’utilisation d’un accesseur comme setSituationMaritale met temporairement l’objet dans un état invalide (tant que l’accesseur setConjoint n’a pas été utilisé).

Pour respecter la contrainte de validité, il serait donc nécessaire d’utiliser des méthodes modifiant simultanément tous les champs sur lesquels porte une même contrainte. Dans l’exemple précédent, il y a plusieurs solutions telles que la création setSituationMaritaleEtConjoint ou plus vraisemblablement plusieurs méthodes telles que setConjointMarié, setConjointPacse, setCelibataire… Noter qu’en java, le respect de la validité à tout instant imposerait par exemple de ne pas utiliser la convention javabean sur le setter (qui précise que chaque propriété pouvant être modifiée doit être accompagnée d’un setter publique nommé setXXX si XXX est le nom de la propriété).

Si l’on veut généraliser ce mécanisme (et éviter de créer des méthodes ad hoc pour chaque sous-ensemble de contraintes à vérifier), il faudrait envisager de mettre en place un setter global (comme setState) prenant comme argument l’ensemble des valeurs permettant de modifier l’objet. Si un tel setter global échoue, il est facile de laisser l’objet dans son état valide antérieur.

On peut bien sûr objecter que l’invalidité temporaire de l’objet n’a aucune importance si cette invalidité n’est pas observable. En effet, en l’absence de multi-threading, l’objet ne peut pas être observé quand il est modifié, même si cette modification consiste en une succession de modifications atomiques de propriétés. Par contre, dans une application multi-threadée, et par exemple dans toute application web J2E, ce n’est plus le cas. Le multi-threading peut en effet interrompre librement toute séquence de modification.

Il y a plusieurs façons d’éliminer le problème tout en conservant la notion d’état « valide » de l’objet :

  • relaxer les contraintes portées par l’implantation objet,
  • n’assurer ces contraintes que dans certains états spécifiques (par exemple, on n’assurerait pas que les contraintes de cardinalité minimales soient vérifiées constamment. C’est d’ailleurs ce que précise l’OMG - l’organisme en charge de la normalisation d’UML - : lorsqu’on fait porter à une relation une cardinalité minimale, cette contrainte de cardinalité ne doit être assurée que lors d’un état stable du système).

Dans le premier cas, l’implantation objet ne garantit que des contraintes plus faibles que celles portées par le modèle… mais le système d’information doit quand même vérifier ces contraintes statiques dans son état « le plus stable », c'est-à-dire en persistance (hors transaction et verrous). Autrement dit, l’implantation objet ne doit assurer la « validité réelle » de l’objet que lors de l’écriture de l’état persistant de l’objet. Dans ce cas, seule la forme persistante assure le respect des contraintes portées par la modélisation objet UML. Il n’est donc pas nécessaire d’utiliser des informations portées par les classes modélisées, cela peut être réalisé directement par du code.

Dans le second cas, la conformité au modèle statique est assurée par l’implantation objet, mais seulement à certains moments.

On pourrait objecter qu’on code des applications web J2E tous les jours, en quoi cette notion d’état valide « conforme à la modélisation » devrait elle nous influer ?

Et d’abord, dans la « vraie vie », comment çà se passe ?

En caricaturant, on pourrait discerner plusieurs types d’implantation :

Beaucoup d’implantations « minimales »

Dans ce type d’implantation, les seules contraintes statiques assurées sont celles portées par la définition même des classes. Dans un langage typé statique (comme java), il s’agit juste d’assurer le type des variables d’instance, éventuellement le caractère readonly des variables d’instance (en ne mettant pas de setter sur la v.i.). Dans un langage non typé, les contraintes statiques se traduisent dans la structure de la classe (ces variables d’instances).

Le respect des types de relations (et par exemple des relations de composition) est souvent mis en place sous forme de traitements spécifiques.

En fait, le respect des contraintes lors de l’écriture en persistance est assurée par un code ad hoc ou les vérifications standards assurée par l’outil de mapping.

Quelques implantations évoluées

On rencontre aussi des implantations plus java complètes des contraintes statiques portées par le modèle, par exemple en utilisant une implantation de la JSR 303 « bean validation » et des annotations comme @NotNull.

Dans les articles suivants, nous étudierons des solutions pratiques permettant d’améliorer la qualité de l’implantation objet tout en facilitant sa maintenance. Il s’agit de renforcer le respect des contraintes statiques et dynamiques de l’implantation objet et par exemple de garantir à tout instant que les objets conservent un état valide. Cela implique par exemple que tout appel à une méthode publique est du type « transactionnel » et se traduit toujours par un état valide des objets. Par ailleurs, il serait aussi souhaitable d’alléger la programmation des méthodes elles mêmes en facilitant la vérification de la validité des paramètres qui leurs sont passés.

Le prochain article portera donc sur la mise en œuvre en java du Design by contract défini par Bertand Meyer pour la conception du langage Eiffel.

Cela nous amènera à étudier l’impact - sur l’ensemble du cycle de vie des objets - des notions d’invariants de classe, préconditions et postconditions :

  • à la création de l’objet,
  • lors des modifications successives de l’objet (comment assurer le respect de contraintes statiques alors qu’un objet est en cours d’édition ?),
  • lors de sa persistance,
  • lors de son utilisation simultanée par d’autres « clients » (en local via multi-threading, en utilisation « remote », dans son état persistant et objet…).

Nouvelle version de UML en cours…

Logo UML Pour ceux qui ne le savent pas encore, UML (Unified Modeling Language : langage de modélisation unifié) est un langage international qui évolue, qui s'enrichit de nouveaux diagrammes à chaque version...

L'association américaine OMG (Object Management Group et non pas "Oh ! My God !" comme on pourrait le croire...) diffuse depuis Novembre 2007 la version UML 2.1.2, et travaille à présent sur la version 2.2.

Les spécifications UML de la version 2.1.2 sont disponibles sur http://www.omg.org/spec/UML/2.1.2/.
Elles sont divisées en deux parties complémentaires : la partie Infrastructure et la partie Superstructure. La partie Infrastructure définit les éléments de base du langage, tandis que la partie Superstructure définit les éléments utilisés par les plus confirmés. Il est conseillé de commencer par la partie Infrastructure si vous souhaitez en savoir plus sur le sujet.

Bonne lecture !