Programmation par contrats

publicité
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
Téléchargement