Formation écrire des classes fiables, tutoriel & guide de travaux pratiques en pdf.
Erreurs de compilation
L’erreur la plus courante et la plus simple à corriger est celle qui apparaît lors de la compilation. Le compilateur indique alors le type d’erreur et la ligne où celui-ci a trouvé un problème. Dans la majorité des cas, il s’agit
✔ d’erreurs typographiques.
✔ d’oublis de déclaration de variables.
✔ d’appels de méthodes non existantes.
✔ de non respect des types et/ou du nombre d’arguments lors de l’utilisation de méthodes. Dans la majorité des cas, le compilateur est très dithyrambique dans ses commentaires et est d’une aide précieuse. 2. Erreurs lors de l’exécution du programme
Arrêt du programme à l’exécution
Cette fois, la compilation se déroule sans erreur mais à l’exécution, le programme « plante ». L’erreur la plus courante est l’oubli de la création d’un objet qui se traduit par le message suivant: *** Error at Run Time ***: Call with a Void target.
Il est assez facile de corriger le bogue en consultant l’état de l’objet au moment du « plantage ». 2 frames in current stack. ===== Bottom of runtime stack ===== <system root> Current = TST#0x8775038 [ str = Void ] line 7 column 2 file /home/jct/bioinfo/work/tst.e ====================================== make TST Current = TST#0x8775038 [ str = Void ] line 9 column 8 file /home/jct/bioinfo/work/tst.e ===== Top of runtime stack ===== Line : 9 column 4 in /home/jct/bioinfo/work/tst.e. *** Error at Run Time ***: Call with a Void target.
Dans le message précédent, on peut lire qu’il y a eu une utilisation d’un objet Void dans la ligne 9. L’objet en question str est à l’état Void; donc il est l’auteur du « plantage ». Current = TST#0x8775038 [ str = Void ]
Comportement instable du programme
Une fois passé ce stade, il reste les erreurs qui ne font pas « planter » le programme mais qui ne donne pas le résultat escompté. Il faut alors s’assurer que les objets ont un « comportement » normal correspondant aux attentes du créateur de classes. Les erreurs peuvent survenir à deux niveaux:
✔ au niveau du programmeur « client » qui utilise incorrectement les classes.
✔ au niveau de l’utilisateur qui n’utilise pas le programme de façon correcte.
Assertions: Garde-fous pour le programmeur client
Une assertion est un test qui s’il est incorrect déclenche l’arrêt de l’exécution du programme. Il joue le rôle d’une sorte de filtre – placé dans une routine ou une classe – qui va bloquer et arrêter l’exécution du programme s’il y a eu une utilisation anormale.
ATTENTION!!! L’assertion ne sert que pendant la phase de test de classes ou du programme et sera « enlevée » une fois que le programme est en phase de production. Il est donc impératif que l’assertion n’ait aucun rôle dans le comportement d’une classe ou d’un programme.
La syntaxe est la suivante: Il est d’usage d’associer au test de l’assertion, un message qui sera affiché par le programme au moment de l’arrêt du programme. La syntaxe d’une assertion en Eiffel est la suivante: my_tag_explaining_the_assertion : condition L’étiquette my_tag_explaining_the_assertion est un seul mot (on utilise donc souvent le caractère souligné « _ » pour faire une miniphrase résumant la condition de l’assertion. L’assertion est équivalente au pseudocode suivant: if condition = False then io.put_string(« my_tag_explaining_the_assertion%N ») die_with(1) End of program end
Une assertion classique est de vérifier que l’argument de votre routine est non vide. Par exemple, pour une méthode foo(arg : MY_CLASS) l’assertion peut alors ressembler à: arg_not_void : arg /= Void
Assertions au niveau des routines
Les routines en Eiffel peuvent être réglementées par des pré et des post conditions qui sont des assertions placées respectivement dans les blocs require et ensure. Une routine classique peut donc être organisée de la manière suivante: foo(arg1 : INTEGER; arg2 : MY_CLASS) is require Here are the preconditions (first assertion block) local Declaration of local variables do code ensure Here are the post conditions (last assertion block) end
Le programmeur « client » doit utiliser la routine foo en respectant les clauses d’un « contrat » entre lui et le créateur de classes via la routine foo. Si les clauses du contrat sont respectées (les preconditions et les postconditions sont correctes), alors la routine est exécutée. Dans le cas contraire, le contrat est rompu, l’exécution s’arrête. Ce schéma de fonctionnement est nommé par le fondateur du langage Eiffel Bertrand Meyer, le « design by contract ».
L’exemple typique est l’utilisation de la méthode sqrt qui calcule la racine carrée d’un nombre. La ligne suivante est incorrecte: (1).sqrt Nombre négatif interdit
class TST
creation make
feature make is do
io.put_double( (1).sqrt); io.put_new_line
end end end of class TST
A l’exécution du programme, le message suivant est affiché: *** Error at Run Time ***: Require Assertion Violated. 3 frames in current stack. ===== Bottom of runtime stack ===== <system root> Current = TST#0x9241038 line 7 column 2 file /home/jct/bioinfo/work/tst.e ====================================== make TST Current = TST#0x9241038 line 9 column 7 file /home/jct/bioinfo/work/tst.e ====================================== sqrt INTEGER_8 Current = 1 Result = 0.000000
line 238 column 9 file /usr/local/SmartEiffel/lib/numeric/integer_general.e ===== Top of runtime stack ===== *** Error at Run Time ***: Require Assertion Violated.