La présentation est en train de télécharger. S'il vous plaît, attendez

La présentation est en train de télécharger. S'il vous plaît, attendez

Page de garde Design by Contract en C++ Maîtrise d’informatique Février 2002.

Présentations similaires


Présentation au sujet: "Page de garde Design by Contract en C++ Maîtrise d’informatique Février 2002."— Transcription de la présentation:

1 Page de garde Design by Contract en C++ Yannis.BRES@cma.inria.fr Maîtrise d’informatique Février 2002

2 Design by Contract Nous ne traiterons ici que des grandes lignes du principe du Design by Contract et de la mise en œuvre en C++. Pour plus de détail, reportez vous au cours très complet de Roger Rousseau, disponible sur : Uranie : ~rr/minfo A l’inverse du language Eiffel, C++ n’offre aucun support pour le DbC, sinon le support d’assertions très primitives via la fonction assert( expr ).  Il va falloir tout gérer soi-même :  Mettre en œuvre des macros de support des différents types d’assertions ;  Rédiger les assertions dans les commentaires Doc++ ;  Respecter le polymorphisme lors des redéfinitions de méthodes (pré/postconditions) ;  Vérifier les invariants de classes à la sortie des méthodes non const.  Et que sais-je encore… C’est extrêmement fastidieux (mais qui a dit que le développement de systèmes robustes ne l’était pas ?), mais selon moi, le "retour sur investissement" justifie cette peine…

3 Rappels Contrats publics : Pour pouvoir invoquer une fonction, l’appelant s’engage à respecter le contrat énoncé par la précondition. En échange, le ou les auteurs de la fonction s’engagent à respecter le contrat énoncé par la postcondition. Toute méthode altérant l’objet ne doit pas le mettre dans un état incohérent qui violerait l’invariant de classe. Contrats privés : + variants et invariants disséminés (assertions régulières, variants et invariants de boucles). L’évaluation des assertions ne doit pas provoquer d’effets de bord.

4 Classes dérivées et redéfinitions Selon le principe de base du polymorphisme, une instance d’une classe dérivée doit pouvoir être confondue avec une instance d’une classe de base : Les préconditions doivent être au moins aussi tolérantes ; Les postconditions doivent être au moins aussi strictes. Les préconditions des fonctions redéfinies seront donc une disjonction des préconditions de ces fonctions dans les classes ancètres. Les postconditions des fonctions redéfinies seront donc une conjonction des postconditions de ces fonctions dans les classes ancètres. Les invariants de classes des classes ancètres seront aussi vérifiés en conjonction de ceux des classes dérivées.

5 Exemple Complètement au hasard, code provenant d’une pile ( ArrayStack ): /** * Returns the item at the top of this stack. * * @precondition !IsEmpty() * * @postcondition & result != NULL */ inline Item& GetTop() const { PRECOND( !IsEmpty() ) Item& result= ArrayList ::GetLast(); POSTCOND( &result != NULL ) return result; }

6 Exemple /** * Pushes the specified item on the top of this stack. * * @precondition &item != NULL * * @postcondition GetItemCount() == GetItemCount @old ()+1 */ inline void Push( Item& item ) { PRECOND( &item != NULL ) #ifdef POSTCONDITIONS_ENABLED const int iOldItemCount= GetItemCount(); #endif ArrayList ::AddLast( item ); POSTCOND( GetItemCount() == iOldItemCount+1 ) ArrayStack::CheckInvariant(); }

7 Exemple /** * Returns and removes the item at the top of this stack. * @precondition !IsEmpty() * @postcondition GetItemCount() == GetItemCount @old ()-1 * @postcondition & result != NULL */ inline Item& Pop() { PRECOND( !IsEmpty() ) #ifdef POSTCONDITIONS_ENABLED const int iOldItemCount= GetItemCount(); #endif Item& result= ArrayList ::Remove( GetItemCount()-1 ); POSTCOND( GetItemCount() == iOldItemCount-1 ) POSTCOND( &result != NULL ) ArrayStack::CheckInvariant(); return result; }

8 Macros de support #ifdef PRECONDITIONS_ENABLED # define PRECOND( expr ) \ {if (!(expr)) PrecondFailed( #expr, __FILE__, __LINE__ );} #else # define PRECOND( expr ) \ {} #endif #ifdef INVARIANTS_ENABLED # define INVARIANT( expr ) \ {if (!(expr)) InvariantFailed( #expr, __FILE__, __LINE__ );} #else # define INVARIANT( expr ) \ {} #endif De même pour CHECK et POSTCOND.

9 Fonctions de support #ifdef INVARIANTS_ENABLED void InvariantFailed( const char * const strAssertionExpr, const char * const strFilename, const int iLine ) { cerr << "Invariant failed: " << strAssertionExpr << endl << "\tIn file: " << strFilename << endl << "\tAt line: " << iLine << endl; exit( 69 ); } #endif Cerise sur le gateau : positionner un point d’arrêt du déboggeur sur exit, ou appeler __debugbreak() (MSVC++ 7).

10 Conclusions Le DbC dans un language qui ne le supporte pas est encore plus fastidieux. Le code des assertions est parfois redondant avec celui des méthodes. L’exécution du système est généralement fortement ralentie lorsque les assertions sont armées. MAIS Le code est [auto]documenté, autovérifiable, autotestable : toute exécution (correcte) du programme ne fait qu’en renforcer la validité ! La détection des bugs est beaucoup plus proche de leur source ; elle intervient avant que le bug ne se propage dans les méandres d’un système au final très complexe. Diagnostic clair en cas de bug. Définition claire des responsabilités en cas de bug décelé. LORSQUE VOUS PROGRAMMEZ SOYEZ PARANO !!!!!


Télécharger ppt "Page de garde Design by Contract en C++ Maîtrise d’informatique Février 2002."

Présentations similaires


Annonces Google