Darstellung von Geschäftsregeln mit Ausnahmen

16

Ich weiß, dass es teuer ist, aber (IMO) ich glaube, dass es eine sehr gute Praxis ist. Ich spreche von Regeln wie zum Beispiel: Sie können keine Rechnung speichern, wenn Sie kein Verkäufer sind. In diesem Fall wird eine Ausnahme ausgelöst, die besagt, dass Sie nicht autorisiert sind.

Ein anderer Ansatz wäre, Objekte mit einem Status oder ähnlichem zu haben

Gibt es einen anderen Ansatz? wie stehen Sie dazu?

sebagomez
quelle

Antworten:

15

Wenn Sie damit meinen, einzelne Geschäftsregelprüfungen mit Ausnahmen darzustellen, halte ich das nicht für eine sehr gute Idee. Oft müssen Sie mehr als eine ausgefallene Bedingung melden und müssen nicht bei der ersten aufhören.

Andererseits glaube ich, dass es eine gute Praxis ist, alle Regeln zu überprüfen und dann eine Ausnahme mit der Zusammenfassung auszulösen.

matiash
quelle
1
Genau so gehe ich mit meinen Apps um. Die Verwendung von FluentValidation, um mir das Leben zu erleichtern, und die ValidateAndThrow-Methode ersparen mir den Tag.
Matteo Mosca
In einer UI-App stimme ich vollständig zu, aber in einer Service-Tier-App würde eine Ausnahme generiert, wenn mir ein Objekt übergeben würde, das nicht den Geschäftsregeln entspricht. Wenn Sie die beiden in Kombination verwenden, fügen Sie manchmal eine Validierungsfunktion oder einen komplexen Fehler hinzu, wie es matiasha im letzten Satz beschreibt.
Bill
8
Wirft eine domänenspezifische Ausnahme. Dies ermöglicht es Ihnen, zwischen unseren und nicht-unseren höher zu trennen .
@ Thorbjørn Ravn Andersen +1 "domain specific" tolle Ergänzung
Justin Ohms
1
@JamesPoulson Es kann ausreichen, JamesPoulsonExceptioneine Unterklasse von zu erstellen RuntimeExceptionund dann die ursprüngliche Ausnahme als cause. Sie können dann einfach sagen, if (exception instanceof JamesPoulsonException)... zu unterscheiden. Verwenden Sie die getCause()Methode, um die ursprüngliche Ausnahme zu erreichen.
9

In dem Beispiel, das Sie uns gegeben haben, halte ich das Auslösen einer Ausnahme für eine schlechte Idee. Wenn Sie wissen, dass der Benutzer vor Arbeitsbeginn nicht autorisiert ist und Sie ihm dennoch erlauben, eine Funktion auszuführen, und ihn dann mit einer Meldung schlagen, nachdem er die Aufgabe bereits abgeschlossen hat, ist dies nur ein schlechtes Design.

Die Verwendung von Ausnahmen zur Durchsetzung von Geschäftsregeln ist kein gutes Konzept.

Walter
quelle
Was ich von dem verstehe, was Sie gesagt haben, ist, dass Sie mit der Benutzeroberfläche nicht einverstanden sind. Das ist ok für mich. Ich stimme Ihnen zu, dass eine viel freundlichere Benutzeroberfläche nicht zulässt, dass Sie versuchen, etwas zu aktualisieren, was Sie nicht zulassen. Dies bedeutet jedoch nicht, dass die Überprüfung und Ausnahmebedingung im Geschäftskern nicht erforderlich ist. Im Gegenteil, ich glaube, sie sind ein Muss. Sie müssen sicherstellen, dass eine schlecht programmierte Benutzeroberfläche keinen BL-Missbrauch zulässt.
Fede
8
@Fede: Es ist eine Frage der Trennung von Bedenken. Die Benutzeroberfläche ist dafür verantwortlich, die Absichten des Benutzers zu erfassen und Feedback aus der Business-Schicht zu melden. Die Aufgabe der Business-Schicht besteht darin, die von der Benutzeroberfläche gesammelten Informationen zu analysieren, sie zu analysieren und entweder an die Benutzeroberfläche Bericht zu erstatten und / oder die Datenschicht aufzufordern, einige Daten beizubehalten. Es sollte nur eine lose Kopplung zwischen diesen Schichten geben. Ausnahmen sind eine schlechte, schlechte Herangehensweise an die lose Kopplung. Dies bedeutet nicht nur, dass tatsächliche Klassen zwischen den Layern geteilt werden, sondern es wird auch ein Mechanismus aufgerufen, der unerwartete Fehler behandeln soll.
Adam Crossland
@Adam - Gut gesagt und genau auf den Punkt.
Walter
1
@Adam - Folgen Sie Ihnen nicht bei der Trennung von Problemen. Ich erwarte nicht, dass jemand in der Benutzeroberfläche eine CustomerNameInLowercaseException behandelt (bitte, ich hoffe auch, dass es keine Ausnahme gibt!). Sie können nur eine generische ValidationException behandeln. Außerdem bin ich zu 100% damit einverstanden, dass die Benutzeroberfläche nur Informationen sammelt und all das. Was ich bereits gesagt habe, ist, dass die BL nicht davon ausgehen sollte, dass alle Eingaben in Ordnung sind, unabhängig davon, was Sie in der Benutzeroberfläche tun. Es ist nur eine defensive Programmierung.
Fede
@Fede: Es ist die Aufgabe der Business-Schicht, sicherzustellen, dass alle Eingaben in Ordnung sind. Wenn die Benutzeroberfläche dies tut, implementiert sie die Geschäftslogik. Nun, wenn es der Fall ist , dass ein Eingabefeld auf Ziffern beschränkt ist und die BL sieht Alpha - Zeichen, mit allen Mitteln wirft eine Ausnahme . Wenn eine Komponente ungültige Eingaben von einer anderen Komponente empfängt, ist das Auslösen einer Ausnahme logisch und richtig. Die Schnittstelle ist defekt und das System ist defekt. Die Validierung von Eingaben unterscheidet sich jedoch stark von der Ausführung von Geschäftslogik. Zwei sehr unterschiedliche Dinge.
Adam Crossland
5

Ich verstehe nicht, welchen Wert das Auslösen einer Ausnahme für die Erstellung einer guten Geschäftslogik hat. Es gibt Dutzende von Ansätzen zur Handhabung von Geschäftslogik, bei denen kein System verwendet wird, mit dem unerwartete Bedingungen beim Betrieb eines Systems behoben werden können.

Es wird erwartet dass in der Geschäftslogik die Bedingungen nicht erfüllt werden. Das ist der Grund dafür, dass es an erster Stelle steht, und Sie möchten nicht auf denselben Mechanismus zurückgreifen, der unerwartete E / A-Fehler, Speicherfehler und Nullreferenzen behandelt. Dies sind Systemfehler, aber das Erkennen nicht erfüllter Geschäftsbedingungen ist der erfolgreiche Betrieb des Systems.

Darüber hinaus ist es ein System, das für unbeabsichtigte Konsequenzen reif ist. Da eine Ausnahme irgendwann abgefangen werden muss, besteht die Gefahr, dass eine neue Geschäftsregel-Ausnahme abgefangen wird, die nicht beabsichtigt ist, oder dass der Code nach Geschäftsregeln sucht, die Ausnahmen abfangen, die eigentlich nicht beabsichtigt sind dafür. Ja, diese Bedingungen können mit guten Codierungspraktiken berücksichtigt werden, aber in jedem nicht trivialen System, an dem mehr als ein Entwickler arbeitet, treten Fehler auf, und Sie müssen nur hoffen, dass es sich nicht um kostspielige Fehler handelt.

Adam Crossland
quelle
1
Ich stimme zu, Ausnahmen werden als Ausnahmen bezeichnet, da nicht erwartet wird, dass sie auftreten. Auf der anderen Seite ist die Durchsetzung von Geschäftsregeln in Ihrer Serviceebene mit einer Ausnahme nicht unbedingt falsch. Sie erwarten nicht, dass es verwendet wird. Sie erwarten, dass der Client nur Vorgänge aufruft und nur Daten sendet, die die gültigen Bedingungen erfüllen. Sie möchten jedoch eine Schutzschicht einbauen, da Sie wissen, dass auch beim Client-Codieren Fehler auftreten können. So ähnlich wie bei der Verwendung von Fremdschlüsseleinschränkungen in einer Datenbank: Sie erwarten, dass Benutzer Daten korrekt einfügen und aktualisieren, aber wissen, dass sie aufgrund eines Programmierfehlers fehlschlagen könnten.
Jeremy
2

Geschäftsregeln auszudrücken ist eine Sache, sie umzusetzen eine andere

Denken Sie an die Benutzererfahrung. wenn der Benutzer nicht ein Verkäufer ist, warum sie einen Knopf geben , die ‚Rechnung erstellen‘ , sagt überhaupt ?

Steven A. Lowe
quelle
1
Nur weil du keinen Knopf drückst, heißt das nicht, dass sie dir sowieso nicht die Nachricht schicken, etwas zu tun. Überlegen Sie, wie einfach Sicherheitsregeln wären, wenn das alles wäre, was es
braucht
Wenn der Benutzer kein X ausführen darf, geben Sie ihm keine Schaltfläche mit der Aufschrift "X ausführen". Die beste Sicherheit ist Unwissenheit - erzählen Sie dem Benutzer nichts über Dinge, die er nicht tun kann;)
Steven A. Lowe
1

Das hängt ganz davon ab, was getan wird.

Was ist das tatsächliche Verhalten, das Sie wollen? Wenn jemand seine eigenen Informationen eingibt, ist eine Ablehnung und ein Dialogfeld mit der Meldung "Das können Sie nicht" wahrscheinlich korrekt. Wenn es sich um eine Dateneingabeperson handelt, die von einem Stapel von Formularen aus arbeitet, ist wahrscheinlich auch ein Dialogfeld hilfreich, und die Dateneingabeperson kann die ungültigen Formulare in einem speziellen Stapel ablegen. Wenn Sie die Stapelverarbeitung ausführen, möchten Sie die Dinge nicht zum Stillstand bringen, sondern sie markieren und zum nächsten übergehen.

Sobald Sie das Verhalten kennen, müssen Sie entscheiden, wie Sie es implementieren möchten. Ein Business Rules Checker, der eine Ausnahme auslöst, ist wahrscheinlich eine gute Idee. Das Zurückgeben und Weitergeben eines Rückkehrcodes kann auch schief gehen, und Sie möchten mit Sicherheit nicht, dass die fehlerhaften Eingaben weitergeleitet werden.

Sorgen Sie sich nicht um Leistungskosten. Im Falle einer Person, die Daten eingibt, ist dies im Vergleich zu den anderen beteiligten Zeiten trivial. Typischerweise wird der Mensch in diesem System die meiste Zeit in Anspruch nehmen. Wenn bei einem Batch-Job Ausnahmen ein Leistungsproblem darstellen, geben Sie viel zu viele fehlerhafte Datensätze ein, und in Wirklichkeit ist die Behandlung und erneute Eingabe all dieser Datensätze ein größeres Problem als die Ausnahmen.

David Thornley
quelle
0

Es ist sehr angemessen, eine robuste und gut gestaltete Ausnahme-API zu haben, die konsistent ist. Dies zur Durchsetzung von Geschäftsregeln zu verwenden, kann ebenfalls angemessen sein. Meiner Erfahrung nach ist es umso wahrscheinlicher, dass die Geschäftsregel so gehandhabt wird, je komplizierter sie ist. Es ist oft genauso einfach, wenn nicht sogar einfacher, ein System zu schreiben, in dem Ausnahmen erwartet werden, als autorisierende Verzweigungslogik zu schreiben.

Dies bedeutet, dass einfache Regeln, die in einem Satz beschrieben werden können, in der Regel präventiv oder autoritativ implementiert werden sollten, je nachdem, um welche es sich handelt. Wenn Sie jedoch eine mehrdimensionale Regel haben, für die mehr als drei oder vier Faktoren erforderlich sind (insbesondere, wenn die Auswahl dieser Faktoren auf einem oder mehreren der anderen Faktoren basiert), kann die Ausnahmecodierung möglicherweise besser verwaltet werden. In diesen Fällen müssen auf dem Logikpfad häufig Vorgängerausnahmen ausgelöst werden (es wird geprüft, warum die Aktion nicht ausgeführt werden kann), und dann (oder umgekehrt) wird die Sicherheit beeinträchtigt (um zu überprüfen, ob die Aktion autorisiert ist) ), manchmal gibt es eine autorisierende Akkumulationslogik, die überprüft werden muss (Verfügbarkeit von Nachkommen / Vorfahren, Vorläuferstatus, in den Objekte eingefügt werden müssen, usw.

Ein Vorteil dieser Art der Ausnahmebedingung besteht darin, dass Sie die Vorläuferausnahmen in mehreren Bereichen Ihres Projekts trennen und wiederverwenden können. (Dies ist die Essenz der aspektorientierten Programmierung.) Auf diese Weise kapseln Sie einen bestimmten Aspekt Ihrer allgemeinen Geschäftsregeln in einer eigenständigen und wartbaren Komponente. Im Allgemeinen entsprechen diese Komponenten 1-1 den ausgegebenen Fehlermeldungen. (Obwohl Sie manchmal eine Komponente haben, die mehrere verschiedene Ausnahmen auslöst, sollten Sie fast nie dieselbe Ausnahme von mehreren Komponenten auslösen.)

Meiner Meinung nach ist es schwieriger, Systeme zu entwerfen, die auf Ausnahmen basieren, und die anfängliche Entwicklungszeit ist länger, da Sie den Ausnahmevorgang über alle N Ebenen hinweg erstellen müssen. Im Allgemeinen sind diese Systeme jedoch wesentlich stabiler. Während es niemals möglich ist, ein System zu entwerfen, das nicht ausfällt, besteht der Vorteil eines ausnahmebasierten Entwurfs darin, dass Sie immer mit einem Ausfall rechnen. Für die meisten Menschen kann der Prozess kontraintuitiv sein. Es ist, als würde man nach dem Weg fragen und sich von jemandem sagen lassen, dass man nicht abbiegen sollte.

Justin Ohms
quelle