Vor einiger Zeit hatte ich mit meinen Kollegen eine Diskussion über die Beständigkeit von Domain-Modellen und darüber, ob wir ausländische Schlüsseleinschränkungen auf Datenbankebene.
Meine erste Reaktion war, dass die bloße Verwendung einer relationalen Datenbank die Durchsetzung solcher Beschränkungen implizierte, aber einige argumentierten, dass die Datenbank als nichts anderes als ein Persistenzmechanismus betrachtet werden sollte und daher sollten wir keine Geschäftslogik darin platzieren. Am Ende verwendeten wir keine Fremdschlüssel-Einschränkungen.
Hier ist meine Frage (ich hoffe, es ist nicht allzu allgemein gehalten): Wird es als gute Praxis angesehen, in diesen Fällen wichtige Einschränkungen durchzusetzen?
Erzwinge Constraints, aber verlasse dich NICHT darauf in deiner Geschäftslogik
Aber wenn Sie und Ihr Team in der Lage sind, fehlerfreie Software zu schreiben und alle möglichen Ausnahmeszenarien in Ihrem Code zu behandeln (einschließlich Hardware- / Netzwerk- / Dummy-Benutzer- / Programmierfehler), dann "Hei, warum sollte man sich mit redundanten FK-Einschränkungen befassen ..." - -Teaser -
Ich denke, ich betrachte es nicht so sehr als etwas für die Geschäftslogik, sondern verhindere, dass "schlechte" Daten in die Datenbank eingegeben werden. Sobald die Datenbank sehr groß wird, werden diese Einschränkungen in der Zukunft Kopfschmerzen verhindern.
Dies tritt besonders dann in Kraft, wenn mehrere Entwickler Apps für dieselben Daten entwickeln. Dies stellt sicher, dass sie nur gültige Daten eingeben können. Es ist sicherlich von Vorteil, Beschränkungen in einem Punkt statt in x Apps zu kontrollieren.
Ich habe das Gefühl, dass das Ignorieren wirklich nützlicher Tools (Datenintegrität auf Datenbankebene) im Interesse einer reinen Entwicklungsmethodik kontraproduktiv ist. Datenbanken sind wirklich gut in dieser Art von Sache ... lass sie es tun.
Irgendwann fängt jede Methode an zu brechen und Sie müssen nur praktisch sein.
Früher dachte ich, aber meine Meinung hat sich geändert, seit ich angefangen habe, viele ressourcenorientierte Systeme zu schreiben. In der Regel sind weit mehr als nur Fremdschlüsseleinschränkungen erforderlich, um ein Stück Daten zu validieren - z. B. muss ein Ticket, das den Status "zugewiesen" hat, einen gültigen "assigned_to" -Wert haben, und so weiter. Alle diese Regeln sollten in einer Validierungsroutine irgendeiner Art platziert werden, und während es theoretisch nicht weh tut , eine zusätzliche Validierung auf Datenbankebene zu haben, wenn Ihre Validierung auf App-Ebene funktioniert, prüfen Sie die fremde Schlüsseleinschränkung sind nur verschwendete Zyklen. Schlimmer noch, Sie haben jetzt Logik an Ihrem Datenmodell, die an zwei Stellen wiederholt wird - der Validierungscode und die Datenbankbeschränkungen.
Denken Sie so darüber nach: Möchten Sie eine andere Anwendungslogik in die Datenbank verschieben (z. B. über gespeicherte Prozeduren), wenn Sie nicht müssen? Wenn Sie aufgrund von Leistungsüberlegungen nicht dazu gezwungen wären, sollte die Antwort im Allgemeinen "nein" lauten.
"Meine erste Reaktion war, dass die bloße Verwendung einer relationalen Datenbank die Durchsetzung solcher Einschränkungen implizierte, aber einige argumentierten, dass die Datenbank als nichts anderes als ein Persistenzmechanismus betrachtet werden sollte und daher sollten wir keine Geschäftslogik darin platzieren. Am Ende verwendeten wir keine Fremdschlüssel-Einschränkungen. "
Ja, na ja, die mittelmäßige Mehrheit gewinnt diese Art von Debatte immer nur durch die Kraft der Zahlen, leider.
Wenn Sie immer noch diesen Kampf kämpfen wollen, könnten Sie Ihre Gegner fragen, wie sie verhindern wollen, dass jemand "direkte Datenbankeditoren" (ala db2-aid, spufi, ...) benutzt und wie sie vorhaben, irgendjemanden davon abzuhalten Verfälschung der Datenbank mit solchen Tools (die ihre programmierten Geschäftsbeschränkungen per Definition umgehen).
Wenn Sie dem Paradigma "Domain Driven Design" folgen möchten, lautet die Antwort "yes" für alle Elemente in einem Aggregat und "Nein" für Aggregationsverknüpfungen.
In fast allen Fällen möchten Sie, dass alles unter dem Aggregatstamm gelöscht wird, wenn das Stammverzeichnis selbst gelöscht wird. Dies wird durch die Verwendung von Fremdschlüsseln mit überlappenden Löschvorgängen auf Datenbankebene erreicht. Sie könnten auch Ihre Repositorys die kaskadierenden Löschungen selbst durchführen lassen, wenn Sie dies nicht auf DB-Ebene tun wollten, aber der Punkt steht immer noch, dass Aggregierte Kinder nicht ohne Root existieren sollten.
Bei Problemen mit der Aggregation von Aggregaten werden Sie wahrscheinlich geschäftliche Entscheidungen darüber treffen, was passieren soll, wenn das eine oder das andere entfernt wird. Oftmals möchten Sie dies asynchron behandeln, um Skalierbarkeit zu ermöglichen, sodass Ihr Domänenmodell letztendlich konsistent wird. Daher ist es in diesen Fällen nicht sinnvoll, Fremdschlüssel zu erzwingen, da es ein Zeitfenster gibt, in dem der eine oder andere Schlüssel möglicherweise nicht existiert.
Hoffe das hilft! Und für weitere Informationen, lesen Sie auf jeden Fall Evans 'Buch über Domain Driven Design - und die vielen Links im Internet auch.
Tags und Links language-agnostic design-patterns orm domain-model