dire, par exemple, que j'ai un Le problème avec ceci est que si une exception est lancée pendant le référentiel actions, il est avalé. Au lieu de cela, je pensais avoir un postsservice code> qui crée un post: créer () code> renvoie false code> et tout ce que le consommateur sait que le poste code> n'a pas été ajouté, mais ne sait pas pourquoi em>. P> Serviceresult Code> Classe: P> public class ServiceResult
{
public bool Success { get; private set; }
public Exception Exception { get; private set; }
}
6 Réponses :
Si vous utilisez WCF, je recommanderais contre un Vous devez définir un Ce Question Stackoverflow a une mise en œuvre complète des contrats d'erreur . P>
Vous pouvez toujours avoir votre front-end, simplement dire "une erreur s'est produite", mais en utilisant un contrat d'erreur permettrait une meilleure gestion des erreurs sur la couche d'interface utilisateur de votre code s'il devient nécessaire à l'avenir. P> Serviceresult code> ou quoi que ce soit similaire pour traiter des exceptions dans une couche SOA. P>
défaut code> pour votre méthode. Cela permettrait à consommer du code de connaître les types d'exceptions pouvant être levées et de les gérer en conséquence en utilisant des blocs traditionnels essayer code>. P>
FWIW - Je n'utilise pas WCF. Devrais-je être? Ceci est pour une application MVC. Je ne voulais vraiment pas jeter mes contrôleurs avec de nombreux blocs d'essai / attraper (ce que j'essayais d'éviter). Merci pour votre contribution!
Je pense que cela dépend de la portée de pourquoi em>. Certaines raisons de défaillance ne devraient pas concerner le consommateur, à mon avis et ceux-ci devraient être connectés au service. D'autre part, il y a des cas lorsque le consommateur doit être informé de ces raisons. En plus de les enregistrer, vous devez indiquer la cause de l'erreur en quelque sorte. p>
Par exemple, supposons un cas d'utilisation très courant d'un service d'enregistrement de l'utilisateur. Il est fort probable que vous disposiez d'un attribut unique qui identifie l'utilisateur (la poignée de l'utilisateur, le courrier électronique, etc.). Cette unicité doit être appliquée par le service (et probablement au niveau de la base de données également). Maintenant, si le consommateur tente d'enregistrer un utilisateur et qu'il échoue, car la contrainte a été violée, le consommateur doit être informé de ces raisons (afin qu'il puisse essayer un autre manuel d'utilisateur). Les validations infructueuses tombent dans le même scénario, la plupart du temps. p>
S'il y a une sorte de problème de base de données interne d'autre part, le consommateur ne doit pas être informé des détails (parce que la responsabilité exclusive du service; et ce n'est pas quelque chose que le consommateur peut faire quoi que ce soit, de toute façon). P >
Considérant que, je dirais que le retour d'un booléen est insuffisant dans de nombreux cas. Donc, avoir une sorte de type serviceresult code> ne ressemble pas à une mauvaise idée. Je ne suis pas sûr d'inclure l'exception code> cependant. Mais peut-être que vous pouvez créer une sorte de serviceExpection, spécifique à votre service. Parfois, les codes d'erreur sont tout simplement bien pour cela. P>
Merci pour votre réponse. Pensez-vous retourner une liste d'erreurs Messages i> préférables aux exceptions actuelles?
@Thecloudlesssky. D'après mon expérience, cela ne fait pas beaucoup de différence, mais c'est probablement parce que j'écris généralement le consommateur, dans ActionScript et lors de la partie de service à PHP ou parfois à .NET). Donc, du point de consommation de VIEF, des exceptions ne sont que des messages, pas de véritables exceptions que je pouvais attraper avec un essai / capture. En tout état de cause, je pense qu'un aspect important consiste à rendre ces messages spécifiques à votre application. Cela pourrait être un peu plus de travail, mais vous leur faisons partie de votre API, de sorte qu'ils sont documentés et les deux extrémités sont d'accord sur le type d'erreurs à attendre.
(suite). Par exemple, il y a quelque temps, j'ai travaillé avec un service Java qui a renvoyé toutes les exceptions en cas d'échec, donc je pouvais voir, par exemple une exception trhown par un pilote Oracle indiquant qu'une contrainte unique a été violée (celle que j'ai mentionnée dans ma réponse, en fait; c'était hors de la paresseux, je suppose). J'ai décidé de ne pas essayer d'analyser cela, car cela lierait le consommateur à un conducteur de DB sur le backend, qui n'a pas de sens. D'autre part, avoir un message indiquant que la règle spécifique de l'entreprise violée aurait été très utile pour notifier l'utilisateur final.
(Disclaimer: Dans mon expérience, j'ai beaucoup travaillé avec exposition / consommation de services entre les environnements, où la fonctionnalité intégrée dans quelque chose comme WCF n'est pas toujours utile et que l'on n'a pas toujours de contrôle sur le client. consommer le service.) p>
De plus en plus dans mes conceptions de service, j'ai déplacé vers un système de demande / de réponses. (En fait, j'ai fait une forte utilisation du bibliothèque AGATHA-RRSL à cet égard .) Dans cette conception, j'ai un Continuer avec ce que vous pensez, que aller plus loin, j'aime aussi inclure quelques éléments dans le L'idée est que le service lui-même devrait jamais em> lancer une exception brute. Quiconque consomme le service devrait toujours s'attendre à obtenir une réponse valide, même si cette réponse indique une défaillance d'une sorte. Cela devrait s'attendre à ce que certaines informations de base reviennent à chaque fois et savent comment gérer cette information. P> Baserequest code> objet et un objet Baseresponse code> à partir de laquelle toutes les types de demande et de réponse héritent. P>
ServiceResult Code> Classe servirait bien comme le début d'un tel Baseresponse code>. Il n'a pas nécessairement besoin de l'exception réelle, mais quelques éléments que j'ai tendance à inclure sont: p>
bool code> indiquant le succès ou l'échec de toute demande, même un qui renvoie des résultats réels sur le succès. Li>
ilist <> code> de message message code> des objets, qui contiennent eux-mêmes un type de message d'une sorte (info, avertissement, erreur, etc.) ainsi que le message Texte (et peut-être un texte de message convivial supplémentaire pour les besoins d'affichage de l'interface utilisateur), la trace de pile si pertinente, etc. li>
ol>
Baserequest code> tel que l'utilisateur originaire, l'hôte, etc. p>
Merci pour votre réponse. C'est une sorte de l'idée que j'allais vers (ne jamais laisser le service lancer une exception brute). Le système de demande / réponse a l'air assez soigné, mais peut I> être trop pour mon système actuel. Quoi qu'il en soit, je pense que c'est vraiment soigné et je garderai ça à l'esprit.
Oui, la classe Aussi, n'atteignez pas exception , il peut faire du mal à trouver des bugs à trouver. p> ServiceResult Code> est une bonne idée, mais je n'inclurais pas d'exception, il y a des fois que vous souhaitez signaler des erreurs, mais vous ne voulez pas / devez créer / lancer / lancer / lancer / lancer / lancé / Attraper une exception, mais j'inclureais une collection de messages d'erreur ou un type d'erreur indiquant ce qui a mal tourné, quelque chose comme membresCreatestatus . p>
Pourquoi n'aurais-je pas attraper code> si j'essaie littéralement saisir toutes les exceptions i> à ce stade du service? Je sais dans un autre code, vous devriez prendre des exceptions spécifiques, mais que le service a besoin d'avaler toutes les erreurs, cela n'a pas de sens?
@Thecloudlesssky: Pourquoi avez-vous besoin d'avaler toutes les exceptions?
Afin que le consommateur ne soit pas obligé d'être jonché d'essayer / attraper. J'aime l'idée que le consommateur n'a pas à s'inquiéter des exceptions, mais peut gérer les messages d'erreur en conséquence.
@Thecloudlesssky: Je recommanderais de remplacer la méthode onexception sur votre contrôleur ou d'utiliser une exceptionFilter, de sorte que vous n'avez pas besoin d'essayer / attraper toutes les actions. Le problème de la déglutition Toutes les exceptions est que vous indiquez essentiellement que toutes les conditions d'erreur sont acceptables, alors qu'il y a clairement des cas, vous ne voulez pas que l'application continue à fonctionner.
Vrai. J'utilise Elmah pour enregistrer toutes les erreurs non capturées et fournira une sorte d'interface pour toutes les erreurs.
Gardez à l'esprit que l'un des principaux avantages d'une architecture orientée du service est le découplage des composants du système. Plus les couches d'appel doivent connaître le service plus étroitement couplé les couches deviennent. Suite à cette logique, il vaut mieux que la couche d'appel peut savoir le moins possible sur l'erreur, tout cela doit savoir, c'est que l'appel de service a échoué. P>
La couche d'appel est-elle vraiment em> besoin de savoir pourquoi le service a échoué? Que peut-il vraiment faire à ce sujet? Est-ce juste pour que vous puissiez montrer un meilleur message à l'utilisateur? Dans ce cas, l'utilisateur se soucie-t-il vraiment des détails? Il est facile de penser que l'utilisateur veut en savoir plus, simplement parce que vous comme le développeur. Mais les développeurs devraient obtenir des informations sur les messages d'erreur à partir de journaux et non des messages d'utilisateur final. P>
@James - Yeah Great Point. C'est ce que j'ai essayé de comprendre. Est-ce que le consommateur vraiment i> se soucie de pourquoi i> quelque chose a échoué (autre que la validation du cours ...)? Donc, dans votre esprit, retournerait un bool code> suffisant?
D'autre part, donner plus d'informations à l'utilisateur accélère le développement. Le programmateur utilisateur n'a pas à appeler le fournisseur de services au téléphone à chaque fois que le service désobéit avec la question "Qu'est-ce que j'ai fait de mal à cette heure?"
@James. Je suis d'accord sur ce que vous dites de découplage. Cependant, parfois, l'utilisateur doit savoir et plus important encore, le développeur a besoin de savoir ce qui s'est mal passé. Je ne veux pas dire des erreurs internes dans le service (bugs, conditions rares, etc.). Mais communs, les conditions d'erreur attendues devraient faire partie de l'API et documentées et notifiées en conséquence. Vous ne pouvez pas toujours compter sur les journaux pour cela (demandez-vous à Facebook de vous montrer leurs journaux afin que vous sachiez si une demande a échoué en raison d'un problème à la fin ou que vous avez publié une demande incorrecte / invalide et que vous avez un bug que vous avez besoin fixation?).
(suite) L'échec de l'échec en silence est une idée en silence car il renvoie des messages ou des codes d'erreur incorrecte / faux (je me souviens de Twitter utilisé pour renvoyer un code d'état HTTP 403 qui semblait indiquer un problème dans l'autorisation, mais a vraiment été causée par leurs serveurs en cours d'exécution. hors capacité). Encore une fois, je pense qu'un service devrait renvoyer des messages / codes d'erreur significatifs et les faire partie de son API. Il suffit de donner le niveau de détail nécessaire au consommateur.
Je ne recommanderais certainement pas d'échouer silencieusement. J'utilise WCF, auquel cas une défaillance est indiquée par une exception de défaut. La valeur de retour est toujours laissée libre à utiliser pour une valeur de retour normale. Si votre mécanisme de communication de service ne prend pas en charge les exceptions, je suis d'accord Utiliser une valeur de retour pouvant indiquer le succès / l'échec - mais je n'aime pas ce modèle personnellement.
(suite Les exemples indiqués ci-dessus où des codes d'erreur supplémentaires sont suggérés sont des exemples où il s'agit davantage du bénéfice du développeur plutôt que de l'utilisateur. Si vous avez le contrôle du service, ceux-ci peuvent tous être triés à l'aide de la journalisation, si vous n'avez pas de contrôle du service, il y a peut-être une justification. Je pense qu'un meilleur modèle dans une fonction publique largement utilisée peut être de proposer une version de développement à tester, cela expose peut-être des journaux, ou d'autres codes d'erreur. Mais dans le code de production, j'avais toujours tendance à éviter en fonction des codes d'erreur pour conduire le comportement si possible.
@James. Assez juste. Je ne sais pas grand chose à propos de la WCF, mais si cela vous permet d'utiliser des exceptions indigènes et de sauver du travail, cela pourrait fonctionner très bien dans de nombreux scénarios. Notez cependant que cela fait augmenter i> couplage entre le service et le consommateur en faisant des hypothèses qui ne sont peut-être pas toujours vraies. La plupart des services de tierces parties qui fonctionnent sur Internet (Facebook, Twitter, Flickr, la plupart des API Google, etc.) incluent des messages d'erreur (je veux dire des objets / des structures avec des données sur les erreurs, pas nécessairement des codes d'erreur) dans leurs réponses.
C'est une très mauvaise idée d'attraper toutes les exceptions. Vous ne attrapez que ce que vous pouvez raisonnablement gérer. Vous ne pouvez pas gérer toutes les exceptions, alors pourquoi l'attrapez-vous? Pour empêcher une trace de pile?
Si vous ne voulez pas que vos utilisateurs voient une trace horrible de pile, je l'obtiens, mais vous voulez que cela meure et moursiez horriblement pour que quelque chose ne soit pas corrompu. P>
Disons que ce service a jeté une exception exceptionnelle, vous venez de l'attraper et ne saura pas si votre application fuit ou non une mémoire comme un tamis ou une allocation incorrecte des objets importants. P>
C'est une mauvaise chose. P>
Si vous ne voulez pas que votre utilisateur voie de voir ce qui n'allait pas, vous devriez changer votre capture à dire: P>
catch (Exception e)
{
//send it to yourself, log it. Just don't swallow it.
LogErrorAndEmailDevTeam(e);
throw new SaveFailedException("We're sorry. \n" +
"It's not your fault, but something bad happened.\n\n" +
"We've been notified and will fix it as soon as possible.");
}
Merci pour votre contribution. Comme je l'ai dit au bas de l'OP, je pensais déjà à enregistrer l'exception attrapée puis en passant de là. Quelques questions: disent que j'ai une unité de travail de travail et que de commettre est appelée à la fin de toutes les actions du service, serait-il souhaitable d'essayer / attraper le commit sur l'unité de travail ou, comme vous l'avez dit, le laisser mourir une mort horrible car ce serait un cas exceptionnel? En outre, utiliserait ServiceResult Code> Travailler avec renversement Messages i> comme je l'ai dit que j'ai mentionné dans les autres messages? Merci!
Vous avez oublié de passer l'exception originale au constructeur de la nouvelle exception.
@Max Nope, c'était exprès. Le DevTeam obtient l'exception réelle lorsqu'ils ouvrent leur courrier électronique ou sont alertés via le journal; L'utilisateur reçoit simplement une exception connue contenant un message d'erreur amical.