Voici une interprétation de la page
15 Best Practices for Exception Handling(http://codebuild.blogspot.com/2012/01/15-best-practices-about-exception.html). Certaines best practices se complètent, il ne me semble pas nécessaire d'en citer 15.
1. Ne pas utiliser les exceptions pour gérer des erreurs métiers
Toutes les erreurs métiers doivent être prévues et gérées via des conditions classiques, on évitera donc d'écrire quelque chose comme catch (FunctionalException $e).
2. Eviter l'usage du \Exception
Le nom de l'exception doit être clair, on évite d'utiliser la classe \Exception, trop générale. Donc on évite le catch (\Exception $e) même dans le cas où on utiliserait une librairie/composant qui retournerait beaucoup d'exception (ex: Doctrine).
Evidemment, si la librairie retourne une instance d'\Exception, il n'y a pas le choix que de la catcher.cher
2.1 Exemples de noms clairs
* MysqlConnectionException
* NullEntityException
* EmptyFileException
* DeniedAccessException
* HttpException (Eventuellement, on peut définir des exceptions pour chaque code d'erreur HTTP)
En plus d'avoir un nom clair, chaque exception doit être correctement documentée.
3. Ne pas utiliser autre chose que des exceptions en cas d'erreurs techniques
On évite de retourner des nombres négatifs par exemple selon les erreurs. Mieux vaut privilégier des exceptions claires et non ambigues.
3.1 Exemples de mapping pour une lecture de fichier
* -1 -> FileNotFoundException
* -2 -> FileNotReadableException
* -3 -> UnsupportedFileException
* -4 -> TooBigFileException (dans le cas d'une limite à l'écriture par exemple)
4. Eviter de faire uniquement un throw dans un catch
Alors, ce genre de code est inutile :
try {
// Peu importe
} catch (AnyException $e) {
throw $e;
}
Soit le catch sert à quelque chose (on logguerait l'erreur par exemple), soit s'il ne sert à rien, il n'a pas de raison d'être.
De la même façon, ce n'est pas pertinent non plus de transformer le type d'exception en un autre type d'exception, autant laisser passer l'exception d'origine.
Eventuellement, il peut être par contre intéressant de compléter le message d'erreur de l'exception afin d'aider à la résolution du problème.
4.1 Eviter de ne rien faire dans le catch
Alors, ignorer l'exception, c'est souvent une fausse bonne idée. On évitera donc ce code :
try {
// Peu importe
} catch (AnyException $e) {
// Sifflote
}
5. Faire de l'héritage autant que faire ce peut
Plutôt que de faire hériter toutes ses exceptions avec \Exception, cela peut être intéressant de les réunir au sein de leurs domaines respectifs (ex: FileNotFoundException extends FileException, NotFoundHttpException extends HttpException, UnauthorizedUserException extends UserException...).
6. Logger les exceptions selon leur gravité
Selon les exceptions catchés, il peut être intéressant d'inscrire dans les logs les erreurs en fonction de leur gravité (DEBUG/NOTICE/FATAL).
On évite par contre de logger plusieurs fois la même erreur.
6.1 Exemples de niveau
DEBUG : Fichier non initialisé, Utilisateur n'existant pas encore
NOTICE : Time out sur la récupération d'une donnée non essentielle en cache par exemple
FATAL : erreur de connexion à la BDD, moteur de recherche, file d'attente
7. Utiliser le finally
Rarement utilisé, il peut être parfois être pratique pour libérer des ressources par exemple.
8. Eviter les try/catch dans des boucles
On peut catcher 1 fois mille erreurs plutôt que catcher mille fois 1 erreur.
9. Faire plusieurs try/catch plutôt qu'un seul
Bon cela se défend car personnellement je préfère fois un seul try/catch que plusieurs d'affilée.
L'idée est qu'il y ait peu d'instructions dans le try afin d'évaluer plus facilement d'où proviennent les erreurs.
10. User de code d'erreurs
Dans l'idéal, chaque exception est accompagnée d'un code d'erreur qui simplifiera la maintenance de l'application, ne serait-ce que dans l'étude statistique des problèmes courants.
11. Enfin, ne pas en abuser
Si pour afficher une seule page web, on risque de tomber sur l'une des 200 exceptions possibles, c'est que manifestement, la page est peut-être trop complexe.
Au-delà de 10 exceptions possibles pour un seul appel HTTP, je pense que cela devient ingérable.