Nous avions récemment abordé le sujet des assertions
dans le cadre des nouveautés du langage Java, en expliquant
qu'elles faisaient partie intégrante d'une méthode de conception
Objet nommée "conception par contrat" (ou programmation par
contrat), venue du langage Eiffel et depuis implémentée dans
de nombreux langages.
Présentation
Le terme "contrat" tient au fait que cette méthode établit
une relation de confiance entre une classe et le code qui
l'utilise, tout comme un grand distributeur peut avoir un
contrat qui spécifie sa relation au client. Ce contrat établit
certains droits et obligations pour chaque partie, et le contrat
ne tient que si les deux parties le respectent à la lettre.
Dans
la programmation par contrat, cela signifie que classe et
"clients" répondent chacun aux conditions de l'autre, à la
fois au début de la relation (le client doit fournir des éléments
précis à la classe) et à sa fin (la classe doit garantir certaines
propriétés). Ainsi, cette méthode permet au développeur de
spécifier précisément et explicitement (c'est-à-dire directement
dans le code source) les contraintes à tenir avant et après
l'exécution d'un composant. Notre contrat nous permet de savoir
à quoi nous pouvons nous attendre quand nous utilisons une
classe.
Mais la programmation par contrat reste plus vaste que la
simple mise en place de quelques assertions ici et là. Plus
que de permettre de préciser que telle valeur doit être positive,
la métaphore du contrat permet d'organiser les échanges entre
les divers composants d'un programme, leurs obligations mutuelles
et les bénéfices de ces échanges. Le développeur ne devine
plus ce que devrait produire tel composant ; il sait, parce
qu'il l'a spécifié dans le code, qu'il ne peut réagir que
d'une manière donnée.
En pratique
Concrètement, le code doit donc remplir trois sortes d'expressions
: préconditions, postconditions, et invariants.
Précondition : le composant qui appelle une méthode
de la classe doit passer des paramètres qui remplissent certaines
conditions. Cela permet de vérifier si l'objet dispose des
bonnes valeurs pour son travail. Ces conditions sont logiquement
évaluées avant même que les arguments ne soient passés à la
méthode.
Si la condition échoue, c'est que le composant client comporte
un bug, à corriger avant toute chose.
Exemple : telle valeur doit être positive pour que
l'on puisse en calculer la racine carrée.
Postcondition : la méthode de classe appelée doit
renvoyer un résultat qui correspond aux attentes du composant
appelant. Elles sont évaluées une fois accompli le travail
de la méthode appelée.
Si la condition échoue (alors que les préconditions ont été
remplies), un bug est à corriger au sein même de la méthode.
Exemple : la valeur retournée doit correspondre à la
racine carrée.
Invariants : en plus des deux expressions précédentes,
qui ne s'appliquent qu'à une méthode donnée, tous les objets
inclus dans l'échange doivent être laissés dans le même état
entre le début et la fin de celui-ci. Ces conditions peuvent
être vérifiées à tout moment, et permettent de s'assurer que
le système entier conserve une certaine uniformité (et que
l'on évite donc les effets de bords disgracieux).
En cas d'effet de bord, un bug se trouve soit dans la méthode
de la classe, soit dans le composant client.
|
Forum |
|
Réagissez
dans les forums
de JDN Développeurs
|
En définitive, réaliser un tel travail en amont permet non
seulement de détecter plus rapidement les erreurs de conception,
mais également, grâce aux invariants, celles liées à l'exécution.
En cela, il s'agit d'un excellent complément aux tests
unitaires.
La programmation par contrat consiste donc en une méthode
de développement très robuste, autorisant la définition de
l'état d'un objet avant et après son exécution, tout en surveillant
le reste du système. En plus de parvenir à du code solide,
cette méthode oblige le développeur a penser plus en amont
sur ses spécifications et les implications de ses choix, ce
qui a terme lui permet de mieux maîtriser sa création.
|