Ich arbeite an einem System, mit dem Administratoren Formulare definieren können, die Felder enthalten. Die definierten Formulare werden dann zur Eingabe von Daten in das System verwendet. Manchmal werden die Formulare von einem Menschen über eine GUI ausgefüllt, manchmal wird das Formular basierend auf Werten ausgefüllt, die von einem anderen System gemeldet wurden.
Für jedes Feld kann der Administrator eine Validierungsregel definieren, die die zulässigen Werte für das Feld begrenzt. Die Validierungsregeln können von "Der in das Feld eingegebene Wert muss wahr oder falsch sein" bis zu "Der in das Feld eingegebene Wert muss in Spalte A von Tabelle B in der Datenbank vorhanden sein" reichen. Der Administrator kann die Validierungsregel für das Feld jederzeit ändern.
Welcher Ort ist Ihrer Meinung nach in diesem Szenario am besten geeignet, um zu überprüfen, ob jedes Feld korrekt ausgefüllt ist? Ich habe derzeit zwei Hauptansätze im Sinn:
Option 1: Validieren im Domänenmodell
Jedes Feldobjekt würde die vom Administrator angegebene Validierungsregel enthalten. Die Field-Objekte hätten auch einen Verweis auf einen IValidator. Wenn versucht wird, den Wert des Felds festzulegen, übergibt das Feld den angegebenen Wert und die Validierungsregel an den IValidator. Wenn der angegebene Wert nicht gültig ist, wird eine ValidationException ausgelöst und in der GUI / Schnittstelle zum anderen System entsprechend behandelt.
Vorteile:
- Starker Schutz gegen Felder, denen versehentlich Werte zugewiesen wurden, die gegen die Validierungsregel verstoßen
Nachteile:
Die Datenzugriffsschicht muss in der Lage sein, die Validierung zu umgehen und Felder zu erstellen, die gegen die aktuelle Validierungsregel verstoßen. Obwohl der Administrator die Validierungsregel für ein Feld geändert hat, müssen wir weiterhin in der Lage sein, Feldobjekte basierend auf den alten Daten zu erstellen, z. B. beim Rendern eines Formulars, das vor Jahren ausgefüllt wurde. Dies könnte möglicherweise behoben werden, indem die aktuelle Validierungsregel bei jedem Speichern des Felds gespeichert wird.
In diesem Entwurf hat das Feldmodell über den IValidator eine indirekte Verbindung zur Datenzugriffsschicht / zum Datenzugriffsrepository. Die Injektion von Diensten / Repositorys in Domänenmodelle scheint allgemein verpönt zu sein .
Option 2: In einem Dienst validieren
Stellen Sie sicher, dass alle Versuche, den Wert eines Felds festzulegen, einen Dienst durchlaufen, der sicherstellt, dass die Validierungsregel gilt. Wenn die Validierungsregel verletzt wird, lösen Sie eine ValidationException aus.
Natürlich würde die Datenzugriffsschicht den Dienst nicht verwenden, wenn Feldobjekte erstellt werden, die zuvor in der Datenbank beibehalten wurden .
Vorteile:
Verstößt nicht gegen das Denken "Keine Services / Repositorys in Ihre Domain-Modelle einfügen".
Die aktuelle Validierungsregel muss nicht beibehalten werden, wenn das Feld beibehalten wird. Der Service kann einfach die aktuelle Validierungsregel für das Feld nachschlagen. Beim Betrachten von Verlaufsdaten wird der Wert des Felds nicht geändert.
Nachteile:
- Keine Garantie, dass alle Logik, die den Service zum Festlegen des Feldwerts verwenden sollte, dies tatsächlich tut. Ich sehe dies als großen Nachteil; Alles, was es zu brauchen scheint, ist jemand, der "thisField.setValue (thatField.getValue ())" schreibt, und die Validierungsregel von thisField könnte verletzt werden, ohne dass jemand klüger ist. Dies könnte möglicherweise gemindert werden, indem sichergestellt wird, dass der Wert des Felds mit der Validierungsregel übereinstimmt, wenn die Datenzugriffsschicht das Feld beibehalten soll.
Ich bevorzuge derzeit Option 1 gegenüber Option 2, hauptsächlich weil ich dies als Geschäftslogik betrachte und der Meinung bin, dass Option 2 ein höheres Risiko für die Einführung fehlerhafter Daten in das System darstellt. Welche Option bevorzugen Sie oder gibt es ein anderes Design, das besser zu diesem Szenario passt als die beiden beschriebenen Optionen?
Bearbeiten (Komplexität der Validierungen)
Die Validierungsfälle, die vorerst aufgetreten sind, sind relativ einfach. Der Feldwert muss z. B. numerisch, ein Datum, ein Datum mit einer Uhrzeit oder ein vorhandener Wert in einer Datenbankspalte sein. Ich vermute jedoch, dass die Komplexität mit der Zeit allmählich zunimmt. Zum Beispiel muss die Validierungslösung unter Berücksichtigung der Internationalisierung erstellt werden - Dinge wie Datumsangaben können in einer länderspezifischen Syntax eingegeben werden.
Ich habe mich entschlossen, vorerst mit Option 1 fortzufahren und darauf zu achten, dass dem Domänenmodell nicht zu viele Verantwortlichkeiten zugewiesen werden. Diejenigen, die sich einer ähnlichen Situation gegenübersehen, möchten möglicherweise auch die damit verbundenen Fragen überprüfen. Validierung und Autorisierung in der Schichtarchitektur und Validierung der Dateneingabe - Wo? Wie viel? .
quelle
Antworten:
Wie komplex sind die Validierungen? Oft erfordern Validierungen eine Kombination von Feldern und / oder Geschäftsregeln, die darauf beruhen, dass Felder genau ausgewertet werden.
Je komplexer die Validierungen sind, desto schwieriger und weniger leistungsfähig ist Option 2.
Natürlich könnte die Datenschicht den Validierungsdienst zur Persistenzzeit aufrufen. Dies könnte die seltsame Situation verbessern, in der sich Daten aufgrund einer Änderung der Regeln in einem ungültigen Zustand befinden.
Der andere Punkt, der kommentiert werden sollte, ist die Möglichkeit, die Validierungsregeln ohne einen Qa-Zyklus zu ändern. Aber das ist ein Thema für einen anderen Thread.
Angesichts der obigen Informationen scheint Option 1 am flexibelsten zu sein, vorausgesetzt, Sie behalten Disziplin bei und trennen Validierung und Persistenz.
quelle
Vielleicht fehlt dir eine Schicht. Ohne die Details Ihrer Anwendung (Anforderungen, Architektur usw.) zu kennen, würde ich so etwas wie Client (wer auch immer) -> Anwendungsdienst -> Domänenmodell tun
Die Anwendungsdienstschicht darf mit dem Repository und dem Domänenmodell interagieren, das die Geschäftslogik enthält. Sie können also so etwas haben wie:
Wenn Sie eine Beziehung zwischen einem Feld und seinen Feldregeln haben und ein ORM wie Hibernate in Java verwenden, tun Sie nur Folgendes:
Weil die ORM das Diagramm der Objekte abfragt und instanziiert, nach denen Sie fragen.
In Bezug auf Ihren Zweifel an der Tatsache, dass jemand tun kann
Jemand könnte auch schreiben: FieldRule alwaysReturnTrueRule = new FieldRule {isValid (newValue) {return true; }} field.updateValue ("uncheckedValue", alwaysReturnTrueRule) Es ist ein obskures Beispiel, aber ich versuche zu sagen, dass nichts Sie vor einer schlechten Verwendung des Codes schützt. Vielleicht gute Dokumentation und Kommunikation von Angesicht zu Angesicht. Ich denke, nichts schützt Sie vor einer schlechten Verwendung des Codes.
quelle