Fehlerbehandlung Sollte ich eine Ausnahme auslösen? Oder handle an der Quelle?

8

Ich habe diese Art von Format

asp.net MVC-Ansicht - & gt; Dienstschicht - & gt; Repository.

Die View ruft also die Service-Schicht auf, in der sich die Business- / Validierungslogik befindet, die ihrerseits das Repository aufruft.

Jetzt hat meine Service-Layer-Methode normalerweise einen bool-Rückgabetyp, so dass ich true zurückgeben kann, wenn die Datenbankabfrage gut abgelaufen ist. Oder wenn es fehlgeschlagen ist. Dann wird dem Benutzer eine generische Nachricht angezeigt.

Ich werde natürlich den Fehler mit Elmah protokollieren. Ich bin mir jedoch nicht sicher, wie ich zu diesem Punkt kommen soll.

Wie im Moment hat mein Repository void Rückgabetypen für Update, erstellen, löschen.

Sagen Sie also, wenn ein Update fehlschlägt, sollte ich eine try / catch in meinem Repository haben, die den Fehler auslöst, Dann fängt meine Service-Schicht es ab und tut elmah Signalisierung und gibt false zurück?

Oder sollen diese Repository-Methoden einen "bool" zurückgeben, den Fehler im Repository abfangen und dann "true" oder "false" an die Service-Schicht zurückgeben, was wiederum "true" oder "false" zurückgibt die Aussicht?

Ausnahmebehandlung verwirrt mich immer noch, wie man mit den Fehlern umgeht und wann man wirft und wann man den Fehler fängt.

    
chobo2 29.08.2009, 21:01
quelle

4 Antworten

15

Als Faustregel verwende ich immer:

  • Bei niedrigen Ebenen wird geworfen, wenn eine Operation aufgrund außergewöhnlicher Umstände nicht abgeschlossen werden kann.
  • In mittleren Schichten fangen Sie mehrere Ausnahmetypen ab und fassen sie in einem einzelnen Ausnahmetyp um.
  • Behandeln Sie Ausnahmen im letzten verantwortlichen Moment.
  • DOKUMENT!

Hier ist ein Beispiel in Pseudocode für eine mehrschichtige ASP.NET MVC-App (UI, Controller, Logik, Sicherheit, Repository):

  1. Der Benutzer klickt auf die Senden-Schaltfläche.
  2. Die Controller-Aktion wird ausgeführt und in die Logische (Business-) Schicht gerufen.
  3. Logic-Methode ruft mit den aktuellen Benutzeranmeldeinformationen in Security auf
    • Benutzer ist ungültig
      • Sicherheitsschicht löst SecurityException
      • aus
      • Die logische Ebene wird abgefangen und in LogicException mit einer allgemeineren Fehlermeldung umbrochen
      • Der Controller fängt LogicException ab und leitet zur Error-Seite um.
    • Der Benutzer ist gültig und die Sicherheit gibt
    • zurück
  4. Die Logikschicht ruft das Repository auf, um die Aktion abzuschließen
    • Das Repository schlägt fehl
      • Das Repository löst die RepositoryException
      • aus
      • Die logische Ebene wird abgefangen und in LogicException mit einer allgemeineren Fehlermeldung umbrochen
      • Der Controller fängt LogicException ab und leitet zur Error-Seite um.
    • Repository ist erfolgreich
  5. Logische Ebene gibt
  6. zurück
  7. Der Controller wird zur Ansicht "Success" umgeleitet.

Beachten Sie, dass die Logikebene nur einen einzelnen Ausnahmetyp auslöst - LogicException. Alle untergeordneten Ausnahmen, die aufsteigen, werden abgefangen und in eine neue Instanz von LogicException eingepackt, die ausgelöst wird. Das gibt uns viele Vorteile.

Zunächst ist der Stack-Trace zugänglich. Zweitens müssen sich Anrufer nur mit einem einzelnen Ausnahmetyp und nicht mit mehreren Ausnahmen befassen. Drittens können technische Ausnahmemeldungen zur Anzeige für Benutzer massiert werden, während die ursprünglichen Ausnahmemeldungen beibehalten werden. Schließlich kann nur der Code, der für die Behandlung von Benutzereingaben zuständig ist, wirklich wissen, was die Absicht des Benutzers war, und bestimmen, welche Antwort angemessen ist, wenn eine Operation fehlschlägt. Das Repository weiß nicht, ob die Benutzeroberfläche die Fehlerseite anzeigen oder den Benutzer mit anderen Werten erneut versuchen soll. Der Controller weiß das.

Übrigens sagt nichts, dass Sie das nicht tun können:

%Vor%     
Will 29.08.2009, 21:55
quelle
2

Die Rückgabe eines Fehlercodes (oder Erfolgscodes) ist oft der bessere Weg. Ausnahmen haben einen großen Vorteil gegenüber der Rückgabe von Codes oder der Unterdrückung von Fehlern im Hintergrund: Sie können sie nicht einfach ignorieren!

Missbrauche keine Ausnahmen für die einfache Flusskontrolle - das wäre das Dümmste, was zu tun ist.

Aber wenn eine Ihrer Funktionen wirklich zu einem "außergewöhnlichen" Problem führt, dann werfen Sie definitiv eine Ausnahme. Der Anrufer muss dann entweder explizit damit umgehen und so wissen, was vor sich geht, oder es bombardiert ihn.

Es ist gefährlich, nur einen Fehlercode zurückzugeben, da der Anrufer den Code vielleicht gar nicht erst inspiziert und möglicherweise trotzdem weitermachen könnte - selbst wenn in der Logik Ihrer App etwas nicht stimmt und behandelt werden muss.

Also: missbrauche keine Ausnahmen, aber wenn eine echte Ausnahme passiert, die den Anrufer dazu veranlasst, etwas dagegen zu tun, würde ich definitiv diesen Mechanismus zur Signalisierung von Ausnahmezuständen empfehlen.

Was die Behandlung von Ausnahmen betrifft: Behandle diejenigen, mit denen du wirklich umgehen kannst. Z.B. Wenn Sie versuchen, eine Datei zu speichern und eine Sicherheitsausnahme zu erhalten, zeigen Sie dem Benutzer einen Dialog an, in dem Sie nach einem anderen Speicherort gefragt werden (da er möglicherweise keine Berechtigungen zum Speichern an der gewünschten Stelle hat).

Aber Ausnahmen, mit denen Sie nicht wirklich fertig werden können (was wollen Sie eigentlich wegen einer "OutOfMemory-Ausnahme" machen?) sollten nicht verändert werden - vielleicht kann ein Anrufer weiter oben im Call-Stack kann Behandle diese - oder nicht. Marc

    
marc_s 29.08.2009 21:58
quelle
1

Ich denke dabei gern an die Ausnahmebehandlung: Sie definieren Ihre Methodensignatur, was Sie erwarten. Wenn Sie das nicht können, müssen Sie eine Ausnahme auslösen. Wenn Sie also erwarten, dass etwas aufgrund der eingegebenen Daten fehlschlägt (den Umgebungsstatus ignorierend), muss Ihre Methodensignatur angeben, ob eine Operation erfolgreich war oder fehlgeschlagen ist. Wenn Ihre Methode jedoch nicht erwartet, dass sie auf der Grundlage der von Ihnen eingegebenen Eingabe fehlschlägt (auch wenn alle anderen Umgebungsbedingungen ignoriert werden), ist eine Ausnahme in Ordnung, wenn die Methode fehlschlägt.

Betrachten Sie diese zwei APIs:

%Vor%     
Charles Prakash Dasari 29.08.2009 21:30
quelle
0

Erstens gibt es keinen Weg, und es gibt keinen perfekten Weg, also überlebe ihn nicht.

Im Allgemeinen möchten Sie Ausnahmen für Ausnahmefälle verwenden (Ausnahmen verursachen einen Leistungs-Overhead, so dass eine Überbeanspruchung insbesondere in "loopy" -Situationen einen Einfluss auf die Performance haben kann). Nehmen wir an, das Repository kann aus irgendeinem Grund keine Verbindung zum Datenbankserver herstellen. Dann würden Sie eine Ausnahme verwenden. Wenn das Repository jedoch eine Suche nach einem Objekt nach ID ausführt und das Objekt nicht gefunden wird, sollten Sie null zurückgeben, statt eine Ausnahme auszulösen, die besagt, dass das Objekt mit der ID x nicht existiert.

Das Gleiche gilt für die Validierungslogik. Da es validiert wird, wird angenommen, dass die Eingabe manchmal nicht validiert wird. In diesem Fall wäre es gut, false aus dem Validierungsdienst zurückzugeben (oder vielleicht einen komplexeren Typ mit einigen zusätzlichen Informationen, warum es nicht validiert wurde). Aber wenn die Validierungslogik prüft, ob ein Benutzername verwendet wird oder nicht, und dies aus irgendeinem Grund nicht möglich ist, würden Sie eine Ausnahme auslösen.

  

Also sag, wenn ein Update fehlschlägt sollte ich   versuche es in meinem Repository   wirft den Fehler, Dann mein Service   Schicht fängt es und tut Elmah   Signalisierung und gibt false zurück?

Warum sollte das Update fehlschlagen? Gibt es einen absolut guten Grund dafür, dass dies Teil des normalen Prozesses ist? Dann werfen Sie keine Ausnahme, wenn es aus einem seltsamen Grund passiert (nehmen wir an, dass etwas den Datensatz vor der Aktualisierung entfernt hat), dann ist eine Ausnahme logisch. Es gibt wirklich keine Möglichkeit, von dieser Situation zu erholen.

    
olle 29.08.2009 21:12
quelle