[{"cw_etype": "Card", "eid": 1471, "title": "Programmation par Contrats et Qualit\u00e9 Logicielle", "synopsis": "Cet article \u00e9crit par Nicolas Chauvat est paru dans le num\u00e9ro\r\nv2.03 du 9 novembre 2001 de \"D\u00e9veloppeur R\u00e9f\u00e9rence\". Tous droits\r\nr\u00e9serv\u00e9s.", "content": "============\r\nIntroduction\r\n============\r\n\r\nR\u00e9cemment, l'un des piliers de l'industrie informatique annon\u00e7ait la mise sur le march\u00e9, d'ici quelques ann\u00e9es, d'ensembles de machines capables de s'administrer et de r\u00e9parer certains de leurs probl\u00e8mes mat\u00e9riels de mani\u00e8re autonome. Ceci illustre bien la croissance continue de la complexit\u00e9 des syst\u00e8mes informatiques, qui est depuis toujours soutenue par l'\u00e9volution parall\u00e8le de la puissance des machines et de l'abstraction des langages et les m\u00e9thodes de d\u00e9veloppements. Avec la croissance de la complexit\u00e9, ce sont les occasions de faire des erreurs qui deviennent plus fr\u00e9quentes. Pour garantir la qualit\u00e9 et le succ\u00e8s de ces syst\u00e8mes complexes, on se doit de ma\u00eetriser leur complexit\u00e9 en employant des outils et des m\u00e9thodes adapt\u00e9es.\r\n\r\nDans le domaine logiciel, les contrats sont l'un des moyens disponibles pour ma\u00eetriser cette complexit\u00e9, garantir la qualit\u00e9 et faciliter la r\u00e9utilisation des composants. Introduits \u00e0 la fin des ann\u00e9es quatre-vingt par Bertrand Meyer avec son langage Eiffel \r\n, les contrats vont bien au-del\u00e0 du m\u00e9canisme d'assertions et de typage fort disponibles auparavant, sans pour autant atteindre le niveau d'abstraction des langages de sp\u00e9cification et de preuve formelle. Leur int\u00e9gration parfaite avec le mod\u00e8le objet et les m\u00e9thodes de d\u00e9veloppement associ\u00e9es en fait un outil de choix pour qui d\u00e9sire garantir la qualit\u00e9 et faciliter la r\u00e9utilisation de composants.\r\n\r\n==================\r\nQualit\u00e9 et D\u00e9fauts\r\n==================\r\n\r\nEn ing\u00e9nierie informatique comme dans d'autre domaines, on a coutume de dire \"la qualit\u00e9 est tout et tout est qualit\u00e9\". En effet, la qualit\u00e9 du produit est un facteur essentiel de son succ\u00e8s et qu'il faut donc employer tous les moyens disponibles pour l'accro\u00eetre et la garantir. De plus, la qualit\u00e9 du tout d\u00e9coule de la qualit\u00e9 des diff\u00e9rents composants, mais aussi des diff\u00e9rentes \u00e9tapes de la r\u00e9alisation et les d\u00e9fauts de chacun auront une r\u00e9percussion sur le produit final.\r\n\r\nBien que tout soit qualit\u00e9, tout n'a pas la m\u00eame influence sur la qualit\u00e9 et tout le monde n'aura pas la m\u00eame perception de la qualit\u00e9. D\u00e9finir la qualit\u00e9 comme une combinaison de diff\u00e9rents facteurs permet donc de comparer de mani\u00e8re objective l'influence des m\u00e9thodes ou des composants sur chacun de ces facteurs, mais aussi d'\u00e9tudier l'influence de ces facteurs sur la perception de la qualit\u00e9 qu'auront les diff\u00e9rents acteurs.\r\n\r\nMeyer propose de d\u00e9composer la qualit\u00e9 en l'ensemble des facteurs suivants: correction, robustesse, efficacit\u00e9, facilit\u00e9 d'utilisation, richesse fonctionnelle, d\u00e9lais, co\u00fbt, adaptabilit\u00e9 et extensibilit\u00e9, compatibilit\u00e9, portabilit\u00e9, r\u00e9utilisation, compr\u00e9hensibilit\u00e9, facilit\u00e9 de test. Vous pouvez vous reporter \u00e0 et pour une d\u00e9finition plus pr\u00e9cise de chacun de ces termes.\r\n\r\nOn voit bien que certains de ces facteurs ne vont pas avoir le m\u00eame poids et que les personnes charg\u00e9es des sp\u00e9cifications, de la programmation, des tests, de la maintenance ou de la vente, pour ne citer que celles-l\u00e0, auront chacune des priorit\u00e9s qui leurs sont propres dans leur approche de la qualit\u00e9.\r\n\r\nA cette premi\u00e8re d\u00e9finition de la qualit\u00e9, il convient d'ajouter celle de son oppos\u00e9, le d\u00e9faut. Cette fois encore, c'est une formulation g\u00e9n\u00e9rale qui semble la plus satisfaisante, car elle permet d'int\u00e9grer les d\u00e9fauts non pas seulement du code, mais aussi des sp\u00e9cifications, de la documentation et du reste.\r\n\r\nUn d\u00e9faut est une propri\u00e9t\u00e9 d'un logiciel qui peut et doit \u00eatre am\u00e9lior\u00e9e. Accro\u00eetre et garantir la qualit\u00e9, c'est donc employer tous les moyens disponibles pour \u00e9viter d'introduire des d\u00e9fauts et d\u00e9tecter puis \u00e9liminer les d\u00e9fauts que l'on a pu introduire par m\u00e9garde.\r\n\r\nL'utilisation de m\u00e9thodes de conception et d'analyse, les formalismes de descriptions, les conventions de documentation, l'identification de bonnes pratiques sont autant d'outils et de guides pour \u00e9viter d'introduire des d\u00e9fauts.\r\n\r\nPour d\u00e9tecter et supprimer les d\u00e9fauts, on peut utiliser la revue(*) lors de la plupart des \u00e9tapes, mais aussi des outils et techniques particuliers lorsqu'il s'agit du code source : analyse statique (compilateur, lint, m\u00e9triques), test (unitaires, int\u00e9gration, validation), outils CASE(*), langages de preuve formelle, etc.\r\n\r\nLes d\u00e9fauts, qui d\u00e9coulent des erreurs que font les personnes, peuvent \u00eatre introduits \u00e0 toutes les \u00e9tapes du d\u00e9veloppement, que ce soit lors de l'analyse, des sp\u00e9cifications, de la r\u00e9alisation, de la documentation, de la validation ou m\u00eame par la suite lors de la r\u00e9utilisation si l'on adopte une approche composants.\r\n\r\nLa qualit\u00e9 doit donc \u00eatre un souci de tous les instants et nous allons maintenant essayer de montrer en quoi la programmation par contrat se r\u00e9v\u00e8le une aide \u00e0 la fois pratique et efficace tout au long de la vie du logiciel, de sa conception \u00e0 sa r\u00e9utilisation en passant par sa r\u00e9alisation et sa validation.\r\n\r\n============\r\nLes Contrats\r\n============\r\n\r\nLes contrats vont au-del\u00e0 des m\u00e9canismes d'assertions et de typage fort, sans pour autant atteindre le niveau d'abstraction des langages de preuve formelle. Les contrats sont un moyen de r\u00e9pondre \u00e0 deux questions essentielles : \"que doit faire le logiciel ?\" et \"le logiciel fait-il ce qu'il est sens\u00e9 faire ?\".\r\n\r\nDans la vie courante, les contrats sont des accords qui lient des parties en d\u00e9crivant de mani\u00e8re pr\u00e9cise les obligations et les b\u00e9n\u00e9fices de chacun. Les contrats transpos\u00e9s au domaine du logiciel vont s'appliquer aux classes et aux appels de m\u00e9thodes pour lesquelles ils vont jouer un r\u00f4le identique et d\u00e9crire de mani\u00e8re pr\u00e9cise plusieurs aspects de leur interactions. Le contrat s'applique \u00e0 la relation entre l'appelant et l'appel\u00e9, gr\u00e2ce aux pr\u00e9-conditions, aux post-conditions et aux invariants, mais il a aussi des cons\u00e9quences sur l'h\u00e9ritage et la gestion des exceptions et des cas anormaux, sans compter qu'il facilite la documentation.\r\n\r\nLes invariants, qui sont d\u00e9finis pour chaque classe, sont les propri\u00e9t\u00e9s qui doivent \u00eatre v\u00e9rifi\u00e9es \u00e0 tout instant et qui seront v\u00e9rifi\u00e9es avant et apr\u00e8s l'ex\u00e9cution de chaque m\u00e9thode. Les invariants permettent donc de capturer le sens et les caract\u00e9ristiques de validit\u00e9 de certaines propri\u00e9t\u00e9s des objets.\r\n\r\nLes pr\u00e9-conditions sont des conditions portant sur les arguments en entr\u00e9e que le client (appelant) a pour devoir de respecter. Si ces conditions ne sont pas respect\u00e9es, le fournisseur (appel\u00e9) n'a pas \u00e0 s'engager \u00e0 ex\u00e9cuter correctement la m\u00e9thode appel\u00e9e. Les pr\u00e9-conditions doivent \u00eatre transparentes, c'est \u00e0 dire qu'elles doivent \u00eatre n\u00e9cessaires et suffisantes pour que l'appelant puisse \u00eatre servi et obtienne les garanties associ\u00e9es aux post-conditions.\r\n\r\nLes post-conditions sont des garanties sur les sorties que le fournisseur (appel\u00e9) s'engage \u00e0 respecter si la m\u00e9thode s'ex\u00e9cute normalement. Si, lors de l'ex\u00e9cution de la m\u00e9thode, le fournisseur rencontre une erreur impossible \u00e0 g\u00e9rer, il doit alors lancer une exception et peut ne pas respecter les post-conditions. En revanche, il lui est interdit, m\u00eame s'il rencontre une erreur, de terminer l'ex\u00e9cution et de rendre le contr\u00f4le normalement au client, sans respecter ses garanties sur les sorties.\r\n\r\nLe mot-clef \"old\" peut \u00eatre utilis\u00e9 dans les post-conditions ou lors du traitement des exceptions pour faire r\u00e9f\u00e9rence \u00e0 l'\u00e9tat dans lequel \u00e9tait l'objet juste avant l'ex\u00e9cution de la m\u00e9thode. Ceci permet de param\u00e9trer les garanties sur les sorties ou de tenter un nouvel essai d'ex\u00e9cution apr\u00e8s une exception.\r\n\r\nLes assertions classiques se retrouvent sous leur forme habituelle pour v\u00e9rifier une condition dans le corps d'une m\u00e9thode ou pour faciliter le traitement des boucles, auquel cas on peut d\u00e9finir des invariants de boucles et des conditions pour les variables utilis\u00e9es dans les boucles. L'id\u00e9e est donc toujours de faire appara\u00eetre au mieux ce qui rel\u00e8ve de l'impl\u00e9mentation et ce qui rel\u00e8ve de la sp\u00e9cification.\r\n\r\nLes exceptions lanc\u00e9es lors de l'ex\u00e9cution de la m\u00e9thode peuvent \u00eatre attrap\u00e9es pour tenter de r\u00e9soudre le probl\u00e8me localement, sans passer directement le contr\u00f4le \u00e0 l'appelant. Le traitement de ces exceptions peut choisir de modifier l'\u00e9tat de l'objet pour corriger les erreurs et reprendre l'ex\u00e9cution, ou bien restaurer l'\u00e9tat d'origine gr\u00e2ce \u00e0 \"old\" et faire un nouvel essai, ou encore agir pour que l'objet soit dans un \u00e9tat coh\u00e9rent avant de rendre contr\u00f4le \u00e0 l'appelant en lan\u00e7ant une exception.\r\n\r\nLorsqu'une classe h\u00e9rite d'une autre, elle h\u00e9rite des contrats associ\u00e9s aux m\u00e9thodes, mais peut choisir de rel\u00e2cher les contraintes portant sur le client et de renforcer ses propres garanties. De cette fa\u00e7on, on peut se reposer sur le contrat d'un parent pour appeler la m\u00e9thode d'un enfant, car les obligations de l'appelant ne peuvent qu'\u00eatre identiques ou moindres (or qui peut le plus peut le moins) et les garanties de l'appel\u00e9 ne peuvent qu'\u00eatre identiques ou sup\u00e9rieures (et abondance de bien ne nuit pas).\r\n\r\nLe contrat est une documentation naturelle, car il r\u00e9pond \u00e0 la question \"qu'est-ce que cette classe est suppos\u00e9e faire ?\". Plut\u00f4t que de se contenter de l'interface, on peut donc utiliser l'interface et le contrat (invariants et pre/post-conditions) comme \u00e9lement de base de la documentation d'une classe. Ceci est utile lors des sp\u00e9cifications, mais aussi lors de la g\u00e9n\u00e9ration automatique de la documentation \u00e0 partir du code et de ses commentaires, comme le permettent des outils disponibles dans de nombreux langages.\r\n\r\nSuite \u00e0 cette description, il est important de faire remarquer ce que ne sont pas les contrats.\r\n\r\nLes contrats ne sont pas une m\u00e9thode de programmation d\u00e9fensive. Au contraire, ils servent \u00e0 se pr\u00e9munir de ce genre d'attitude qui consiste \u00e0 toujours v\u00e9rifier en d\u00e9but de m\u00e9thode la validit\u00e9 des arguments re\u00e7us, puisqu'il est recommand\u00e9 qu'une m\u00e9thode ne cherche pas \u00e0 v\u00e9rifier dans son corps ce qui a \u00e9t\u00e9 garanti par les pr\u00e9-conditions du contrat.\r\n\r\nEnfin, les contrats vont bien plus loin que les assertions, qui ne sont en comparaison qu'un m\u00e9canisme de base, lequel n'a que peu en commun avec les aspects m\u00e9thodologiques et l'int\u00e9gration au mod\u00e8le objet et \u00e0 l'h\u00e9ritage qu'offrent les contrats. Il est cependant int\u00e9ressant de noter que plusieurs langages qui ne proposent pas de programmation par contrats dans leur version de base, utilisent le m\u00e9canisme d'assertion, lorsqu'il est disponible, pour mettre en oeuvre les contrats avec des biblioth\u00e8ques, des pr\u00e9processeurs ou d'autres moyens sp\u00e9cialis\u00e9s.\r\n\r\n====================\r\nLangages et Contrats\r\n====================\r\n\r\nA l'origine, Bertrand Meyer a appliqu\u00e9 ses id\u00e9es sur les contrats \u00e0 son langage Eiffel, qui reste le seul \u00e0 proposer un m\u00e9canisme de contrats faisant partie int\u00e9grante du langage. Cependant, de nombreux langages modernes offrent une mise en oeuvre plus ou moins exhaustive des contrats, rajout\u00e9e par le biais de pr\u00e9-processeurs, de m\u00e9ta-programmation, ou d'autres techniques, faisant usage par exemple de la r\u00e9flexivit\u00e9 lorsqu'elle est disponible. Parmi ces langages, on compte Java, C++, Python, Perl ou d'autres langages sp\u00e9cialis\u00e9s et moins connus, comme Narval, qui est d\u00e9di\u00e9 \u00e0 la mise en oeuvre d'assistants personnels intelligents.\r\n\r\nNous allons maintenant voir ce que chacun propose et comparer le code obtenu en deux langages, Python et Eiffel, pour un m\u00eame exemple : le mod\u00e8le d'un r\u00e9servoir. Sa capacit\u00e9 est mesur\u00e9e en litres et on le consid\u00e8re plein lorsqu'il est plein \u00e0 97% et vide lorsqu'il est plein \u00e0 moins de 3%. Les actions possibles sont vider le r\u00e9servoir, le remplir, ajouter un volume pr\u00e9cis ou retirer un volume pr\u00e9cis.\r\n\r\n======\r\nEiffel\r\n======\r\n\r\nEiffel, en tant que langage d'origine, propose une mise en oeuvre assez exhaustive avec les invariants, les pre et post-conditions, l'utilisation de \"old\", les formes abr\u00e9g\u00e9es de classes utilis\u00e9es comme documentation et l'int\u00e9gration avec le m\u00e9canisme d'h\u00e9ritage. Eiffel ne propose cependant pas de traitement g\u00e9n\u00e9rique des exceptions et se contente d'un do/rescue/retry : si la m\u00e9thode d\u00e9crite par do produit une exception, le contr\u00f4le passe \u00e0 rescue, dans lequel on peut tenter un retry qui reprend l'ex\u00e9cution au d\u00e9but du do. Voir \r\n.\r\nNotre exemple du r\u00e9servoir peut \u00eatre impl\u00e9ment\u00e9 comme suit en Eiffel :\r\n\r\n.. code::\r\n\r\n\tclass RESERVOIR\r\n\r\n\t* RESERVOIR mod\u00e9lise un r\u00e9servoir dont la capacit\u00e9 est d\u00e9termin\u00e9e\r\n\t* \u00e0 la cr\u00e9ation et que l'on peut remplir et vider\r\n\r\n            creation creer feature\r\n\r\n\tcapacite: INTEGER\r\n           remplissage: INTEGER\r\n           capacite_maximale: INTEGER is 2000\r\n\r\n\tinvariant\r\n\t\tremplissage >= 0\r\n\t\tremplissage = 0\r\n\t\tcapacite  97*capacite\r\n\t\tend\r\n\r\n\tajouter(volume:INTEGER) is\r\n\t\t-- Ajouter le volume donn\u00e9 au r\u00e9servoir \r\n                       require\r\n\t\t\tremplissage + volume = 0\r\n\t\tdo\r\n\t\t\t-- code qui contr\u00f4le le vidage du r\u00e9servoir\r\n\t\tensure\r\n\t\t\tremplissage = old remplissage - volume\r\n\t\tend\r\n\r\n\tcontient(NONE):INTEGER is\r\n\t\t-- Renvoie le volume contenu dans le r\u00e9servoir\r\n\t\tdo\r\n\t\t\tResult:= remplissage\r\n\t\tend\r\n\r\n\testVide(NONE):BOOLEAN is\r\n\t\t-- Teste si le r\u00e9servoir est vide\r\n\t\tdo\r\n\t\t\tResult:= (remplissage*100  97*capacite)\r\n\t\tend\r\n\r\nend\t-- class RESERVOIR\r\n\r\n======\r\nPython\r\n======\r\n\r\nUne seule mise en oeuvre des contrats est disponible pour python, mais elle utilise au mieux le caract\u00e8re dynamique du langage gr\u00e2ce \u00e0 une approche de m\u00e9ta-programmation. Le constructeur des objets que l'on d\u00e9sire voir respecter les contrats renvoie un proxy (au sens des Design Patterns \r\n\r\n), qui \u00e0 chaque appel de m\u00e9thode prendra soin de conserver une copie de l'objet \u00e0 laquelle faire r\u00e9f\u00e9rence par la suite avec \"old\" et extraira de la cha\u00eene de documentation associ\u00e9e \u00e0 la m\u00e9thode et \u00e0 la classe les conditions n\u00e9cessaires qui seront v\u00e9rifi\u00e9es en utilisant le m\u00e9canisme d'assertion natif.\r\n\r\nCeci permet, sans modifier l'interpr\u00e9teur, et en choisissant classe par classe, de faire respecter des invariants, des pre et post-conditions, d'utiliser \"old\", mais aussi de rajouter un typage fort des arguments des m\u00e9thodes et cela en conservant les avantages qu'apportent les contrats en mati\u00e8re de documentation puisque les conditions sont conserv\u00e9es dans les commentaires associ\u00e9s aux m\u00e9thodes et aux classes. Cette mise en oeuvre ne pr\u00e9voit en l'\u00e9tat rien de particulier concernant les exceptions, mais l'approche de m\u00e9ta-programmation choisie permet d'y porter rem\u00e8de tr\u00e8s rapidement en modifiant la classe proxy. Voir .\r\n\r\nNotre exemple du r\u00e9servoir peut \u00eatre impl\u00e9ment\u00e9 comme suit en Python :\r\n\r\n.. class:code\r\n\r\n\tclass Reservoir :\r\n\t\"\"\"R\u00e9servoir mod\u00e9lise un r\u00e9servoir dont la capacit\u00e9 est d\u00e9termin\u00e9e\r\n\t\u00e0 la creation et que l'on peut remplir et vider.\r\n\r\n\tinv: 0  97*self.capacite;\r\n\t\t\"\"\"\r\n\t\tpass # code qui contr\u00f4le le remplissage du r\u00e9servoir\r\n\r\n\r\n\tdef ajouter(self,volume) :\r\n\t\t\"\"\"Ajouter le volume donn\u00e9 au r\u00e9servoir\r\n\r\n\t\tolds.remplissage: self.remplissage;\r\n\r\n\t\treq: self.remplissage + volume = 0;\r\n\t\tensure: self.remplissage = self.olds.remplissage -volume;\r\n\t\t\"\"\"\r\n\t\tpass # code qui contr\u00f4le le vidage du reservoir\r\n\r\n\r\n\tdef contient(self) :\r\n\t\t\"\"\"Renvoie le volume contenu dans le r\u00e9servoir\"\"\"\r\n\t\treturn self.remplissage\r\n\r\n\r\n\tdef estVide(self) :\r\n\t\t\"\"\"Test si le r\u00e9servoir est vide\"\"\"\r\n\t\treturn (self.remplissage*100  97*self.capacite)\r\n\r\n====\r\nJava\r\n====\r\n\r\nJava ne propose dans sa version de base ni contrats ni m\u00eame assertions. Malgr\u00e9 cela, deux mises en oeuvre des contrats sont disponibles pour Java.\r\n\r\njContractor utilise le m\u00e9canisme de r\u00e9flexivit\u00e9 de Java et la possibilit\u00e9 de remplacer le ClassLoader de la machine virtuelle pour remplacer un appel \u00e0 une m\u00e9thode par une suite d'appels \u00e0 la m\u00e9thode des invariants de classe, sa m\u00e9thode pr\u00e9-condition, elle-m\u00eame, sa m\u00e9thode post-condition et \u00e0 nouveau la m\u00e9thode des invariants, pour peu que ces m\u00e9thodes aient \u00e9t\u00e9 correctement nommm\u00e9es. En cas d'exception, le contr\u00f4le est transmis \u00e0 la m\u00e9thode de gestion appropri\u00e9e. jContractor g\u00e8re donc les invariants, les pre et post-conditions, l'utilisation de \"old\" et les exceptions g\u00e9n\u00e9riques, mais l'utilisation des contrats pour la documentation se r\u00e9v\u00e8le difficile puisque leur expression est contenue dans des m\u00e9thodes et n'appara\u00eet donc pas avec les outils classiques comme javadoc. Voir .\r\n\r\niContract est un pr\u00e9-processeur qui extrait les directives inscrites dans les commentaires pr\u00e9c\u00e9dents les m\u00e9thodes pour g\u00e9n\u00e9rer le code n\u00e9cessaire, lequel sera ensuite compil\u00e9 comme \u00e0 l'habitude. iContract traite les invariants et les pre et post-conditions. Les directives \u00e9tant \u00e9crites dans les commentaires, le contrats apparaissent naturellement dans la documentation des classes en utilisant les outils habituels. Voir .\r\n\r\n===\r\nC++\r\n===\r\n\r\nDeux mises en oeuvre des contrats sont disponibles pour le C et le C++.\r\n\r\nLa premi\u00e8re est Assertions.h, qui d\u00e9finit tout sous forme de macros qui peuvent \u00eatre activ\u00e9es au moment de la compilation et transforment les diff\u00e9rentes conditions en des assertion de base du langage C. Cette mise en oeuvre est assez exhaustive et comprend les invariants, les pre/post-conditions, les assertions classiques, l'utilisation de old, mais aussi des connecteurs logiques (et, ou, implication, etc.), l'appartenance \u00e0 un ensemble, la validit\u00e9 de bornes et les comparaisons avec z\u00e9ro. Le d\u00e9faut d'Assertions.h est ne ne pas fournir de solution d'int\u00e9gration avec le m\u00e9canisme d'h\u00e9ritage ni avec les outils de g\u00e9n\u00e9ration de documentation. Voir .\r\n\r\nLa seconde est GNU Nana, qui d\u00e9finit tout sous forme de macros C/C++ sur la base des assertions du langage C et offre, en plus de la possibilit\u00e9 de les d\u00e9sactiver \u00e0 la compilation, d'autres macros pour faciliter le d\u00e9boguage avec gdb. Cette mise en oeuvre est tr\u00e8s compl\u00e8te et propose, en plus des contrats tels que d\u00e9finis dans Eiffel, des fonctions destin\u00e9es \u00e0 faciliter le d\u00e9boguage et la mesure de certains param\u00e8tres, tels que le nombre de cycles consomm\u00e9s par le processeur pour ex\u00e9cuter une fonction, le temps d'ex\u00e9cution, etc. Comme Assertions.h, GNU Nana ne permet pas d'int\u00e9grer les contrats avec le m\u00e9canisme d'h\u00e9ritage de C++, en revanche, cette solution fournit un g\u00e9n\u00e9rateur de documentation. Voir .\r\n\r\n=============\r\nNarval et XML\r\n=============\r\n\r\nLe langage Narval, d\u00e9velopp\u00e9 par Logilab \r\nLogilab est la soci\u00e9t\u00e9 pour laquelle travaille l'auteur de cet article\r\n, est d\u00e9di\u00e9 \u00e0 la cr\u00e9ation d'assistants personnels intelligents. Avec Narval, plut\u00f4t que des programmes, on \u00e9crit des recettes qui d\u00e9crivent des comportements que pourra avoir l'assistant. Les recettes sont des encha\u00eenements d'\u00e9tapes li\u00e9es par des transitions. Les \u00e9tapes sont des actions ou des transformations qui acceptent des fragments de XML en entr\u00e9e et produisent des fragments de XML en sortie. La caract\u00e9ristique int\u00e9ressante est que le prototype de ces \u00e9tapes est constitu\u00e9 de conditions sur le entr\u00e9es et les sorties exprim\u00e9es en XPath. Ceci permet \u00e0 la fois d'expliciter le type des arguments et d'imposer des pre/post conditions. On a cherch\u00e9 \u00e0 unifier ainsi la signature d'une fonction et la notion de pre/post-condition en les formulant comme une extension du typage. Ces prototypes servent de documentation pour les \u00e9tapes, mais sont aussi employ\u00e9s pour la plannification automatique, auquel cas leur utilisation se rapproche des pr\u00e9dicats en logique. Dans ce langage, il n'y a cependant pas d'h\u00e9ritage des actions, car il est mis en oeuvre \u00e0 un niveau inf\u00e9rieur dans l'\u00e9criture des biblioth\u00e8ques. De plus, la sp\u00e9cialisation des conditions sur les entr\u00e9es et les sorties ne se fait que par ajout et renforcement. Voir .\r\n\r\n===============\r\nAutres langages\r\n===============\r\n\r\nDes mises en oeuvre des contrats existent aussi dans d'autres langages, n'h\u00e9sitez donc pas \u00e0 partir \u00e0 leur recherche sur internet. Les amateurs de perl sont les plus chanceux puisqu'un module ad-hoc est disponible sur CPAN .\r\n\r\n=======================================\r\nAvantages des contrats pour la qualit\u00e9 \r\n=======================================\r\n\r\nLa programmation par contrat, de m\u00eame que l'approche orient\u00e9e-objet qu'elle vient renforcer, est une m\u00e9thode qui permet de formaliser les probl\u00e8mes et leur solution \u00e0 un niveau d'abstraction o\u00f9 ils trouvent une expression claire. C'est en l'occurence une avanc\u00e9e nette par rapport aux m\u00e9canismes d'assertion ou de typage fort disponibles dans plusieurs langages.\r\n\r\nBien que les contrats apportent un niveau de formalisme et d'abstraction sup\u00e9rieur, ils ne constituent pas pour autant une marche difficile \u00e0 franchir. Etant parfaitement int\u00e9gr\u00e9 au mod\u00e8le objet, ils sont facilement abordables et compr\u00e9hensibles, ce qui les rend rapidement utilisables et permet d'en retirer un b\u00e9n\u00e9fice direct.\r\n\r\nDe plus comme il font partie du programme, ils \u00e9vitent de creuser l'habituel foss\u00e9 qui s\u00e9pare langage de sp\u00e9cification ou de preuve formelle et langage de r\u00e9alisation.\r\n\r\nLes contrats facilitent toutes les \u00e9tapes du d\u00e9veloppement, des sp\u00e9cifications aux tests et au d\u00e9boguage en passant par la documentation, car ils permettent de comparer ce que le programme est suppos\u00e9 faire avec ce qu'il fait r\u00e9ellement.\r\n\r\nOn ne peut m\u00eame pas reprocher aux contrats d'imposer un compromis g\u00eanant qui contraindrait \u00e0 \u00e9changer cette s\u00e9curit\u00e9 suppl\u00e9mentaire contre une d\u00e9gradation des performances puisque la plupart des mises en oeuvre permettent de supprimer la v\u00e9rification des contrats. Le m\u00eame code source peut donc \u00eatre utilis\u00e9 avec les contrats activ\u00e9s lors du d\u00e9veloppement et des tests, puis sans les contrats lorsqu'il est d\u00e9ploy\u00e9 et que l'on souhaite am\u00e9liorer les temps d'ex\u00e9cution.\r\n\r\nLorsqu'on souhaite r\u00e9utiliser un composant logiciel, les contrats servent \u00e0 la fois de documentation et de garantie que le comportement attendu sera obtenu. Leur avantage par rapport \u00e0 des sp\u00e9cifications est d'\u00eatre indissociables du code source et facilement activables pour v\u00e9rifier qu'ils sont correctement utilis\u00e9s. On pourra se reporter \u00e0 ce sujet aux m\u00e9saventures du lanceur europ\u00e9en Ariane 5 \r\n.\r\nComparativement aux autres m\u00e9thodes disponibles dans la panoplie de l'ing\u00e9nieur logiciel pour \u00e9viter d'introduire des d\u00e9fauts ou pour d\u00e9tecter et supprimer ceux que l'on aurait introduits, les contrats sont particuli\u00e8rement rentables et offrent un rapport \u00e9l\u00e9v\u00e9 entre le b\u00e9n\u00e9fice pour qualit\u00e9 et l'effort consenti tout au long du d\u00e9veloppement.\r\n\r\n==========\r\nConclusion\r\n==========\r\n\r\n\r\nCet article a cherch\u00e9 \u00e0 montrer ce que peuvent apporter les contrats au d\u00e9veloppement logiciel, qu'il s'agisse de l'analyse et des sp\u00e9cifications, de la documentation, des tests et du d\u00e9boguage, de la robustesse, ou de la r\u00e9utilisation de composants. Ces avantages des contrats sont autant de facteurs pour am\u00e9liorer la qualit\u00e9, qui doit \u00eatre pr\u00e9sente d\u00e8s l'origine et non simplement v\u00e9rifi\u00e9e \u00e0 la fin du d\u00e9veloppement.\r\n\r\nSi les contrats sont si avantageux, pourquoi ne sont-ils pas plus largement r\u00e9pandus ? Probablement par manque d'\u00e9ducation et de publicit\u00e9, mais aussi parce qu'ils ne font pas partie des versions de base de la plupart des langages modernes. Cet article aura tent\u00e9 de vous faire conna\u00eetre les diff\u00e9rentes mises en oeuvre disponibles et d'apporter ainsi sa modeste pierre \u00e0 l'\u00e9difice...\r\n\r\n===========\r\nD\u00e9finitions\r\n===========\r\n\r\nD\u00e9faut \r\n    Propri\u00e9t\u00e9 d'un logiciel qui doit et peut \u00eatre am\u00e9lior\u00e9e.\r\n\r\nCASE\r\n    Computer Assisted Software Engineering.\r\n\r\nRevue \r\n    Une personne qui n'a pas particip\u00e9 \u00e0 la r\u00e9alisation commente et critique les choix et les r\u00e9sultats.\r\n\r\n===========================\r\nBibliographie et r\u00e9f\u00e9rences\r\n===========================\r\n\r\nObject-Oriented Software Construction\r\n______________________________________\r\n\r\n**BertrandMeyer** *Prentice HallSecond Edition, 1997* http://www.eiffel.com/doc/oosc.html\r\n\r\n**Design Patterns: Elements of Reusable Object-Oriented Software \r\nErichGamma\r\nRichardHelm\r\nRalphJohnson** \r\n*JohnVlissides*\r\nAddison-Wesley 1995 http://www.hillside.net/patterns/DPBook/DPBook.html\r\n\r\n**Design by contract: the lessons of the Ariane\r\nJean-MarcJezequel\r\nBertrandMeyer**\r\n*IEEE Computer 1997*\r\n30 2 129-130\r\nhttp://www.eiffel.com/doc/manuals/technology/contract/ariane/page.html\r\n\r\n**Design By Contract: A Missing Link In The Quest For Quality Software\r\nTodd Plessel**\r\n*Lockheed Martin, US EPA 1998* https://www.eiffel.org/doc/solutions/Design_by_Contract_and_Assertions\r\n\r\n**Eiffel**\r\nhttp://www.eiffel.com/doc/manuals/technology/contract/\r\n\r\n**iContract**\r\nhttp://www.reliable-systems.com/tools/iContract/iContract.htm\r\n\r\n**jContractor: Reflective Java Library to Support Design-by-Contract.\r\nMuratKaraorman UrsH\u00f6lzle JohnBruno**\r\n*Technical Report TRCS98-31, University of California, Santa Barbara 1998* http://www.cs.ucsb.edu/oocsb/papers/TRCS98-31.html\r\n\r\n**Assertions.h**\r\nhttps://www.eiffel.org/doc/solutions/Design_by_Contract_and_Assertions\r\n\r\n**Gnu Nana: improved support for assertions and logging in C and C++\r\nP.J.Maker**\r\nhttps://savannah.gnu.org/projects/nana\r\n\r\n**Design by Contract for Python\r\nReinholdPl\u00f6sch**\r\n*IEEE Proceedings of the Joint Asia Pacific Software Engineering Conference (APSEC97/ICSC97), Hongkong.1997* \r\nhttps://python.plainenglish.io/design-by-contract-in-python-44db6e899db2\r\n\r\n**Perl. Class::Contract disponible sur CPAN**\r\nhttp://search.cpan.org/search?module=Class::Contract", "content_format": "text/rest", "wikiid": "contrats_et_qualite", "creation_date": "2011/12/01 14:52:37", "cwuri": "http://beta.logilab.fr/1471", "modification_date": "2023/01/12 14:56:40"}]