« La qualité constitue sûrement lun des enjeux majeurs du développement logiciel. Plusieurs techniques adaptées à la programmation orientée objet ont été imaginées pour sassurer de cette qualité. Si leXtreme Programming a popularisé lutilisation des tests unitaires, Bertrand Meyer, quant à lui, a proposé depuis longtemps la mise en uvre de la notion de contrat.
Cette technique on lappelle Design by contract ou programmation par contrat consiste à exprimer les spécifications des composants logiciels sous la forme de contrats et à vérifier en permanence le respect de ces derniers.
Après avoir présenté les principes du Design by contract, nous nous intéresserons à sa mise en uvre dans des langages comme le C++, Delphi ou Java. Par ailleurs, nous montrerons pourquoi cette technique est complémentaire des tests unitaires préconisés par XP. »
Les développeurs finissent parfois par oublier que ce que l'on attend d'eux, c'est de produire des logiciels de qualité. C'est-à-dire des logiciels sans bugs. Qu'est ce qu'un bug ? un bug est une erreur dissimulée dans un programme, nuisible à son bon fonctionnement. Ce qui signifie que l'on est en présence d'un bug lorsque le programme ne se comporte pas comme il devrait le faire, comme nous avions spécifié qu'il devrait se comporter. Nous allons découvrir dans la suite de cet article une technique qui permet d'exprimer clairement dans le code des éléments de spécification et de s'assurer lors de l'exécution du logiciel que ces spécifications sont vérifiées.Formulé autrement, nous allons demander à notre logiciel de nous prévenir s'il y a des bugs et de nous dires quels sont-ils.
une telle expression, qui affirme ce que l'élément doit faire et non pas comment il le fait, est appelée une assertion
l'une des façons d'y arriver consiste à inclure des éléments de spécification dans les implémentations elles-mêmes.
les assertions peuvent être contrôlées lors de l'exécution.
une assertion fausse correspond à un bug
les assertions vont être examinées comme une technique de construction des systèmes corrects, et de documentation, expliquent pourquoi ils sont corrects
Que faire quand une assertion n'est pas vérifiée ?
Il est également conseillé de conserver quelques contrôles actifs, même dans le programme le mieux contrôlé. Un appel à abort est donc rarement acceptable dans du code de production.
la relation entre une classe et ses clients est vue comme un accord formel, qui exprime les droits et les obligations de chaque partie.
Comment exprimer la notion d'invariant : une façon simple consiste à définir une fonction de contrôle d'invariant et à insérer des apples destinés à cette fonction à la fin de chaque méthode publique
En C++ : utiliser la variable NDEBUG
#ifndef NDEBUG
le code de l'invariant
#endif
L'Extreme programming — imaginée par Kent Beck — a popularisé une pratique, les tests unitaires, dont le but est justement de s'assurer de la qualité logicielle. Le principe de cette pratique est relativement simple : il s'agit de tout tester à l'aide de tests unitaires automatiques — tant dans leur exécution que dans leur interprétation. Pour cela Kent Beck et Erich Gamma — le coauteur de l'ouvrage de référence à propos de design patterns — ont développé JUnit, un framework de test dont le but est d'assurer cette automatisation.
On peut alors se demander si design by contract et test unitaire sont des techniques compatibles ou redondantes. Kent Beck, dans son ouvrage de présentation de l'Extreme programming, remarque que l'on pourrait utiliser le design by contract plutôt que les tests unitaires pour s'assurer de la qualité du logiciel que l'on développe. J'avoue que je ne suis pas d'accord avec ce point de vue et qu'il me semble profitable de mettre en pratique ces deux techniques.
Un test unitaire consiste à coder un exemple d'utilisation d'une méthode ou d'une classe et de vérifier que le résultat de cette utilisation conduit bien au résultat attendu. Ce résultat attendu est exprimé sous la forme d'assertions que JUnit à la charge de vérifier. Par conséquent, la vérification de ces tests résulte d'une action volontaire — caractérisée par le fait que l'on va les exécuter — et ces tests vont vérifier le bon comportement du système dans des cas particuliers que l'on espère les plus généraux possibles. (parce que l'on code des cas particulier, on est capable de définir des assertions contraignantes) ; les tests sont en dehors du code du programme.
Le design by contract quant à lui consiste à exprimer des assertions qui vont être vérifiées au cours de l'exécution du programme. Ces assertion s doivent être vérifiées dans tous les cas. Alors que les tests unitaires s'appliquaient sur des cas particulier (le calcul de la racine carrée de 4 vaut 2) : les assertions peuvent donc être très précises mais on court toujours le risque que le test ne mette pas en évidence un bug dans un autre cas particulier ; le design by contract s'efforce de définir des assertions qui s'appliquent dans tous les cas (on ne peut calculer la racine carrée que d'un nombre positif et dans ce cas cette racine est positive
Les notions de précondition, de postcondition et d'invariant sont apparues initialement dans les travaux de Floyd, Naur et Hoare, puis ont ensuite été popularisées par Bertrand Meyer et son language Eiffel.
Bertrand Meyer, Object-oriented software construction, Prenctice Hall, 1988
Bjarne Stroustrup, The C++ programming language, Third edition, Addison Wesley, 1997
Andrew Hunt, David Thomas, The pragmatic programmer, Addison Wesley, 2000
Copyright © 2002-2012 Olivier Mangez – Tous droits réservés