5.6 programmation défensive
avec les exceptions Delphi



Plan du chapitre:

Introduction

1. Notions de défense et de protection
 

1.1 Outils participant à la programmation défensive
1.2 Rôle et mode d’action d’une exception
1.3 Gestion de la protection du code Fonctionnement sans incident
Fonctionnement avec incident
1.4 Effets dus à la position du bloc except...end Fonctionnement sans incident
Fonctionnement avec incident
 1.5 Interception d’une exception d’une classe donnée
1.6 Ordre dans l’interception d’une exception Interception dans l’ordre de la hiérarchie
Interception dans l’ordre inverse
1.7 Créer et lancer ses propres exceptions


2. Traitement d’un exemple de protections
 

2.1 Le code de départ de l’unité
2.2 Code de la version.1 (premier niveau de sécurité)
2.3 Code de la version.2 (deuxième niveau de sécurité)
.

Introduction
 
Dans un autre cours nous avons vu une méthode de programmation défensive à l’aide des plans d’action dans une interface. Nous allons montrer comment on peut concevoir la programmation défensive sous un autre angle en protégeant directement le code à l’aide de la notion d’exception (semblable à celle du C++ ou d’Ada). L’objectif principal est d’améliorer la qualité de " robustesse " (définie par B.Meyer) d’un logiciel. L’utilisation des exceptions avec leur mécanisme intégré, autorise la construction rapide et néanmoins efficace de logiciels robustes.

Rappellons au lecteur que la sécurité d'une application est susceptible d'être mise à mal par toute une série de facteurs :

  • les problèmes liés au matériel : par exemple la perte subite d'une connection à un port, un disque défectueux...
  • les actions imprévues de l'utilisateur, entrainant par exemple une division par zéro...
  •  

    1. Notions de défense et de protection
     

    A l’occasion de la traduction Algorithme à langage évolué comme pascal, nous avons répertorié en plus des actions algorithmiques, des actions de sécurité et des actions ergonomiques qui doivent elles aussi être programmées.

    procedure TForm1.Button1Clic(Sender: TObject);
    var x,y,z:real;
    begin
     try
       x:=StrtoFloat(Edit1.text);
       y:=StrtoFloat(Edit2.text);
       z:=x /y ;
       Edit3.text:=FloattoStr(z);
     except
      ............
      ............
     end;
    end;
    Au départ nous avons edit1.textß 12,875 et edit2.text ß 0. Le calcul est erroné car x vaut 12,85 et y vaut zéro ce qui va induire une erreur de division par zéro dans l’instruction z := x / y .

    Observons ce qui se passe lorsque nous interceptons les exceptions EMathError et EZeroDivide.
     
     

    1.6.1 - Interception dans l’ordre de la hiérarchie :

    La sélection d’exception est programmée dans l’ordre de la hiérarchie des classes :

    EMathError
       |____ EZeroDivide
     
     

    procedure TForm1.Button1Clic(Sender: TObject);
    var x,y,z:real;
    begin
     try
       x:=StrtoFloat(Edit1.text);
       y:=StrtoFloat(Edit2.text);
       z:=x /y ;
       Edit3.text:=FloattoStr(z);
     except
       on EMathError do
         Edit3.text:='Erreur générale';
       on EZeroDivide do
         Edit3.text:='division par zéro';
     end;
    end;
    EMathError est interceptée en premier.
     
     

    1.6.2 - Interception dans l’ordre inverse :

    La sélection d’exception est programmée dans l’ordre inverse de la hiérarchie des classes.
     
     

    procedure TForm1.Button1Clic(Sender: TObject);
    var x,y,z:real;
    begin
     try
       x:=StrtoFloat(Edit1.text);
       y:=StrtoFloat(Edit2.text);
       z:=x /y ;
       Edit3.text:=FloattoStr(z);
     except
      on EZeroDivide do
         Edit3.text:='division par zéro';
       on EMathError do
         Edit3.text:='Erreur générale';
     end;
    end;

    1.7 Créer et lancer ses propres exceptions



    Il est possible de construire de nouvelle classe d'exceptions personnalisées en héritant d'une des classes de Delphi mentionnées plus haut, ou à minima de la classe de base Exception.(cette classe contient une propriété public property Message: string, qui contient en type string le texte à afficher dans la boîte de dialogue des exceptions quand l'exception est déclenchée).

    Il est aussi possible de lancer une exception personnalisée (comme si c'était une exception  propre à Delphi) à n'importe quel endroit dans le code d'une méthode d'une classe en instanciant un objet d'exception personnalisé et en le préfixant du mot clef raise.

    Le mécanisme général d'interception des exceptions à travers des gestionnaires d'exceptions try…except s'applique à tous les types d'exceptions y compris les exceptions personnalisées.
     
    Création d'une nouvelle classe



    Type
       MonExcept = class (Exception)

       End;

    MonExcept hérite par construction de la propriété public Message de sa mère.

    Lancer une MonExcept


    Type
       MonExcept = class (Exception)

       End;

    Procedure classA.Truc;
    begin
        …..
     raise MonExcept.Create ( 'salut' );
       …..

    end;

    intercepter une MonExcept


    MonExcept = class (Exception)…    end;

    Procedure classB.Meth;
    begin
       …..
        try….. // code à protéger
        except on MonExcept do begin
             ….. // code de réaction à l'exception
                   end;
         end;
    end;