Home > .NET/C#, Software, Software Architecture > Opinion sans originalité sur les exceptions

Opinion sans originalité sur les exceptions

Cet article est en réalité un courriel répondant à une question sur les bonnes pratiques avec les exceptions. S’il peut être utile à quelqu’un, tant mieux!

Premièrement, l’Exception Management Application Block est surtout fait pour “réagir” et publier les exceptions à l’extérieur du contexte d’exécution du code. Il n’aide donc, selon moi, aucunement à la bonne gestion des erreur à l’intérieur du code.

Généralement on arrive devant un des cas suivants:

  • L’exception est lancée dans un contexte transactionnel, dans quel cas le catch et le finally doivent s’assurer de faire le rollback, et laisser la classe appellante faire son rollback aussi. Dans ces cas là on ne veut pas gérer l’exception elle même, seulement s’assurer du bon fonctionnement du code.
  • L’exception est lancée à un niveau du stack directement causée par une action de l’utilisateur (par exemple, un paramètre invalide non vérifiable par des validateurs, ou une valeur invalide dans le querystring). Dans ces cas là, on peut simplement gérer l’erreur sur place (afficher une page disant que la page a reçu un paramètre invalide) ou, ma préférence personnelle, laisser l’erreur remonter jusqu’au handler principal (généralement le Main dans une application windows, ou le Global_asax.Application_Error dans les application web).
  • L’exception est récupérable (par exemple, le caching plante). Dans ces cas là (plutôt rares), simplement récupérer (et s’assurer qu’il n’est pas possible d’éviter qu’il y aie une exception en remplaçant le code fautif par une vérification des paramètres! Les exceptions ne devraient jamais faire partie intégrante d’un flow “valide” du code) et publier l’erreur.

J’ai toujours créé un assemblage “partagé” contenant les exceptions, les fonctions de logging, etc. par le passé. Je créais toujours des exceptions héritées de ApplicationException (du genre MyProjectException), de laquelle toutes mes exceptions précises héritaient. Avec le temps j’ai réalisé que ça ne me servait strictement à rien. Tant que le message d’exception est clair, et qu’il n’y a pas de besoin de catcher un type précis, une ApplicationException ordinaire fait le travail.

Personnellement je ne suis pas un fanatique de l’Application Block de gestion d’exception. C’est pratique, mais généralement un simple logging au niveau le plus haut de l’architecture fait amplement le travail. (Ça veut pas dire de pas l’utiliser, seulement que je ne donnerais pas de points pour ça dans une architecture). Je ne fais des throws (incluant l’exception initiale) que lorsque de l’information supplémentaire est disponible, sinon je la laisse passer. Exemple:

public bool VerifyCompatibility( Computer c, Version v )
{
if( c == null )
—-throw new ApplicationException( “Computer parameter must not be null” );


}

public void RegisterComputer( int computerId )
{
try
{
—-if( VerifyCompatibility(
——ComputerRegistry.Computer[computerId],
——Versions.CurrentVersion )
——)
——
}
catch( Exception exc )
{
—-throw new Exception( “Could not register computer ” + computerId, exc );
}
}

Dans ce cas précédent, si on avait pas encapsulé l’exception, il aurait été très difficile de retracer le cas fautif. Tandis que maintenant on a les exceptions:

[Computer parameter must not be null]
[Could not register computer 689]

L’information, ajoutée à l’URL, l’utilisateur en cours, les informations du navigateur client et le stack trace est suffisante pour reproduire l’erreur et la régler au niveau où il convient. Bref, les exceptions doivent être complémentaires, et servir à:

– Faire faillir le code le plus vite et facilement possible pour détecter les bogues tôt dans le développement
– Avoir l’information la plus concise et complète possible pour reproduire les erreurs facilement.

En bref, les exceptions ne devraient servir à rien d’autre qu’à déboguer et logger. Si vous jugez pertinent de créer une exception spéciale qui contient plus d’information (comme le niveau de gravité de l’erreur ou un message à afficher au client), amusez vous, mais rappellez-vous que généralement on ne log et n’utilise que le message et le stack trace d’une exception.

Une chose importante: une exception ne doit en aucun cas être affichée à l’utilisateur, directement ou indirectement, ni servir à générer un message utilisateur. Si une exception représente un paramètre invalide (disons une lettre dans un TextBox qui devrait contenir un chiffre), c’est effectivement une erreur du programme, et non pas de l’utilisateur. Pourquoi? Une validation de l’entrée de l’utilisateur aurait dû avoir lieu. Par exemple, un achat avec un numéro de carte de crédit invalide qui lance une erreur est un problème majeur, car il y aurait dû y avoir un ValidateCreditCardNumber avant, ou la méthode pourrait retourner un enum du statut de la commande.

À vous de juger! Mon mentra est: léger et complet, et ne jamais laisser passer un “Object not set to an instance of an object”! Jamais!

  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: