Entwickler-Kochbuch: DDD-Rezepte (Teil 3, Anwendungsarchitektur)

    Einleitung


    In früheren Artikeln haben wir den Umfang des Ansatzes hervorgehoben und die wichtigsten methodischen Prinzipien von Domain Driven Design untersucht .


    In diesem Artikel möchte ich die wichtigsten modernen Ansätze zum Aufbau einer Unternehmenssystemarchitektur identifizieren: Geschmeidig, schreien, reinigen und ihnen eine klare Interpretation in Form einer komplett fertigen Lösung geben.


    WM


    Im Folgenden werden die einzelnen Entwurfsmuster detailliert beschrieben: Definieren Sie den Gültigkeitsbereich, geben Sie Beispiele für Code an und zeigen Sie die empfohlenen Vorgehensweisen. Als Ergebnis werden wir einen fertigen Microservice schreiben.


    Flexible Architektur


    Im letzten Artikel haben wir darüber gesprochen, dass DDD die Praxis der Implementierung durch das Modell einschließt. Der Themenbereich sollte durch Ihren Code beschrieben werden. Versuchen wir herauszufinden, wie das geht.


    In seinem Buch bietet Eric Evans eine Reihe von empfohlenen Entwurfsmustern an und bezeichnet diesen Ansatz als flexibel:


    Im Namen der Flexibilität der Architektur wurden viele unnötige Konstruktionen in Programmen aufgeschichtet. Zusätzliche Abstraktionsebenen und indirekte Verweise stören eher als Hilfe in dieser Angelegenheit. Schauen Sie sich die Architektur an, die die Programmierer wirklich inspiriert, die an ihrer Verfeinerung beteiligt sind, und Sie werden in der Regel etwas sehr Einfaches sehen. Einfach bedeutet jedoch nicht, dass es einfach ist, es auszuführen. Um solche Elemente zu erstellen, die zu komplexen Systemen zusammengefügt werden können und es nicht schwer zu verstehen ist, ist es notwendig, „Hingabe“ zu kombinieren, um dem Modell einen eher strengen Architekturstil zu verleihen. Ein gewisses Design-Können ist nicht nur notwendig, um etwas zu kreieren, sondern sogar um fertige Produkte zu verwenden.

    Eric Evans, domänengetriebenes Design: Komplexität im Herzen von Software

    Der vorgestellte Satz von Entwurfsmustern ist keine strenge Architektur oder eine vorgefertigte Lösung, sondern eher ein Denkanstoß.


    Architektur schreien


    Ähnliche Gedanken kamen bei vielen Entwicklern und Entwicklern komplexer Systeme vor.


    Im Jahr 2011 gab es einen Artikel von Robert Martin - Screaming Architecture , in dem es heißt, dass Ihr Code nicht nur den Themenbereich beschreiben muss, sondern darüber schreit, vorzugsweise mit Obszönitäten.


    Also, was ist Ihre Anwendung schreien? Die Struktur des Pakets; schreien sie: Health Care System oder Accounting System oder Inventory Management System? Oder schreien sie: Rails oder Spring / Hibernate oder ASP?

    Robert C. Martin, 30. September 2011

    Robert sagt, dass der Code für Ihre Anwendung die Aktivität der Anwendung widerspiegeln sollte, anstatt sich an die Regeln des Frameworks anzupassen. Die Rahmenstruktur sollte Ihre Architektur nicht einschränken. Die Anwendung sollte nicht an die Datenbank oder das HTTP-Protokoll gebunden sein. Dies sind lediglich Speicher- und Bereitstellungsmechanismen. Der Begrenzungsrahmen ist ein Werkzeug. Sie sollten kein erfahrener Frame Maker werden. Tests Ihrer Anwendung sind Tests der Logik des Betriebs und nicht des http-Protokolls.


    Reine Architektur


    Ein Jahr später, Robert Martins nächster Artikel, The Clean Architecture . Darin sagt der Autor, wie man den Code zum Schreien bringt. Nachdem er mehrere Architekturen studiert hat, umreißt er die grundlegenden Prinzipien:


    1. Unabhängigkeit vom Rahmen. Die Architektur hängt nicht von einer vorhandenen Bibliothek ab. Auf diese Weise können Sie Frameworks als Werkzeuge verwenden, nicht als Einschränkungen, die Ihre Hände binden.
    2. Testbarkeit Geschäftsregeln können ohne Benutzeroberfläche, Datenbank, Webserver oder andere technische Mittel getestet werden.
    3. Unabhängigkeit von der Benutzeroberfläche. Die Benutzeroberfläche kann leicht geändert werden, ohne den Rest des Systems zu ändern. Beispielsweise kann eine Webschnittstelle durch eine Konsolenschnittstelle ersetzt werden, ohne die Geschäftslogik zu ändern.
    4. Unabhängigkeit von der Datenbank. Sie können Oracle oder SQL Server gegen Mongo, BigTable, CouchDB oder etwas anderes austauschen. Die Logik Ihrer Anwendung sollte nicht an eine Datenbank gebunden sein.
    5. Unabhängigkeit von den Auswirkungen der Umwelt. Tatsächlich wissen Ihre Geschäftsregeln nichts über die Außenwelt.

    Zu Habré hat bereits ein sehr guter Artikel Missverständnisse Clean Architecture veröffentlicht . Sein Autor, Jeevuz , kaute sehr gut die Feinheiten des Verständnisses dieses Ansatzes. Ich empfehle dringend, sich sowohl mit dem Originalmaterial als auch mit dem Original vertraut zu machen.


    Variable Architektur


    Die Beschreibung des oben dargestellten Ansatzes sieht nicht so eindeutig aus. Als Teil der Entwicklung der Architektur einer Reihe komplexer Unternehmenssysteme entwickelten ich und meine Kollegen eine ziemlich klare Interpretation der beschriebenen Ansätze, die ich im Folgenden vorstellen möchte.


    Vor dem Aufkommen von Computern und Programmiersprachen wurde mit Papierworkflow Systeme mit komplexer Geschäftslogik erstellt und verwaltet. Das Ergebnis eines Prozesses war ein Dokument, in dem ein bestimmtes Geschäftsobjekt beschrieben wurde. Infolgedessen wurde die Schreibarbeit auf drei einfache Aktionen reduziert :


    1. Dokumenterstellung
    2. Dokumentenverarbeitung
    3. Arbeiten Sie mit dem Archiv der Dokumente
    4. Dokument Präsentation

    Dokument - Fixierung von Informationen über die wirtschaftliche Aktivität eines bestimmten realen Geschäftsobjekts.

    Bitte beachten Sie, dass das Dokument selbst kein echtes Geschäftsobjekt ist, sondern nur sein Modell . Derzeit werden Papierdokumente durch elektronische Dokumente ersetzt. Ein Dokument kann ein Datensatz in einer Tabelle, ein Bild, eine Datei, ein Brief oder eine andere Information sein.
    Ich mag nicht mehr weiter ein Word - Dokument zu verwenden, da wird es mehr Verwirrung macht, werden wir das Konzept der Verwendung Essenz (Entity) von DDD Terminologie. Sie können sich jedoch vorstellen, dass Ihr gesamtes System jetzt ein elektronisches Dokumentenverwaltungssystem ist, das vier einfache Aktionen ausführt .


    1. Sammeln
    2. Verarbeitung
    3. Lagerung
    4. Vertretung

    Aktion (Aktion) - die strukturelle Einheit des Geschäftsmodells; ein relativ vollständiger separater Akt eines wahrgenommenen Ziels, einer willkürlichen Absicht und der Absicht der individuellen Aktivität eines Geschäftsobjekts, das vom Endbenutzer unterschieden wird.

    Ein gutes Beispiel für Dacevtia ist der Theaterakt. Theater simuliert Ereignisse aus dem wirklichen Leben. Der Akt ist ein sinnvoller Teil des Stücks. Aber um die Geschichte abzuschließen, müssen Sie mehrere Akte in einer genau definierten Reihenfolge verlieren. Eine solche Reihenfolge in unserer Architektur nennen wir Mode .


    Modus (Leitung) - eine Reihe von Aktionen in einer bestimmten Reihenfolge, die einen vollständigen Sinn hat und dem Endbenutzer Nutzen bringt.

    Leitung


    Für diese Modi selektive oder Leiter wurde Arbeit geprägt Variator (Selector). Insbesondere wurde das " US- Patent Nr. 2870278A für die Vielzahl von Operationssequenzen" erhalten . Wir kennen dieses Gerät als "Drehung" einer Waschmaschine. Architektonische "Wendung" wird am Anfang des Artikels gegeben.


    Die Variabilität des Ansatzes zeigt sich in der Tatsache, dass Sie bei einer solchen Architektur einen der vier Modi auswählen können , durch die Sie keine unnötigen Aktionen ausführen .


    Beim Starten der Waschmaschine können Sie den Modus auswählen: Waschen, Spülen oder Schleudern. Wenn Sie sich für das Waschen entscheiden, spült Ihr Gerät die Wäsche immer noch aus und wringt dann aus. Mit dem Spülen sind Sie sicher, dass Sie einen Spin bekommen. Spin - die letzte Aktion beim Waschen ist die "einfachste". In unserer Architektur die einfachste Aktivität - Darstellung , und fange damit an.


    Vertretung


    Wenn wir von einer sauberen Ansicht sprechen, ohne auf die Datenbank oder eine externe Quelle zuzugreifen, geben wir statische Informationen heraus: HTML-Seite, Datei, Verzeichnis in Form von Json'a. Wir können sogar nur eine Code-Antwort ausgeben - 200:


    Lassen Sie uns das einfachste "Gesundheitscheck" schreiben


    moduleHealthclassEndpoints < Sinatra::Base
          get '/check'do; endendend

    In der primitivsten Form sieht unser Schema so aus:


    Vertretung


    Lyrischer Rückzug

    Я прошу заметить, что во фреймворке Sinatra класс Endpoints объединяет в себе как Router, так и Controller в одном классе. Не нарушает ли это принципа единственной ответственности? По факту, Endpoints это не класс, а слой, выраженный через класс, и зона его ответственности на более высоком уровне.


    Ок, а как же Router и Controller? Они представлены не набором классов, а наименованием и реализацией функции. А статический файл это вообще файл. Один класс отвечает одной ответственности, но не пытайтесь выразить каждую ответственность через класс. Исходите из практичности, а не из догматизма.


    Arbeit mit dem Speichersystem (Storage)


    Das Geschäft stellt hohe Anforderungen an die Verfügbarkeit Ihrer Anwendung. Warum sollte jemand Ihren Service brauchen, wenn wir ihn nicht im richtigen Moment nutzen können? Um die Datenintegrität zu gewährleisten, erfassen wir nach jeder Verarbeitung eine Änderung des Status eines Geschäftsobjekts.


    Um ein Objekt aus dem Speicher abzurufen, ist keine Geschäftslogik erforderlich. Stellen Sie sich vor, wir automatisieren die Aktivitäten einer Hotelkette und wir haben ein Magazin mit Gästen an der Rezeption. Wir haben uns entschieden, die Informationen über den Besucher anzusehen.


    moduleReceptionclassEndpoints < Sinatra::Base# Show item
        get '/residents/:id', provides::jsondo
          resident = Repository::Residents.find params[:id]
          status 200
          serialize(resident)
        endendend

    Arbeiten mit dem Speichersystem in Form eines grafischen Schemas:


    Lagerung


    Wie wir sehen, wird die Kommunikation zwischen der für die Speicherung zuständigen Ebene und der für die Datendarstellung zuständigen Ebene durch das Antwortmodell implementiert. Dieses Modell gehört zu keiner dieser Schichten. Es handelt sich tatsächlich um ein Geschäftsobjekt, das sich in der für die Geschäftslogik zuständigen Schicht befindet.


    Verarbeitung


    Wenn sich das Objektmodell aufgrund seiner Eigenschaften ändert, ohne neue Daten hinzuzufügen, können wir direkt auf die Interactor- Schicht zugreifen . Schicht Interaktorsystem ist der Schlüssel zu unserer Anwendung, dass sie über alle Geschäftslogik in Form von einzelnen beschreibt Varianten Verwendung (Use Cases) , und dass es die Änderung der Essenzen .


    Betrachten Sie diesen Anwendungsfall. In unserem Hotel ist der Besucher bereits registriert, aber wir feiern jede Ankunft oder Abreise.


    moduleReceptionclassEndpoints < Sinatra::Base# Register resident arrival
          post '/residents/:uid/arrival', provides::jsondo
            result = Interactors::Arrival.call(resident_id: params[:id])
            check!(result) do
              status 201
              serialize result.data
            endend# Register resident departure
          post '/residents/:uid/departure', provides::jsondo
            result = Interactors::Departure.call(resident_id: params[:id])
            check!(result) do
              status 201
              serialize result.data
            endendendend

    Lass uns ein bisschen aufhören. Warum nicht mit einer Methode mit Parameter implementieren status? InteraktorenArrival und Departureradikal anders. Wenn ein Gast zu uns gekommen ist, müssen wir prüfen, ob die Reinigung beendet ist, ob neue Nachrichten für ihn vorliegen usw. Wenn er geht, müssen wir im Gegenteil die Reinigung einleiten, wenn nötig. Wir erinnern uns nicht einmal an die Nachrichten, denn wenn er in einem Hotel wäre, würden wir ihn sofort anrufen. All diese Geschäftslogik schreiben wir auf der Interactor- Schicht vor .


    Verarbeitung


    Aber was sollen wir tun, wenn wir Daten von außen haben? Hier verbindet sich die Data Collect- Aktion .


    Daten sammeln


    Bei der ersten Anmeldung eines Gastes in einem Hotel füllt er ein Anmeldeformular aus. Dieses Formular wird überprüft. Wenn die Daten korrekt sind, wird ein Geschäftsprozess registriert. Der Prozess gibt Daten zurück - das erstellte Geschäftsmodell „Resident“. Dieses Modell präsentieren wir dem Bewohner in lesbarer Form:


    moduleReceptionclassEndpoints < Sinatra::Base# Register new resident
        post '/residents', provides: [:json] do
          form = Forms::Registration.new(params)
          complete! form do
            check! form.result do
              status 201
              serialize form.result.data
            endendendendend

    Schematisch sieht es so aus:


    Sammeln


    Spielregeln (Regeln)


    • Variables System in Bezug auf Prozesse ist in Aktionen unterteilt .
    • Die Reihenfolge der Aktionen wird vom Modus bestimmt .
    • Die Modi sind inkrementell.
    • Der "komplexere" Modus ergänzt den eher "einfachen " Modus für eine einzige Aktion.
    • Jede Aktion findet in einer einzelnen Ebene statt .
    • Jede Ebene wird durch eine Klasse dargestellt .
    • Innerhalb einer Ebene können Klassen-Ebenen und Klassen-Verantwortlichkeiten vorhanden sein .
    • Die Kommunikation findet nur zwischen der Schicht und der inneren Schichtklasse statt .
    • View Models sind Ausnahmen.
    • Die Fehlerbehandlung sollte auf Klassenebene erfolgen .

    Baum


    Allgemeine Regelung


    Dieser Ansatz hat eine hohe Eintrittsschwelle. Seine Anwendung erfordert eine große Erfahrung des Designers, um die zu lösenden Aufgaben genau zu verstehen. Schwierigkeit ist auch eine Auswahl an Werkzeugen. Trotz der Komplexität der Struktur ist die Implementierung auf Codeebene unglaublich einfach und ausdrucksstark. Obwohl es eine Reihe von Konventionen und Vollmachten enthält. In Zukunft analysieren wir jedes Entwurfsmuster separat, beschreiben, wie es erstellt, getestet und der Umfang festgelegt wird. Und um nicht in ihrer Vielfalt verwirrt zu werden, wird die vollständige Karte angeboten:


    Hochauflösende Karte




    Quellen der Inspiration

    Jetzt auch beliebt: