Je ne crois pas que les captures locales soient un anti-modèle, en fait, si je me souviens bien, elles sont en fait appliquées en Java!
Ce qui est essentiel pour moi lors de la mise en œuvre de la gestion des erreurs, c'est la stratégie globale. Vous voudrez peut-être un filtre qui capture toutes les exceptions à la limite du service, vous pouvez les intercepter manuellement - les deux sont très bien tant qu'il existe une stratégie globale, qui tombera dans les normes de codage de vos équipes.
Personnellement, j'aime détecter les erreurs dans une fonction lorsque je peux effectuer l'une des opérations suivantes:
- Ajouter des informations contextuelles (telles que l'état des objets ou ce qui se passait)
- Gérez l'exception en toute sécurité (comme une méthode TryX)
- Votre système franchit une frontière de service et appelle une bibliothèque externe ou une API
- Vous souhaitez intercepter et renvoyer un autre type d'exception (peut-être avec l'original comme exception interne)
- L'exception a été levée dans le cadre d'une fonctionnalité d'arrière-plan de faible valeur
Si ce n'est pas un de ces cas, je n'ajoute pas de try / catch local. Si c'est le cas, selon le scénario, je peux gérer l'exception (par exemple une méthode TryX qui retourne un faux) ou relancer afin que l'exception soit gérée par la stratégie globale.
Par exemple:
public bool TryConnectToDatabase()
{
try
{
this.ConnectToDatabase(_databaseType); // this method will throw if it fails to connect
return true;
}
catch(Exception ex)
{
this.Logger.Error(ex, "There was an error connecting to the database, the databaseType was {0}", _databaseType);
return false;
}
}
Ou un exemple de retour:
public IDbConnection ConnectToDatabase()
{
try
{
// connect to the database and return the connection, will throw if the connection cannot be made
}
catch(Exception ex)
{
this.Logger.Error(ex, "There was an error connecting to the database, the databaseType was {0}", _databaseType);
throw;
}
}
Ensuite, vous attrapez l'erreur en haut de la pile et présentez un bon message convivial à l'utilisateur.
Quelle que soit l'approche que vous adoptez, il est toujours utile de créer des tests unitaires pour ces scénarios afin de vous assurer que la fonctionnalité ne change pas et ne perturbe pas le flux du projet à une date ultérieure.
Vous n'avez pas mentionné la langue dans laquelle vous travaillez, mais vous êtes un développeur .NET et vous l'avez vu trop de fois pour ne pas le mentionner.
N'ÉCRIS PAS:
catch(Exception ex)
{
throw ex;
}
Utilisation:
catch(Exception ex)
{
throw;
}
Le premier réinitialise la trace de la pile et rend votre capture de niveau supérieur totalement inutile!
TLDR
La capture locale n'est pas un anti-modèle, elle peut souvent faire partie d'une conception et peut aider à ajouter un contexte supplémentaire à l'erreur.