La couche de service doit-elle intercepter toutes les exceptions dao et les encapsuler en tant qu'exceptions de service?

23

J'ai une application web Spring à trois couches: dao, service et contrôleurs. Un contrôleur n'appelle jamais directement le dao, il le fait via la couche service. À l'heure actuelle, la plupart du temps, s'il y a une exception dao (runtime) qui n'est pas gérée, elle sera interceptée par un JSP affichant un message d'erreur à l'utilisateur final. La couche de service doit-elle intercepter toutes les exceptions dao et les encapsuler en tant qu'exceptions de service?

try {
   daoInstance.someDaoMethod();
} catch(DataAccessException dae) {
   throw new ServiceException("message", dae);
}

Supposons que ServiceException soit également à l'exécution et qu'il ne soit pas géré non plus. Y a-t-il une différence pour simplement lancer la DataAccessException au lieu de la ServiceException? Je pensais juste que la couche de présentation ne devrait pas connaître l'exception d'accès aux données. Mais je ne vois pas l'intérêt d'attraper des exceptions irrécupérables juste pour les envelopper.

oscar
la source

Réponses:

18

Je pense qu'un facteur important est de savoir qui sont vos clients.

Si votre couche de service n'est qu'une frontière architecturale entre les couches de votre propre projet et que le client de service se trouve dans le même domaine de confiance, alors il est normal de détendre les choses et de laisser des exceptions non contrôlées se propager à la couche de contrôleur ou au client de service.

Cependant, pour le code accessible au public; services qui sont consommés par un tiers ou un client, je pense qu'il est plus propre d'envelopper toutes les exceptions non vérifiées avec une exception orientée service, principalement pour des problèmes de sécurité, deuxièmement pour un couplage lâche et une abstraction propre.

Une exception de couche de données ne devrait jamais se rendre directement à l'utilisateur final d'une application Web . Il contient potentiellement des informations internes sur votre schéma, vos requêtes, les informations de numéro de ligne, les noms de variables ou de fonctions, etc. Les exceptions des utilisateurs finaux peuvent être filtrées dans un paramètre sécurisé.

Un client de service externe n'est pas concerné par vos détails d'implémentation et ne peut pas gérer les exceptions non contrôlées de toute façon, car il s'agit de bogues ou de problèmes environnementaux. Dans les applications sécurisées, les erreurs de base de données ne sont tout simplement pas suffisamment sécurisées pour se propager, OracleException - ORA-01234 - ...ce qui pourrait être la troisième table qui a été insérée. Le client doit être autorisé à traiter toutes les exceptions vérifiées / attendues qu'il peut gérer et à traiter tout le reste comme un rapport de bogue potentiel. Votre contrat de service doit être une abstraction atomique, cohérente et transactionnelle. S'il ne peut rien faire contre l'exception, alors la seule chose utile qui reste est de vous donner un rapport de bogue. Vous avez déjà la possibilité de consigner l'exception, alors pourquoi charger votre utilisateur final avec les détails? Votre application peut être surveillée afin que vous connaissiez déjà les exceptions non vérifiées avant que les utilisateurs ne les signalent.

Ce n'est jamais correct de manger des exceptions, je ne suis pas non plus un fan d'exceptions vérifiées, mais je préfère avoir un plan qui convient à la nature du produit dans son ensemble.

codenheim
la source
13

Non, vous ne devez pas encapsuler les exceptions DAO dans une application Web

C'est beaucoup de bruit dans le code pour un avantage nul. Les exceptions DAO sont des exceptions non vérifiées pour une bonne raison. Le code d'application ne peut rien faire d'utile pour récupérer à partir d'une exception DAO. Le vrai problème est ici:

... il sera intercepté par un JSP affichant un message d'erreur à l'utilisateur final.

Résolvez ce problème en un seul endroit au lieu de craquer toute la base de code.

Vous contrôlez la façon dont une exception non interceptée est affichée à l'utilisateur. Les exceptions non détectées sont dues à des bogues d'application ou à une défaillance du système sous-jacent. Il n'y a aucune raison de donner à l'utilisateur des informations sur la raison pour laquelle sa demande n'a pas pu être traitée. L'utilisateur ne peut rien faire. Tout ce que vous devez faire est de diffuser une page d'erreur conviviale.

NB: si vous vous retrouvez en train d'écrire beaucoup de code fastidieux, par exemple, en créant un tas de blocs catch qui encapsulent et relancent simplement, il y a presque toujours une meilleure solution.

Kevin Cline
la source
Merci pour votre réponse. Et oui, le jsp affiche un message personnalisé: "Oups, quelque chose s'est mal passé". Il ne montre aucune information sur l'exception
Oscar
7

La principale raison pour laquelle on utiliserait l' encapsulation d'exceptions est d'empêcher le code de la couche de gestion d'avoir à connaître toutes les exceptions possibles dans le système . Il y a deux raisons principales pour cela:

  • Cohérence: les exceptions déclarées se regroupent vers le haut de la pile d'appels. Si vous n'encapsulez pas les exceptions, mais les transmettez à la place en déclarant vos méthodes pour les lever, vous pouvez vous retrouver avec des méthodes de niveau supérieur qui déclarent de nombreuses exceptions différentes. La déclaration de toutes ces exceptions dans chaque méthode de sauvegarde de la pile d'appels devient fastidieuse.

  • Encapsulation: vous ne voudrez peut-être pas que vos composants de niveau supérieur connaissent quoi que ce soit sur les composants de niveau inférieur, ni sur les exceptions qu'ils génèrent. Par exemple, le but des interfaces et des implémentations DAO est d'abstraire les détails de l'accès aux données loin du reste de l'application. Maintenant, si vos méthodes DAO lèvent des SQLException, alors le code utilisant les DAO devra les attraper. Que faire si vous passez à une implémentation qui lit les données d'un service Web plutôt que d'une base de données? Ensuite, vos méthodes DAO devront lancer à la fois RemoteException et SQLException. Et, si vous avez un DAO qui lit les données d'un fichier, vous devrez également lancer IOException. Il s'agit de trois exceptions différentes, chacune liée à sa propre implémentation DAO.

Bref, la réponse est oui!

fabienbk
la source
3
Les implémentations JPA (par exemple Hibernate) lèvent des exceptions non contrôlées. Ils n'ont pas besoin d'être déclarés ou capturés.
kevin cline