[JAVA] [DDD] Übersicht über die domänengetriebene + Zwiebelarchitektur

DDD serialisierter Artikel

Hintergrund

Ich habe es im Artikel [Welche Architektur ist am besten zugänglich, um mit der Implementierung mit domänengesteuertem Design zu beginnen] empfohlen (http://little-hands.hatenablog.com/entry/2017/10/04/231743). War die Zwiebelarchitektur.

Dieses Mal möchte ich die Zwiebelarchitektur im Detail erklären.

Wie ich im obigen Artikel geschrieben habe, sind "Hexagonal, Onion, Clean" im Wesentlichen gleich, und die Idee ist, dass sie in Hexagonal abgeschlossen sind, aber die Zwiebel, die konkreter erklärt wird. Ich denke, es ist einfacher zu verstehen, wenn Sie die Erklärung aus der Architektur lesen.
Wenn Sie danach die Erklärung von sechseckig lesen, lautet sie "Ich sehe" und "Oh, es ist doch sechseckig". Lol

Traditionelle Schichtarchitektur

image.png

Diese Architektur wurde entwickelt, um buchstäblich die gesamte Geschäftslogik in der Business Logic-Schicht zusammenzufassen. Aber,

Es gibt Nachteile wie.

Schichtarchitektur eingeführt in "Eric Evans Domain Driven"

image.png

Diese Architektur ist ein Versuch, die Wartbarkeit zu verbessern, indem dem Domänenschichtmodell Geschäftswissen aus der traditionellen Schichtarchitektur vermittelt wird.

Dies wird im Artikel Was drückt Domänenwissen in einem Modell aus? mit Beispielcode erläutert. Bitte beziehen Sie sich darauf.

Dieses Design hat die einfache Modellierung erheblich verbessert, hat aber immer noch seine Schwächen. *** Die Domänenschicht hängt von der Infrastrukturschicht ab ***.

Dies bedeutet, dass Änderungen der Infrastrukturschicht, wie z. B. Bibliotheksänderungen oder Datenbankwechsel, die gesamte Geschäftslogik beeinflussen können.

Lassen Sie mich Ihnen ein konkretes Beispiel geben.

image.png

Angenommen, Sie haben den DB-Zugriff für ein Modell als RDB implementiert.
Wenn die Implementierung der Infrastruktur- und Domänenschicht eine Beschreibung der Annahme ist, die in einem bestimmten RDBMS verwendet werden soll, wie viel Code muss geändert werden, wenn Sie später versuchen, RDB in Dynamo von AWS zu ändern ... ?? Es ist schwer vorstellbar.

Als weiteres Beispiel für das Ersetzen der Infrastrukturschicht können Sie sich realistisch vorstellen, dass Sie von der Erstellung eines eigenen E-Mail-Versanddienstes zu einem komplexeren externen Dienst wechseln möchten.

Das Problem dabei ist, dass Sie versuchen, "um das Domänenmodell herum zu entwerfen", aber die Domänenschicht hängt von einer Schicht ab. Die Domänenschicht möchte nur geändert werden, wenn sich das Domänenmodell ändert.

Zwiebelarchitektur

Prinzip der Abhängigkeitsumkehr

image.png Das ist also die Architektur.

Basierend auf dem im Artikel [Was drückt Domänenwissen in einem Modell aus?] Vorgestellten Beispielobjekt (http://little-hands.hatenablog.com/entry/2017/10/04/201201) ・ ・ ・

Aufgabe: Domänenmodellschicht(Echte Klasse)
TaskRepository: Domain Service-Schicht(Repository/Schnittstelle)
TaskApplication: Anwendungsdienstschicht
TaskRDBRepository: Infrastrukturschicht(Repository/Echte Klasse)
TaskDynamoRepository: Infrastrukturschicht(Repository/Echte Klasse)

image.png

Hoppla, ich konnte das Domänenmodell erfolgreich als eine Klasse implementieren, die von nichts abhängt!

Was ist der Unterschied?

Ja, die Abhängigkeit von der Infrastrukturschicht wurde umgekehrt, da das TaskRepository anstelle einer realen Klasse zu einer Schnittstelle wurde.

Diese Methode wird als Prinzip der Abhängigkeitsumkehr bezeichnet. (Referenz)
*** Anstatt eine Ebene auf niedriger Ebene zu implementieren und sich dann auf eine Ebene auf hoher Ebene zu verlassen, ist sie hoch. Es wird von der Low-Level-Schicht basierend auf der von der Level-Schicht freigelegten Schnittstelle implementiert! Dies ermöglicht ein höheres Maß an Schichtunabhängigkeit.

In diesem Fall,

public inteterface TaskRepository {
  Task findById(Long taksId);

  void save(Task task);
}

In DomainService werden nur die Aufrufmethode und der Rückgabetyp auf diese Weise definiert, und das Persistenzziel wird nicht angegeben. * Sie deklarieren es in Form von "Das Persistenzziel kann überall sein, aber die Implementierungsklasse sollte damit übereinstimmen, da es auf diese Weise gesucht und gespeichert wird" *. ApplicationService wird durch den TaskRepository-Typ und dann durch DI (Dependency Injection) definiert 80% A7% E3% 81% AE% E6% B3% A8% E5% 85% A5) usw., damit die tatsächliche Klasse zur Laufzeit beurteilt wird.

Selbst wenn Sie das Persistenzziel von RDB zu Dynamo ersetzen möchten und eine andere Implementierungsklasse vorbereiten, können Sie jetzt entwerfen, ohne DomainModel, DomainService, ApplicationService zu ändern. Es ist wunderbar.

Der Vorteil besteht nicht nur darin, dass die Implementierungsklasse leicht ersetzt werden kann, sondern auch darin, dass sie leichter zu lesen und zu warten ist, da Code auf niedriger Ebene nicht in dem Modell enthalten ist, das das Geschäft ausdrückt.

Bedeutet, sich in einer runden Form auszudrücken

In der obigen Abbildung sind die Schichten zum Vergleich mit der Schichtarchitektur flach dargestellt. Die ursprüngliche Definition lautet jedoch, dass sie in einer runden Form dargestellt werden, da sie als "Zwiebel" bezeichnet werden.

image.png

Was bedeutet diese runde Form?

Es stellt das Modell *** dar, das eine Grenze zwischen der Anwendung und ihrer Außenseite aufweist, und kommuniziert zwischen ihnen über einen Adapter ***. (Die Pfeile stellen die Richtung der Anforderung dar und erhalten jeweils eine Antwort in die entgegengesetzte Richtung.)

image.png

Im Fall einer Anforderung von einem bestimmten HttpClient empfängt die Anwendung diese zuerst mit einem dedizierten Adapter, die Anwendung führt eine Verarbeitung durch, erfasst bei Bedarf Informationen aus der Datenbank, und die Anwendung verarbeitet die DB-Antwort und gibt sie als HttpClient-Antwort zurück. ..

Auch beim Integrationstest empfängt die Anwendung eine Anforderung vom dedizierten Adapter und verarbeitet sie. In diesem Fall ist es jedoch auch möglich, die Datenbank durch MockDB (In-Memory usw.) zu ersetzen.

Der Vorteil dieses Modells besteht darin, dass *** DomainModel und Application immer unabhängig voneinander geschrieben werden können und die Qualität in dieser Einheit garantiert werden kann ***. Da es nur von außen mit der von der Anwendung zugelassenen Methode aufgerufen werden kann, kann davon ausgegangen werden, dass sich die Anwendung unabhängig vom Client, der sie aufruft, nicht seltsam verhält, wenn die Anwendung durch automatisierte Tests qualitätsgarantiert ist. Dieses Sicherheitsgefühl ist enorm.

Teststrategie

Ich denke, dies hängt von der Richtlinie jedes Projekts ab, aber ich persönlich denke, dass die Richtlinie, nur den Integrationstest für Application Service zu implementieren, am kostengünstigsten ist.

Darüber hinaus legt DDD Wert auf Refactoring, um das Modell zu reifen. Es besteht jedoch auch der Vorteil, dass es einfacher ist, das Innere frei zu refactorisieren, indem mit einer bestimmten großen Granularität namens Application Serice getestet wird. Wenn Sie Klasse für Klasse zu genau testen, kann es sein, dass Sie sich beim Refactoring unwohl fühlen, da jede Klasse zum Zeitpunkt des Refactorings verschwindet und daher die Dynamik des Nicht-Refactorings möglicherweise funktioniert.

Wie oben erwähnt, können Sie sich beim Testen für jeden Anwendungsdienst hinsichtlich der Qualität beruhigt fühlen. Wenn Sie eine Teststrategie in Betracht ziehen, sollten Sie sie meiner Meinung nach nur als Referenz angeben.

Oh, diese Form

Ups, und der letzte Adapter sieht aus wie etwas ...
Ja, es ist eine sechseckige Architektur.

image.png

Die im Artikel eingeführte hexagonale Architektur Was ist die einfachste Architektur, um mit der Implementierung eines domänengesteuerten Designs zu beginnen Modelldiagramm

Die Idee, diese Anwendung und die Außenwelt mit einem Adapter zu verbinden, besteht darin, den sechseckigen so zu verwenden, wie er ist. Immerhin ist diese sechseckige Idee sehr gut, nicht wahr?

Die Zwiebelarchitektur ist in der Anwendung etwas detaillierter, gibt den Adaptertyp an und macht ihn insgesamt etwas spezifischer.

Haben Sie, wie ich am Anfang dieses Artikels schrieb, gesagt: "Oh, es ist doch sechseckig"? Lol

Zusammenfassung

Haben Sie übrigens die Attraktivität und das Implementierungsimage der Zwiebelarchitektur vermittelt? Wenn Sie sich bis zu diesem Punkt vorstellen können, denke ich, dass Sie nach und nach fortfahren können, indem Sie sich bei Bedarf auf die detaillierten Geschichten beziehen.

Ich werde in Zukunft detailliertere Geschichten schreiben. Bitte bleiben Sie mit mir in Kontakt, wenn Sie möchten.

Wenn Sie mehr wissen wollen

Wir haben ein Buch für diejenigen veröffentlicht, die zum ersten Mal DDD lernen, oder für diejenigen, die tatsächlich begonnen haben und mit Schwierigkeiten konfrontiert sind.

Domain Driven Design Modeling / Implementierungshandbuch

Beginnend mit einer Erklärung des "Zwecks von DDD" und des "Modells", die dazu neigen, verloren zu gehen Wir möchten die Attraktivität und die Auswirkungen von DDD anhand von Beispielen für die konkrete Modellierung und Implementierung erfahren.

"Kapitel 5 Architektur" in diesem Buch enthält eine detailliertere Erläuterung des Inhalts dieses Artikels. Bitte kaufen Sie, wenn Sie möchten.

Auf Twitter senden wir auch Fragen zu DDD und akzeptieren Fragen über einen Dienst namens "Question Box". Bitte folgen Sie mir, wenn Sie möchten.

@little_hand_s

Recommended Posts

[DDD] Übersicht über die domänengetriebene + Zwiebelarchitektur
Beantwortete Fragen zu DDD [Domain Driven Design]
Was ist domänengesteuertes Design, das versucht, [DDD] zu lösen?
[DDD] Was ist die am besten zugängliche Architektur, um mit domänengesteuertem Design zu beginnen?
Was ist der Unterschied zwischen den Verantwortlichkeiten der Domänenschicht und der Anwendungsschicht in der Zwiebelarchitektur [DDD]?