Journal : Qu'est-ce que bien gérer les erreurs dans ses programmes ?
Posté par Nicolas Boulay () le 14 décembre 2007
La question métaphysique du jour : comment bien gérer les erreurs ?
Il y a déjà plusieurs types d'erreurs: celles qui relèvent de la mauvaise utilisation de code, elle pourrait se traiter avec des assert(), il y a celle qui remonte un mauvais fonctionnement à l'étage du dessus, et celle entre les deux, qui peuvent servir parfois à effectuer des "scans" de fonctionnalités (genre on charge tous les noyau réseau un par un pour trouver le bon driver de sa carte).
Les problèmes surviennent lorsque du code qui devrait retourner un assert() et donc crasher en cas d'erreur font un simple "return error"; et qui a le malheur de faire une exécution partielle du code. En général, 2 ou 3 appels de fonctions différentes de la lib en question plus tard, tout va se viander aléatoirement.
Donc, il faut déjà prévoir quoi faire en cas d'erreurs au plus bas niveau et ne remonter qu'en cas d'impossibilité de gérer le problème à ce niveau et encore, en le faisant proprement (par exemple, un retour de malloc à 0 ?).
Proprement, cela veut dire peut-être de séparer fonction de test de validité des paramètres, et exécution proprement dite de la fonction, cela permet d'éviter les exécutions partielles (imaginez une fonction de lib qui retourne une erreur en s'étant exécuter à moitie dans un cas qui n'entraine pas une erreur fatal de l'ensemble).
Souvent dans les exemples d'utilisation, la gestion des erreurs est mise de coté pour éviter d'alourdir un exemple. Cela démontre déjà que la gestion d'erreur à tendance à brouiller l'algorithme de base. Je trouve que cela renforce le principe de base de bien séparer exécution et traitement d'erreur.
Il y a maintenant les gestions d'exception pour faire cela. Je n'ai jamais vraiment coder avec, mais je n'ai jamais non plus vu un véritable enthousiasme pour ce système.
J'aurais tendance à éviter toute gestion d'erreurs qui entraîne un crash. Aucun utilisateur n'aime voir un crash, surtout dans l'embarqué. Cela me rappelle une certaine central inertielle qui partait en autotest sur une exception Ada. J'aurais tendance à interdire formellement tout code qui interrompt la fonctionnalité.
Connaissez vous des règles génériques pour déterminer la conduite à tenir en cas de retour d'erreur ?
Qu'est-ce que vous conseillez donc pour faire propre ?
Il y a déjà plusieurs types d'erreurs: celles qui relèvent de la mauvaise utilisation de code, elle pourrait se traiter avec des assert(), il y a celle qui remonte un mauvais fonctionnement à l'étage du dessus, et celle entre les deux, qui peuvent servir parfois à effectuer des "scans" de fonctionnalités (genre on charge tous les noyau réseau un par un pour trouver le bon driver de sa carte).
Les problèmes surviennent lorsque du code qui devrait retourner un assert() et donc crasher en cas d'erreur font un simple "return error"; et qui a le malheur de faire une exécution partielle du code. En général, 2 ou 3 appels de fonctions différentes de la lib en question plus tard, tout va se viander aléatoirement.
Donc, il faut déjà prévoir quoi faire en cas d'erreurs au plus bas niveau et ne remonter qu'en cas d'impossibilité de gérer le problème à ce niveau et encore, en le faisant proprement (par exemple, un retour de malloc à 0 ?).
Proprement, cela veut dire peut-être de séparer fonction de test de validité des paramètres, et exécution proprement dite de la fonction, cela permet d'éviter les exécutions partielles (imaginez une fonction de lib qui retourne une erreur en s'étant exécuter à moitie dans un cas qui n'entraine pas une erreur fatal de l'ensemble).
Souvent dans les exemples d'utilisation, la gestion des erreurs est mise de coté pour éviter d'alourdir un exemple. Cela démontre déjà que la gestion d'erreur à tendance à brouiller l'algorithme de base. Je trouve que cela renforce le principe de base de bien séparer exécution et traitement d'erreur.
Il y a maintenant les gestions d'exception pour faire cela. Je n'ai jamais vraiment coder avec, mais je n'ai jamais non plus vu un véritable enthousiasme pour ce système.
J'aurais tendance à éviter toute gestion d'erreurs qui entraîne un crash. Aucun utilisateur n'aime voir un crash, surtout dans l'embarqué. Cela me rappelle une certaine central inertielle qui partait en autotest sur une exception Ada. J'aurais tendance à interdire formellement tout code qui interrompt la fonctionnalité.
Connaissez vous des règles génériques pour déterminer la conduite à tenir en cas de retour d'erreur ?
Qu'est-ce que vous conseillez donc pour faire propre ?
> Lire le journal (80 commentaires, moyenne: 2,4).
Vous avez demandé le commentaire #891062.



Programmation par aspects ?
Soit un type de données. Sur ce type de données, on va effectuer toute une série d'opérations. À chaque opération, on doit vérifier que l'instance passée en paramètre respecte certaines règles (contraintes du domaine d'application ou contraintes techniques). Toute cette gestion d'erreur va être mélangée au code fonctionnel (l'algorithme) et éparpillée dans l'API. Si une contrainte change, il faut tout changer, partout...
Ce sont deux symptômes classiques :
- confusion ou mélange de problèmes différents dans un même fichier (tangling)
- éparpillement d'un même problème dans plusieurs fichiers (scattering)
C'est tout à fait le genre de problème que la programmation par aspects peut régler (disons "mitiger"). D'autres exemples typiques d'utilisation sont le logging ou le contrôle d'accès.
Disclémeur: je suis une buse en aspect, nul si découvert, toussa...
[^]Re: Programmation par aspects ?
Cela serait plus clair si tu donnais un exemple genre en pseudo code.
Je comprends bien l'idée d'avoir 2 "plans" pour voir un algo, le cas normal et le cas en erreur. Mais en pratique, je ne vois pas du tout la tronche que cela peut avoir.
[^]Re: Programmation par aspects ?
Tu as le programme de base, dans un fichier, et divers « aspects », chacun dans un fichier séparé. Chaque aspect contient le code à insérer, l'endroit où il faut l'insérer et éventuellement des propriétés à vérifier. Lorsque le programme est compilé, il est d'abord « tissé » (woven en anglais), les différents aspects sont insérés automatiquement par un pré-compilateur (un weaver) puis tout ça est compilé.
Il existe aussi des weaver qui travaillent en niveau byte-code, et même au run-time. Tout ça est encore un peu académique (j'ai jamais vu d'application à large échelle, mais je ne suis pas un expert). Ceci dit, ça ne me semble pas abracadabrant, comme approche... YMMV
[^]Re: Programmation par aspects ?
Le sempiternel lien vers Wikipedia kivabien :
http://fr.wikipedia.org/wiki/Programmation_orientée_a(...)