Dernièrement, je me suis retrouvé dans de nombreux arguments avec mon patron sur la gestion des exceptions dans notre application Web (une application C # ASP.NET MVC). P>
Fondamentalement, les conversations vont quelque chose comme ceci: p>
BOSS: "Il y a quelque chose qui ne va pas avec notre programme, la base de données du client X a diminué aujourd'hui et tout le monde voit la page d'erreur." P>
moi: "La plupart du temps chaque page de l'application utilise la base de données pour quelque chose (sauf la page d'erreur), il n'existe aucune alternative raisonnable autre que de montrer la page d'erreur." P>
BOSS: "Notre application doit être plus résiliente - la partie de l'application qui ne nécessite pas d'accès à la base de données doit toujours fonctionner." P>
Souvent, les cas sont aussi extrêmes que cela, mais parfois nous rencontrons dans un cas où nous nous intégrons à un autre service où nous pouvons toujours afficher d'autres parties de la page ou compléter l'opération, même si Des parties ultérieures du code doivent utiliser ultérieurement les résultats de l'opération pouvant avoir échoué. S'il y a beaucoup de points d'échec possibles, cela peut transformer en un code extrêmement ingérable. P>
En général, pour une application Web «normale» (pas de la mission-critique, etc.) Combien de temps les "bons" développeurs passent-ils à essayer de rendre leur code suffisamment résilient pour gérer ce genre de situations. Mon patron semble penser que le code devrait être capable de manipuler presque toutes les situations (ne pouvez-vous pas attraper une exception?). Je ne vois pas comment cela peut être économique quand il y a de nombreux points d'échec possibles. P>
8 Réponses :
Je laisserais au patron de décider. Dites-lui une estimation dans les heures combien de temps il faudrait pour rendre l'application "résiliente" et il décidera si cela vaut la peine d'investir. P>
C'est en fait l'approche que je prends habituellement. Il est généralement assez efficace que je percevoie parfois le sentiment que mes estimations sont trop transmises et que cela devrait être une question de "attraper une exception" qu'elle est rarement.
Cela dépend ... De nombreuses pages Web affichent et rendent des "widgets" individuels. Chaque widget peut s'appuyer sur une source de données différente ... Certains peuvent même être complètement statiques. Je suis d'accord avec votre patron du point de vue que si le chargement d'un widget échoue pour une raison quelconque, nous devrions toujours essayer de charger le reste de la page. Un widget échoué ne doit pas empêcher l'utilisateur d'interagir avec le reste du site. P>
Comme exemple de Stackoverflow, disons que la section "associée" à droite de ces réponses ne parvient pas à charger ou que le pied de page ne parvient pas à charger pour une raison quelconque. Je dirais qu'il est préférable de simplement afficher un message d'erreur dans ces portions de la page et de charger toujours votre question et les réponses, car elles ne doivent pas être affectées. P>
Maintenant, il existe des situations lorsque le code charge tous ces "widgets" échoue ... ou une source de données utilisée par votre cadre échoue. Dans ces cas, je pense qu'il est raisonnable d'afficher une page d'erreur générique ... Si le Cadre ou le "widget" du code de chargement échoue pour une raison quelconque, c'est en effet un cas exceptionnel qui ne peut probablement pas être traité. p>
En résumé, je suis surtout d'accord avec votre patron et affirmez que, autant de cas d'erreur que possible, devraient être considérés et manipulés ... et que nous devrions afficher tout ce qui est possible pour l'utilisateur. P>
Je suppose que je serais un peu inquiet que vous perdiez des bases de données avec une fréquence qui cause cette question surviennent. Même dans les applications critiques non-missionnaires, si vous perdez une DB plus d'une fois par semaine, je verrais ce que je pouvais faire de ce que je pouvais faire de l'amélioration de cela avant que je m'inquiétait de façonner les moyens de sortir de la question de l'utilisateur final de l'application. . p>
Cela étant dit, les meilleures pratiques de mon entreprise incluent le codage de sorte que quelque chose comme une erreur de base de données ne fonctionne pas gracieusement sur l'utilisateur se termine à un message "Impossible de connecter" le message dans la sortie plutôt qu'une erreur complète de type 404 de 404. J'ai constaté que cela n'ajoute vraiment pas plus de quelques minutes au processus de codage et la valeur de ne pas générer l'utilisateur vaut bien le "coût" p>
Peut-être que l'exemple de la base de données n'était pas un bon car il est un peu extrême. Il s'agit généralement d'intégrer avec des services Web tiers et similaires.
La plupart des applications que j'ai travaillé à ce sujet sont fortement pilotées par des données ont redirigé vers une page d'erreur personnalisée lorsque la base de données principale (c'est-à-dire celle qui alimente 99% des pages) est en panne. (Vous voulez vous montrer un écran personnalisé cependant, ne les laissez pas simplement obtenir la page d'erreur de serveur) p>
Pour des services externes tels que frapper un serveur SMTP ou une base de données qui n'est pas utilisé par une grande partie du reste de l'application, nous aurons généralement du code qui affiche simplement des commentaires sur la page si le service / la base de données est en panne / inaccessible. p>
C'est vraiment en place le client / intervenant, déterminez simplement ce qu'ils veulent avoir lieu lorsque la base de données est en panne et le faire pour eux. Ça prendra du temps mais cela ne devrait pas conduire à une application non satinée ou à une autre horreur codante. P>
Votre patron aurait dû discuter avec le client avant de créer l'application. Les termes tels que "non critiques" doivent être définis comme un nombre (pourcentage de disponibilité). Certaines applications nécessitent différentes parties de l'application pour avoir des nombres différents de disponibilité (ce que votre patron suggère) et les applications sont en place dans son ensemble (comment cela fonctionne maintenant). L'application "résiliente" sera probablement écrite d'une manière différente (lecture distribuée / async écrit, etc.) que l'application "normale", de sorte qu'elle (probablement) être difficile de convertir l'application "normale". p>
Un bon patron discute d'une bonne SLA avec le client de l'application et le raconte aux développeurs avant le début du développement. De l'autre côté, un bon développeur devrait se plaindre par son patron, sur des exigences incomplètes avant de commencer le développement. Lorsque rien n'est mentionné sur la disponibilité dans les exigences, les exigences sont incomplètes. p>
Lorsque les exigences de disponibilité ou d'évolutivité d'une application existante changent de manière significative, il pourrait être très difficile de modifier une demande rentable. Lorsque vous avez un bon patron, ces exigences ne changeront considérablement que lorsque l'application a beaucoup plus de succès, puis initialement estimée (comme 100 fois plus d'utilisateurs). Dans ce cas, le succès énorme générera suffisamment d'argent pour rendre la situation rentable de réécrire d'énormes parties de l'application. p>
Ceci est probablement une réponse plus académique étant donné que vous avez hérité de ce code. Si vous utilisez, ou plutôt si quelqu'un avait utilisé, le motif Microsoft.ProCes.EnterprisElibrary.EnterprisElibrary.ExceptionThandling Modèle exceptionnel est vraiment facile de passer de la page d'erreur (en lancant une exception) pour alimenter des exceptions et afficher des grilles vides, des listes, etc.
Vous pouvez déjà être conscient de ce petit motif, mais ici, il est de toute façon: p>
Probablement vous montrez simplement une page d'erreur générique lorsqu'un ensemble de données vide avec et un message d'erreur «convivial».
Donc, par exemple, si vous affichez une liste d'utilisateurs / messages / date mais le service où vous collectez-le est en panne, vous pouvez probablement montrer un ensemble vide. p>
donc au lieu de montrer: p> Votre application ne fonctionnera toujours pas, car les données ne sont pas disponibles, mais au lieu de la jeter à la face d'utilisateur final, vous pouvez mettre un espace réservé sans données. P> Ceci varie beaucoup en fonction de ce que vous utilisez, mais en termes généraux, cela pourrait être aussi simple que: p> que Est-ce que vous initialisez votre liste ou quelle que soit la structure de quelque chose de vide, puis remplissez-le avec le service, et s'il échoue (la liste restera vide) Ajouter un message d'erreur (utilisateur convivial s'il vous plaît) et connectez-vous l'exception. p> p>
Je pense qu'une fois que nous commençons à pratiquer quelque chose, construire des applications résilientes pour par exemple, nous passons peu de temps à classer en catégorisation à la normale ou à la mission essentielle et à créer de la construction élastique, ha, évolutive, etc. Application pour faire face aux défaillances. P>
Plus d'effort est certainement nécessaire pour assurer des applications résilientes, mais une fois que cette connaissance est acquise et mise en œuvre, La prochaine fois, cela devient beaucoup plus facile. Des bibliothèques génériques telles que le disjoncteur de printemps ou de Netflix sont déjà disponibles, ce qui, sur l'intégration, peut traiter avec des échecs gracieusement dans certains aspects. Réessayer une opération idempotente est également facile à mettre en œuvre. P>
Pour faire une application utilisable, il doit être disponible et fiable. Presque toutes les applications (autres que les utilitaires de bureau autonomes) sont 2 applications à plusieurs niveaux, ce qui signifie que l'appel réseau sera présent et tous les problèmes connexes N / W. Donc, une fois que vous avez commencé à pratiquer, vous commencerez à mettre en œuvre des modèles de résilience dans toutes les applications. P>
La question elle-même est (maintenant) hors sujet (remarquez qu'il a été publié il y a plus de 7 ans). Même la réponse acceptée est simplement une opinion. Veuillez ne pas ajouter à cela avec plus d'opinion (le vôtre étant de la variété N-Tier, et de ne pas envisager une architecture de microservice moderne). En outre, j'ai supprimé le lien vers votre blog - ce n'est pas l'endroit pour cela.
Dans cette économie, faites ce que vous voulez vous dire.
L'exemple de la base de données est peut-être un peu extrême et trop simplifié. Fondamentalement, nous avons des pages qui interagissent avec plusieurs services tiers - géocodage / Facebook / etc ... Il peut y avoir plusieurs appels à un service donné effectué dans l'exécution d'une page. Les résultats d'un service peuvent être transmis plus tard à un autre ou utilisés dans le rendu de la page. En supposant que l'une d'entre elles puisse être en panne et essayer de produire une production sensible dans tous les cas semble devenir très difficile en présence de nombreux services.
Quelle est la page d'erreur utile? Si un instant, vous étiez un utilisateur final, que voudriez-vous voir?