Ich tauche im Domain Driven Design (DDD) und während ich mich eingehender damit beschäftige, gibt es einige Dinge, die ich nicht verstehe. Nach meinem Verständnis besteht ein Hauptpunkt darin, die Domänenlogik (Geschäftslogik) von der Infrastruktur (Datenbank, Dateisystem usw.) zu trennen.
Ich frage mich, was passiert, wenn ich sehr komplexe Abfragen habe, wie z. B. eine Abfrage zur Berechnung von Materialressourcen? Bei solchen Abfragen arbeiten Sie mit umfangreichen Operationen, für die SQL entwickelt wurde. Wenn Sie diese Berechnungen in der Domänenebene durchführen und mit vielen Mengen darin arbeiten, ist das wie das Wegwerfen der SQL-Technologie.
Das Durchführen dieser Berechnungen in der Infrastruktur ist nicht möglich, da das DDD-Muster Änderungen in der Infrastruktur zulässt, ohne die Domänenebene zu ändern, und zu wissen, dass MongoDB nicht über die gleichen Funktionen wie z. B. SQL Server verfügt, die nicht möglich sind.
Ist das eine Falle des DDD-Musters?
quelle
... is like throwing away the SQL technology
Nur weil eine bestimmte Technologie etwas kann , heißt das nicht, dass es die beste Wahl ist. Es ist ein anekdotischer Beweis, aber ich habe viel zu viele Unternehmen getroffen, die Geschäftslogik in der Datenbank gespeichert haben und aufgrund der damit verbundenen langfristigen Probleme mit der Wartbarkeit von der Datenbank abwandern. Vereinfachend, aber Datenbanken sind zum Speichern von Daten gedacht, und Programmiersprachen sind zum Transformieren von Daten gedacht. Ich möchte keine DB mehr für die Geschäftslogik verwenden, als meine Anwendung zum direkten Speichern meiner Daten verwenden möchte.Antworten:
Heutzutage werden wahrscheinlich Lesevorgänge (Abfragen) anders behandelt als Schreibvorgänge (Befehle). In einem System mit einer komplizierten Abfrage durchläuft die Abfrage selbst wahrscheinlich nicht das Domänenmodell (das in erster Linie für die Aufrechterhaltung der Konsistenz der Schreibvorgänge verantwortlich ist ).
Sie haben vollkommen Recht, dass wir das, was SQL ist, in SQL rendern sollten. Daher entwerfen wir ein Datenmodell, das für die Lesevorgänge optimiert ist, und für eine Abfrage dieses Datenmodells wird normalerweise ein Codepfad verwendet, in dem das Domänenmodell nicht enthalten ist (mit der möglichen Ausnahme einiger Eingabevalidierungen - um sicherzustellen, dass die Parameter in der Abfrage enthalten sind) sind vernünftig).
quelle
Dies ist die Grundlage des Missverständnisses: Der Zweck von DDD besteht nicht darin, Dinge entlang einer festen Linie zu trennen, wie "dies ist im SQL-Server, darf also nicht BL sein". Der Zweck von DDD besteht darin, Domänen zu trennen und Barrieren zwischen ihnen zu schaffen diese, mit denen die Interna einer Domain vollständig von den Interna einer anderen Domain getrennt werden können, und die gemeinsam genutzten Externa zwischen ihnen definieren können.
Stellen Sie sich SQL nicht als BL / DL-Barriere vor - das ist es nicht. Stellen Sie sich stattdessen "dies ist das Ende der internen Domäne" als Barriere vor.
Jede Domäne sollte über nach außen gerichtete APIs verfügen, mit denen sie mit allen anderen Domänen zusammenarbeiten kann. Im Fall der Datenspeicherschicht sollte sie über Lese- / Schreibaktionen (CRUD) für die gespeicherten Datenobjekte verfügen. Diese Mittel SQL selbst nicht wirklich die Barriere ist, die
VIEW
undPROCEDURE
sind Komponenten. Sie sollten niemals direkt aus der Tabelle lesen: Dies ist das Implementierungsdetail , um das sich DDD als externer Verbraucher keine Sorgen machen sollte.Betrachten Sie Ihr Beispiel:
Genau das sollte in SQL dann sein, und es ist keine Verletzung von DDD. Dafür haben wir DDD gemacht . Mit dieser Berechnung in SQL wird dies Teil des BL / DL. Was auf Sie tun würde , eine separate Ansicht / Stored Procedure verwenden / was-haben-Sie und halten Sie die Geschäftslogik von der Datenschicht getrennt sind , als dass Ihre externe API ist. Tatsächlich sollte Ihre Datenschicht eine andere DDD-Domänenschicht sein, auf der Ihre Datenschicht eigene Abstraktionen für die Arbeit mit den anderen Domänenschichten hat.
Das ist ein weiteres Missverständnis: Es besagt, dass sich Implementierungsdetails intern ändern können, ohne dass andere Domänenschichten geändert werden . Es heißt nicht, dass Sie nur eine ganze Infrastruktureinheit ersetzen können .
Denken Sie auch hier daran, dass es bei DDD darum geht, Interna mit genau definierten externen APIs zu verbergen. Wo diese APIs sitzen, ist eine ganz andere Frage, und DDD definiert das nicht. Es definiert lediglich, dass diese APIs existieren und sich niemals ändern sollten .
DDD ist nicht so eingerichtet, dass Sie MSSQL ad-hoc durch MongoDB ersetzen können - das sind zwei völlig unterschiedliche Infrastrukturkomponenten.
Verwenden wir stattdessen eine Analogie für das, was DDD definiert: Gas vs. Elektroautos. Beide Fahrzeuge verfügen über zwei völlig unterschiedliche Methoden zum Erzeugen von Antrieben, aber dieselben APIs: Ein / Aus, Gas / Bremse und Räder zum Antreiben des Fahrzeugs. Laut DDD sollten wir in der Lage sein, den Motor (Gas oder Elektrizität) in unserem Auto auszutauschen. Es heißt nicht, dass wir das Auto durch ein Motorrad ersetzen können, und genau das ist MSSQL → MongoDB.
quelle
Wenn Sie jemals an einem Projekt teilgenommen haben, bei dem die Organisation, die die Anwendung hostet, entscheidet, dass die Lizenzen auf Datenbankebene zu teuer sind, werden Sie die einfache Migration Ihrer Datenbank / Ihres Datenspeichers zu schätzen wissen. Alles in allem passiert das zwar, aber nicht oft .
Man kann sozusagen das Beste aus beiden Welten bekommen. Wenn Sie die Ausführung der komplexen Funktionen in der Datenbank als Optimierung betrachten, können Sie über eine Schnittstelle eine alternative Implementierung der Berechnung einbinden. Das Problem ist, dass Sie die Logik an mehreren Stellen verwalten müssen.
Abweichung von einem Architekturmuster
Wenn Sie Schwierigkeiten haben, ein Muster rein zu implementieren oder in einem bestimmten Bereich davon abzuweichen, müssen Sie eine Entscheidung treffen. Ein Muster ist einfach eine vorgefertigte Methode, um die Organisation Ihres Projekts zu unterstützen. Nehmen Sie sich an dieser Stelle Zeit, um Folgendes zu bewerten:
Sie werden feststellen, dass einige Architekturmuster gut zu 80-90% Ihrer Anwendung passen, aber weniger zu den verbleibenden Teilen. Die gelegentliche Abweichung von dem vorgeschriebenen Muster ist aus Leistungs- oder logistischen Gründen nützlich.
Wenn Sie jedoch feststellen, dass Ihre kumulativen Abweichungen mehr als 20% Ihrer Anwendungsarchitektur ausmachen, ist dies wahrscheinlich nur eine schlechte Lösung.
Wenn Sie sich für die Architektur entscheiden, tun Sie sich selbst einen Gefallen und dokumentieren Sie, wo und warum Sie von der vorgeschriebenen Vorgehensweise abgewichen sind. Wenn Sie ein neues begeistertes Mitglied in Ihrem Team finden, können Sie es auf die Dokumentation verweisen, die die Leistungsmessungen und Begründungen enthält. Dadurch wird die Wahrscheinlichkeit von wiederholten Anfragen zur Behebung des "Problems" verringert. Diese Dokumentation wird auch dazu beitragen, grassierende Abweichungen zu verhindern.
quelle
Die eingestellte Manipulationslogik, in der SQL gut ist, kann problemlos in DDD integriert werden.
Angenommen, ich möchte einen Gesamtwert kennen, die Gesamtanzahl der Produkte nach Typ. Einfach in SQL auszuführen, aber langsam, wenn ich jedes Produkt in den Speicher lade und sie alle addiere.
Ich führe einfach ein neues Domain-Objekt ein,
und eine Methode in meinem Repository
Klar, vielleicht verlasse ich mich jetzt darauf, dass meine DB bestimmte Fähigkeiten hat. Aber ich habe technisch immer noch die Trennung und solange die Logik einfach ist, kann ich argumentieren, dass es nicht 'Geschäftslogik' ist.
quelle
Query
als Parameter erhalten.repository.find(query);
. Ich habe das selbe aber mitSpecs. That opens a door to leave
Query` als Abstraktion gelesen undQueryImpl
oder die abfragespezifische Implementierung auf die Infrastrukturebene.I know some people do that
Einige Leute sind Pivotal und sein Rahmen. SpringFramework hat viel davon :-). Wie @VoiceOfUnreason bereits angedeutet hat, besteht der Schlüssel zu DDD darin, die Konsistenz der Schriften zu wahren. Ich bin nicht sicher, ob ich das Design mit Domänenmodellen erzwingen soll, deren einziger Zweck darin besteht, Abfragen abzufragen oder zu parametrisieren. Dies könnte mit Datenstrukturen (pocos, pojos, dtos, row mappers, was auch immer) außerhalb der Domäne angegangen werden.Eine der Möglichkeiten, um dieses Dilemma zu lösen, besteht darin, SQL als Assemblersprache zu betrachten: Sie codieren selten, wenn überhaupt, direkt in der Assemblersprache, aber wenn es auf die Leistung ankommt, müssen Sie in der Lage sein, den von Ihrem C erzeugten Code zu verstehen / C ++ / Golang / Rust-Compiler und möglicherweise sogar ein winziges Snippet in Assembly schreiben, wenn Sie den Code in Ihrer Hochsprache nicht ändern können, um den gewünschten Maschinencode zu erzeugen.
Auf ähnliche Weise bieten im Bereich von Datenbanken und SQL verschiedene SQL-Bibliotheken (von denen einige ORM sind ), z. B. SQLAlchemy und Django ORM für Python, LINQ für .NET, Abstraktionen auf höherer Ebene, verwenden jedoch, wenn möglich, generierten SQL-Code, um Leistung zu erzielen. Sie bieten auch eine gewisse Portabilität hinsichtlich der verwendeten Datenbank, möglicherweise mit unterschiedlicher Leistung, z. B. unter Postgres und MySQL, aufgrund einiger Vorgänge, bei denen optimaleres DB-spezifisches SQL verwendet wird.
Und genau wie bei Hochsprachen ist es wichtig zu verstehen, wie SQL funktioniert, auch wenn nur die mit den oben genannten SQL-Bibliotheken durchgeführten Abfragen neu angeordnet werden müssen, um die gewünschte Effizienz zu erzielen.
PS Ich würde das lieber kommentieren, aber dafür habe ich keinen ausreichenden Ruf.
quelle
Wie üblich ist dies eines der Dinge, die von einer Reihe von Faktoren abhängen. Es ist wahr, dass Sie mit SQL viel anfangen können. Es gibt auch Herausforderungen bei der Verwendung und einige praktische Einschränkungen relationaler Datenbanken.
Wie Jared Goguen in den Kommentaren festhält, kann es sehr schwierig sein, SQL zu testen und zu verifizieren. Die Hauptfaktoren, die dazu führen, sind, dass es (im Allgemeinen) nicht in Komponenten zerlegt werden kann. In der Praxis muss eine komplexe Abfrage insgesamt berücksichtigt werden. Ein weiterer erschwerender Faktor ist, dass Verhalten und Korrektheit von SQL in hohem Maße von der Struktur und dem Inhalt Ihrer Daten abhängen. Dies bedeutet, dass das Testen aller möglichen Szenarien (oder sogar das Bestimmen, was sie sind) oft nicht durchführbar oder unmöglich ist. Das Refactoring von SQL und die Änderung der Datenbankstruktur ist ebenfalls problematisch.
Der andere große Faktor, der zur Abkehr von SQL geführt hat, ist, dass relationale Datenbanken in der Regel nur vertikal skaliert werden. Wenn Sie beispielsweise komplexe Berechnungen in SQL erstellen, um sie in SQL Server auszuführen, werden sie in der Datenbank ausgeführt. Das bedeutet, dass die gesamte Arbeit Ressourcen in der Datenbank beansprucht. Je mehr Sie in SQL ausführen, desto mehr Ressourcen benötigt Ihre Datenbank in Bezug auf Arbeitsspeicher und CPU. Es ist oft weniger effizient, diese Dinge auf anderen Systemen auszuführen, aber es gibt keine praktische Grenze für die Anzahl zusätzlicher Maschinen, die Sie zu einer solchen Lösung hinzufügen können. Dieser Ansatz ist kostengünstiger und fehlertoleranter als der Aufbau eines Monster-Datenbankservers.
Diese Probleme können auf das jeweilige Problem zutreffen oder nicht. Wenn Sie in der Lage sind, Ihr Problem mit verfügbaren Datenbankressourcen zu lösen, ist SQL möglicherweise in Ordnung für Ihren Problembereich. Sie müssen jedoch Wachstum berücksichtigen. Es mag heute in Ordnung sein, aber einige Jahre später können die Kosten für das Hinzufügen zusätzlicher Ressourcen zu einem Problem werden.
quelle
Lassen Sie mich zunächst einige Missverständnisse klären.
DDD ist kein Muster. Und es schreibt nicht wirklich Muster vor.
Das Vorwort zu Eric Evans DDD- Buch lautet:
Auf diese Weise können Sie sich der Softwareentwicklung und der Domänenmodellierung nähern und einige technische Vokabeln verwenden, die diese Aktivitäten unterstützen (ein Vokabular mit verschiedenen Konzepten und Mustern). Es ist auch nichts völlig Neues.
Beachten Sie auch, dass ein Domänenmodell nicht die OO-Implementierung ist, die in Ihrem System vorhanden ist. Dies ist nur eine Möglichkeit, es auszudrücken oder einen Teil davon auszudrücken. Ein Domain-Modell ist die Art und Weise, wie Sie über das Problem nachdenken, das Sie mit der Software lösen möchten. Es ist, wie Sie Dinge verstehen und wahrnehmen, wie Sie darüber sprechen. Es ist konzeptionell . Aber nicht in einem vagen Sinne. Es ist tief und raffiniert und das Ergebnis harter Arbeit und des Sammelns von Wissen. Es wird im Laufe der Zeit weiter verfeinert und wahrscheinlich weiterentwickelt und beinhaltet Implementierungsaspekte (von denen einige das Modell einschränken können). Es sollte von allen Teammitgliedern geteilt werden (und involvierte Domain-Experten), und es sollte bestimmen, wie Sie das System implementieren, damit das System es genau widerspiegelt.
Nichts davon ist von Natur aus Pro-SQL oder Anti-SQL, obwohl OO-Entwickler das Modell im Allgemeinen besser in OO-Sprachen ausdrücken können und der Ausdruck vieler Domänenkonzepte von OOP besser unterstützt wird. Aber manchmal müssen Teile des Modells in einem anderen Paradigma ausgedrückt werden.
Im Allgemeinen gibt es hier zwei Szenarien.
Im ersten Fall ist für einige Aspekte einer Domäne eine komplexe Abfrage erforderlich. Dieser Aspekt lässt sich möglicherweise am besten im SQL- / relationalen Paradigma ausdrücken. Verwenden Sie daher das für den Job geeignete Tool. Reflektieren Sie diese Aspekte in Ihrem Domain-Denken und die Sprache, die bei der Kommunikation von Konzepten verwendet wird. Wenn die Domäne komplex ist, ist dies möglicherweise Teil einer Unterdomäne mit einem eigenen begrenzten Kontext.
Das andere Szenario ist, dass das wahrgenommene Bedürfnis, etwas in SQL auszudrücken, das Ergebnis eines eingeschränkten Denkens ist. Wenn eine Person oder ein Team schon immer datenbankorientiert gedacht hat, kann es für sie aufgrund ihrer Trägheit schwierig sein, eine andere Herangehensweise an Dinge zu erkennen. Dies wird zu einem Problem, wenn der alte Weg die neuen Anforderungen nicht erfüllt und ein Umdenken erforderlich ist. Bei DDD als Entwurfsansatz geht es zum Teil darum, wie Sie aus dieser Situation herausfinden können, indem Sie das Wissen über die Domäne sammeln und vertiefen. Aber jeder scheint diesen Teil des Buches zu ignorieren und konzentriert sich auf einige der aufgelisteten technischen Vokabeln und Muster.
quelle
Sequel wurde populär, als Speicher teuer war, weil das relationale Datenmodell die Möglichkeit bot, Ihre Daten zu normalisieren und effektiv im Dateisystem zu speichern.
Jetzt ist der Speicher relativ billig, sodass wir die Normalisierung überspringen und in dem Format speichern können, in dem wir ihn verwenden, oder aus Gründen der Geschwindigkeit sogar viele gleiche Daten duplizieren können.
Betrachten Sie die Datenbank als einfaches E / A-Gerät , dessen Aufgabe es ist, Daten im Dateisystem zu speichern. Ja, ich weiß, es ist schwer vorstellbar, da wir viele Anwendungen mit wichtiger Geschäftslogik in SQL-Abfragen geschrieben haben. Versuchen Sie jedoch, sich diesen SQL Server vorzustellen ist nur ein weiterer Drucker.
Würden Sie den PDF-Generator in den Druckertreiber einbetten oder einen Auslöser hinzufügen, der die Protokollseite für jeden von unserem Drucker ausgedruckten Kundenauftrag druckt?
Ich gehe davon aus, dass die Antwort "Nein" lautet, da wir nicht möchten, dass unsere Anwendung an den spezifischen Gerätetyp gekoppelt ist (und nicht einmal über die Effizienz einer solchen Idee spricht).
In den 70er und 90er Jahren waren SQL-Datenbanken jetzt effizient? - Nicht sicher, ob in einigen Szenarien die asynchrone Datenabfrage die erforderlichen Daten schneller als mehrere Verknüpfungen in der SQL-Abfrage zurückgibt.
SQL wurde nicht für komplizierte Abfragen entwickelt, sondern zum effizienten Speichern von Daten und zur Bereitstellung einer Schnittstelle / Sprache zum Abfragen gespeicherter Daten.
Ich würde sagen, die Erstellung Ihrer Anwendung um ein relationales Datenmodell mit komplizierten Abfragen ist Missbrauch der Datenbank-Engine. Natürlich freuen sich Datenbank-Engine-Anbieter, wenn Sie Ihr Unternehmen eng mit ihrem Produkt verknüpfen. Sie werden mehr Funktionen bereitstellen, die diese Bindung stärken.
quelle