Ambitions
Un Atelier de Génie Logiciel, tel qu'il est
"conçu" depuis des années, se doit de
prendre en charge
toute la chaîne de production d'un logiciel,
depuis la rédaction et le maintien en cohérence
des différents documents préliminaires au code
(cahier des charges, spécification,
conception,...), jusqu'à la rédaction et la
mise en uvre de jeux de tests, ou encore de
compte-rendus de recettes et de livraisons, en
passant par le codage et sa gestion de
configuration.
!!!...
Cela regroupe clairement plusieurs métiers :
- GDE (Gestion de
Documents Electroniques, pour les documents de
spéc'),
- Gestion de conf'
(gestion de configuration pour maintenir des
livraisons de code stabilisé et
"public"),
- Gestion de projet
(avec toute la traçabilité que cela implique,
en terme de suivi des faits techniques - ou
corrections de bugs - par exemple).
Les quelques logiciels qui se sont
attelés à cette titanesque tâche se sont tous
révélés trop coûteux et trop lourd à mettre
en uvre (jusqu'à aujourd'hui, 1999).
Réalité
Pour l'instant, les
AGL auxquels vous serez certainement confrontés,
développeur junior que vous êtes, possèdent
les caractéristiques suivantes :
- un éditeur de notation
de modélisation (normalement UML -
Unified Modeling Language),
- un générateur de code
issu de votre modélisation,
- un générateur de
documentation extrayant automatiquement
les bouts de doc associés à vos divers
composants (objets, diagrammes, ...)
- un module de reverse
engineering (Java car le langage s'y
prête bien, plus rarement C++ car le
"reverse" demeure plus compliqué)
Bref, il s'agit d'un "ersatz" d'AGL, un
véritable "sous-extrait", mais dont la
puissance actuelle des machines à bas coût (PC
standard) permet une exploitation efficace.
Car ne nous y trompons pas : derrière ces
quelques fonctionnalités centrées autours du
codage se cachent des enjeux capitaux si l'on
veut réaliser efficacement et rapidement un code
objet de qualité (c.à.d. fiable, robuste,
maintenable voire même réutilisable).
Parmis les principaux enjeux, en voici 4 qui
conditionnent particulièrement la vie du
programmeur de tous les jours.
Comme mentionné en introduction, ces "enjeux" sont
indépendants de la notion d'AGL, mais ce dernier
permet de faciliter considérablement leur mise
en uvre.
Cohérence modèle-code
S'il ne devait y avoir qu'une
raison majeure en faveur de l'utilisation des ces
"petits AGL", ce serait celle-là.
Cette
cohérence découle de la capacité d'un AGL à
générer plusieurs fois le code d'une classe
sans en écraser le corps des fonctions déjà
écrites. Ainsi, pour rajouter un
attribut, ou changer la signature d'une fonction,
le développeur passera systématiquement d'abord
par son AGL, générera le code correspondant
avant d'en modifier le contenu dans son éditeur
préféré.
Cette nouvelle façon de travailler utilise la
notion de vue
architecturale. Elle est primordiale, dès que le projet dépasse les
"20" classes, ou dès qu'il utilise des
packages (ensemble fonctionnel cohérent de
classes) provenant d'autres équipes.
En effet, dans les phases de
codage, il n'est pas rare d'amorcer un second
cycle de spécification - conception. En clair :
le bô modèle initialement envisagé nécessite
d'urgence des modifs afin d'être (plus facile à
coder) (mieux modélisé) (etc.). Or ces modifs, si
elles interviennent directement dans le code,
sont perdues pour le modèle.
Les programmeurs suivants, qui se chargent de
maintenir et/ou faire évoluer le code existant
n'auront, pour toute documentation, qu'une série
de .h et de .cpp (pour le C++, par ex.) à partir
desquels ils doivent reconstituer les concepts et
principes de modélisation choisis... C'est plus
qu'hasardeux!
D'autant que les concepts sont très importants
dans le développement d'un code efficace et
constituent le deuxième grand enjeu de
cet AGL : |
Mettre en
avant les concepts
Les mettre en avant
par rapport à quoi : à l'implémentation. Il
s'agit de masquer
l'implémentation.
(certes, on ne la masque jamais complètement,
mais on peut la rendre suffisamment
"discrète" pour se concentrer d'abord
sur les concepts, comme le montre l'exemple
suivant).
Un exemple simple et typique est
une association 1-n entre deux classes A et B.
Vous pouvez choisir, dans votre modèle UML, de
représenter cette association selon la première
figure.
Les désavantages sont :
- vous ne mettez pas en évidence le lien
conceptuel entre A et B (il faut bien regarder A
pour découvrir, parmi ses - potentiellement -
nombreux attributs, qu'un vector de pointeurs sur
B s'y cache!
- vous affichez clairement
("std::vector") une implémentation
dont : 1/ on n'a que faire, 2/ le choix peut
être remis du jour au lendemain (pourquoi
toujours la librairie stl ? pourquoi un vector et
pas une list ou un set ? etc.)
La deuxième figure a l'avantage de
mettre en avant l'essentiel :

|
- Le concept de A ne peut exister sans B :
couplage fort mono-directionnel.
- A possède une association vers B (ce qui veut
dire que A peut disparaître sans entraîner la
destruction de B)
- les B sont accessibles (+mes_B = il existe un
accesseur public vers cette collection
d'élément).
Il appartient au programmeur de spécifier cette
association (en double-cliquant sur la flèche)
pour en préciser le mécanisme d'implémentation
choisi : si ce dernier évolue, le modèle n'en
n'est pas affecté et sa
compréhension globale reste centrée sur
l'essentiel : "qui connaît quoi" (et
pourquoi, mais certainement pas comment).
Organiser les dépendances
"Qui connaît
quoi"... parlons-en justement. Une fois les
concepts bien identifiés - jusqu'aux classes -
il s'agit de bien représenter, via un AGL
adéquat, les dépendances qui existent entre
classes et celles qui existent entre packages.
Il n'y a qu'à relire mes remarques
sur l'importance du couplage (aussi bien en analyse,
en conception,
en codage
et en test)
pour s'apercevoir qu'un AGL a aussi pour fonction
essentielle de bien mettre en évidence ces
dépendances.
Dès qu'un projet est découpé en
packages plus ou moins importants, ceux-ci
deviennent à terme des librairies développées
par des personnes différentes, chacune faisant
évoluer sa ou ses librairies à son rythme.
Afin d'éviter des crises de nerfs
inutiles, il est alors
indispensable de voir au premier coup
d'il, en regardant un modèle, quelles sont les sous-parties qui
utilisent la librairie qui vient de bouger le
matin-même : ces sous-parties risquent de
devoir être mises-à-jour d'urgence, parce
qu'elles sont elles-même utilisées par 3 autres
équipes de développeurs!...
Dans le même ordre d'idées, il est important de faire des
packages stables
(dont l'interface des classes publiques ne
variera pas ou peu), et de faire en sorte que les packages moins stables, les
plus susceptibles d'évoluer, utilisent les
premiers (et non l'inverse!).
Parler «interface»
"Les classes
publiques [d'un package]"... L'AGL est
également idéal pour bien faire
ressortir les classes destinées à être vues
par d'autres packages de celles qui
apportent une fonctionnalité purement interne
et/ou utilitaire.
Le fait de raisonner de cette façon a une grande
importance sur l'évolutivité et la maintenance
de votre code.
Autant d'enjeux peu visibles lorsque l'on ne fait
qu'effleurer un projet mais qui deviennent vite
cruciaux dans une démarche à plus long terme,
au sein d'une équipe à l'esprit critique et
alors que plusieurs personnes font évoluer un ou
plusieurs modules communs!
Donc, si vous utilisez un AGL.... pensez à ces
quatre derniers points.
|