INF3143 Modélisation et spécification formelles des logiciels Hiver 2017 Alexandre Terrasa Département d’informatique, UQÀM Conception modulaire Chapitre tiré du cours de INF3140 - Spécification Formelle de Logiciels Hafedh Mili 2 Conception modulaire Comment limiter la complexité globale d’un système? Idée: Découper un tout en morceaux (modules) 3 Exigences de la conception modulaire Chaque module doit ● être moins complexe que le tout (diviser pour régner) ● offrir une sous fonction utile et cohérente du système (forte cohésion) ● être relativement indépendant des autres modules (faible couplage) 4 Forte cohésion Avantages ● Clarté ● Maintenabilité, Testabilité ● Extensibilité, Réutilisabilité Comment l’atteindre? ● Single Responsability Principle ● une seule action par classe / méthode 5 Faible couplage Avantages ● modules plus réutilisables ● moins d’impacts lors des modifications Comment l’atteindre? ● bien choisir le contenu ● dissimuler les détails d’implémentation 6 Interface publique Interface publique = API Application Programming Interface Ensemble des méthodes (services) que l’on peut appeler sur un module ou composant ● services publiques et protégés ● documentation associée 7 Programmation modulaire Comment faire? Une idée: programmation par contrats 8 Programmation par contrats 9 Programmation par contrats Design By Contract (DBC) Paradigme de programmation pour ● écrire des programmes robustes ● faciliter la détection des erreurs ● faciliter la réutilisation du code Basé sur des pré-conditions, des post-conditions et des invariants. 10 Contrat: définition Relation de confiance entre deux parties ● client (l’appelant d’un service) ● fournisseur du service (l’appelé) Chacune des deux parties s’engage à respecter sa part du contrat. 11 Contrats: Histoire 1980: notation Z (Jean-Raymond Abrial) ● spécification par prédicats 1985: Eiffel (Bertrand Meyer) ● programmation par contrats 2000: Java IContract 2010: Java Cofoja 2012: Ada 12 Rappel: Assertions Expression booléenne ● évaluée à l’exécution (dynamiquement) ● permet de vérifier l’état du système Si le système fonctionne correctement, toutes les assertions doivent être vraies. Sinon, il y a un bogue. 13 Contrats et assertions Trois types d’assertions pour définir des contrats ● pré-conditions ● post-conditions ● invariants 14 Pré-conditions Condition à vérifier par le client avant l’appel d’un service. Obligation ● le client doit satisfaire la pré-condition Bénéfice ● le client est assuré que la post-condition sera satisfaite par le fournisseur 15 Intérêt des pré-conditions Pour le fournisseur ● établir un contrat d’utilisation ● dicter les règles à respecter par le client ● limiter les opérations de vérification et de contre-mesure sur les arguments Si une pré-condition n’est pas respectée, l’erreur se trouve dans le code du client. 16 Post-conditions Condition à garantir par le fournisseur après l’appel d’un service. Obligation ● le fournisseur doit satisfaire la post-condition Bénéfice ● le fournisseur est assuré que la pré-condition est respectée par le client 17 Intérêt des post-conditions Pour le client ● établir un contrat de résultat ● dicter les règles à respecter par le fournisseur Si une post-condition n’est pas respectée, l’erreur se trouve dans le code du fournisseur. 18 Exemple de contrat En pseudo-code double sqrt(double x) requires x >= 0 ensures result >= 0 Math.abs(x - result * result) < 0.001 19 Invariants Condition toujours vraie s’appliquant à une classe ou une interface. Permet de valider l’état du système. Bénéfice ● vérifier les propriétés d’un objet qui ne devraient jamais changer durant l’exécution 20 Évaluation des contrats Durant l’exécution ● pré-condition: avant chaque appel ● post-condition: après chaque appel ● invariants: avant et après chaque appel Cas particulier des invariants: ● en théorie: ne devraient jamais changer ● en pratique: peuvent changer brièvement entre la pré et la post condition 21 Contrats et langages de programmation 22 Lien entre contrats et langages de programmation Les contrats sont vérifiés dynamiquement ● comment écrire les contrats? ○ dans le langage de programmation? ○ à côté? ● comment vérifier les contrats? ○ quand? ○ quel outil? 23 Contrats et langages de programmation Plusieurs façon d’intégrer la programmation par contrats à un langage ● nativement (directement dans le langage) ○ Eiffel, D, Lisaac, Spark, VDM, Ada ● via des pré-processeurs et des commentaires ou annotations spécifiques ○ Java IContract, Java Cofoja ● via des macros ○ C, C++ 24 Contrats en Eiffel Depuis 1987 ● Support natif des contrats ● Constructions pour les méthodes ○ bloc require (pré-condition) ○ bloc ensure (post-condition) ● Construction pour les classes/interfaces ○ bloc invariant https://www.eiffel.com/values/design-by-contract/introduction/ 25 Exemple de contrat en Eiffel class DICTIONNAIRE[G] feature ajouter(x: G; cle: STRING) is require taille <= capacite not cle.empty do -- code d’insertion ensure has (x) item (cle) = x taille = old taille + 1 -- reste du code end 26 Contrats en Java Nous avons déjà vu les assertions. Deux approches via des pré-processeurs 2000: Java IContract ● basé sur des commentaires ● déprécié depuis quelques années... 2010: Java Cofoja ● basé sur des annotations Java ● supporté par Google 27 Exemple avec les assertions double sqrt(double x) { assert x >= 0.0 // … définir la valeur de retour `res` assert res >= 0.0 assert Math.abs((res * res) - x) < 0.001 } 28 Exemple avec Java iContract /** * @pre (x >= 0.0) * @post (return >= 0.0) && * Math.abs((return * return) - x) < 0.001 */ double sqrt(double x) { // ... } http://www.javaworld.com/article/2074956/learn-j ava/icontract--design-by-contract-in-java.html 29 Exemple avec Java Cofoja @Requires("x >= 0.0") @Ensures({ "result >= 0.0", "Math.abs(result * result - x) < 0.001" }) double sqrt(double x) { return Math.sqrt(x); } https://github.com/nhatminhle/cofoja 30 Contrats en C/C++ Deux approches pour le langage C 1995: APP ● basé sur des commentaires et un pré-processeur Macros ● basé sur des macros de compilation 31 Exemple C avec APP /*@ * assume (x >= 0.0) * return res where (res >= 0.0) && * abs((res * res) - x) < 0.001 @*/ float sqrt(float x) { // ... } D. S. Rosenblum. A practical approach to programming with assertions. IEEE Trans. Soft. Eng., 21(1):19-31, 1995. 32 Exemple C avec macro Fichier assert.h void assert( int expression ); Définition de la macro: #ifdef NDEBUG #define assert(expr) 0 #else #define assert(expr) \ (expr) ? 0 : __assert_fail(__STRING(expr), __FILE__, __LINE__) #endif 33 Exemple macro C (suite) Utilisation de la macro #include <assert.h> int sqrt( int x ) { assert( x >= 0 ) // … } S. Maguire. L’art du code. Microsoft Press, 1995. 34 Utilisation de Cofoja 35 Contract For Java (Cofoja) Contrats pour Java ● ● ● ● ● https://github.com/nhatminhle/cofoja Nhat Minh Lê (Google) dernière version: février 2016 Java 1.6 à 1.8 open-source 36 Exemple import com.google.java.contract.Ensures; import com.google.java.contract.Requires; public class Main { @Requires("x >= 0.0") @Ensures({ "result >= 0.0", "Math.abs(result * result - x) < 0.001" }) public static double sqrt(double x) { return Math.sqrt(x); } public static void main(String[] args) { // pre-condition OK double x = sqrt(100); System.out.println("x = " + x); // pre-condition FAIL x = sqrt(-100); System.out.println("x = " + x); } } 37 Comment ça marche? javac .java processeur d’annotations java .class contract contract contrats tisseur 38 Utiliser Cofoja Nécessite un jar pour fonctionner ● cofoja.contracts.asm-VERSION.jar ● version stable actuelle 1.3 Télécharger les dépendances sur https://github.com/nhatminhle/cofoja/releases 39 Cofoja en ligne de commandes Compiler avec les annotations: javac \ -cp cofoja.jar \ -processorpath cofoja.jar \ src/Main.java Exécuter avec les contrats: java -javaagent:cofoja.jar Main 40 Cofoja dans Eclipse 1. Créer un nouveau projet Java 41 Cofoja dans Eclipse 2. Ajouter la dépendance vers cofoja.jar 42 Cofoja dans Eclipse 3. Activer le processeur d’annotation 43 Cofoja dans Eclipse 4. Passer les options à Cofoja 44 Cofoja dans Eclipse Options: com.google.java.contract.classpath %PROJECT.DIR%/lib/cofoja.asm-VERSION.jar com.google.java.contract.sourcepath %PROJECT.DIR%/src com.google.java.contract.classoutput %PROJECT.DIR%/bin 45 Cofoja dans Eclipse 5. Activer Cofoja à l’exécution -javaagent:lib/cofoja.asm-VERSION.jar 46 Cofoja dans Eclipse Exécuter le projet sans l’agent x = 10.0 x = NaN Exécuter le projet avec l’agent x = 10.0 Exception in thread "main" com.google.java.contract.PreconditionError: x >= 0.0 at Main.sqrt.<pre>(Main.java) at Main.sqrt(Main.java) at Main.main(Main.java:14) 47 Exercices 48 Exercice 1 Traduire l’OCL ci-dessous en contrat context Etudiant::inscrire() pre: estInscrit = false post: estInscrit = true context Etudiant::desinscrire() pre: estInscrit = true post: estInscrit = false 49 Exercice 2 Écrire les contrats adéquates pour la classe suivante: Compte solde: Real getSolde(): Real créditer(montant: Real) débiter(montant: Real) 50 Exercice 3 Écrire les contrats en pré-condition et post-condition pour MyInteger::div() MyInteger value: Integer div(diviseur: MyInteger): MyInteger 51 Exercice 4 Exprimer les contrats: ● valeurs est toujours strictement supérieur à 0 ● ajoute prend un paramètre toujours supérieur ou égal à 0 ● ajoute incrémente le nombre de valeurs et additionne valeur à somme ● moyenne retourne la moyenne de somme sur valeurs Compteur valeurs: Integer somme: Integer ajoute(valeur: Integer) moyenne(): Integer 52 Exercice 5 Contrats à implémenter init à 6 Permis Assuré 1 1 valeurVehicule(): Integer assurance.vehicule.valeur ou 0.0 points: Integer retirerPoints(p: Integer) 1 retire p points Assuré doit avoir des points sur son permis pour avoir une assurance 0..1 “auto” ou “moto” Assurance categorie: String valeur: Integer Véhicule 1 = catégorie de l’assurance 1 catégorie: String valeur: Integer <= valeur assurance 53 Conclusion Programmation par contrats ● basés sur les pré / post-conditions et invariants ● facilitent la conception modulaire ● définissent les attentes et responsabilités du client et du fournisseur ● permettent un code plus robuste, sûr 54 Ressources ● http://www.labunix.uqam.ca/~tremblay/INF3135/ Materiel/contrats+erreurs.pdf ● https://www.eiffel.com/values/design-by-contract/i ntroduction/ ● G. Tremblay. Modélisation et spécification formelle des logiciels. Éditions Loze-Dion, 2004. Chap 15 ● R. Mitchell, J. McKim. Design by Contract, by Example. Addison-Wesley, 2001. ● J.M. Jézéquel, M. Train, C. Mingins. Design Patterns and Contracts. Addison-Wesley, 2001. 55