Es gibt sehr wenig Anleitung, wie man Front-End-Anwendungen in der Welt von React organisiert. (Verschieben Sie einfach Dateien, bis es sich „richtig anfühlt“, lol). Die Wahrheit ist, dass wir es besser können. Lassen Sie uns ein Muster betrachten, das Sie für die Architektur Ihrer Website in Betracht ziehen könnten.
Zuerst könnten Sie Ihren Code in Ordnern /components und /containers aufteilen. Das funktioniert für kleine Websites, aber Sie werden feststellen, dass Sie bei der Skalierung auf größere Websites nach etwas Robusterem suchen. Glücklicherweise hat uns jahrzehntelange Forschung im Systemdesign eine Fülle von Mustern beschert, die wir erforschen können, um eine skalierbare Architektur zu schaffen.
Eines davon ist Domain-Driven Design, und es hat in den letzten Jahren wieder an Popularität gewonnen. Lassen Sie uns untersuchen, wie wir es in React anwenden können.
Eine Einführung in Domain-Driven Design
Domain-Driven Design (DDD) ist die Praxis der Verwaltung der Komplexität von Softwareanwendungen, indem ihre zugrunde liegenden Datenmodelle mit der Domänenlogik verknüpft werden. Das ist viel gesagt, also lassen Sie es uns weiter aufschlüsseln.
Die Domäne ist eine Ontologie, was bedeutet, wie Dinge in der Welt gruppiert werden. Zum Beispiel hat das Wort *Balken* eine sehr spezifische Verbindung zur Domäne des Bauwesens. Ein anderes Wort, wie *Mike*, kann zu mehreren Domänen gehören, wie der Domäne biblischer Namen (kurz für Michael) oder in der Domäne der Politik im Zusammenhang mit dem NATO-Alphabet.
Wenn das Design domänengetrieben ist, bedeutet dies, dass wir das Modell unserer Domäne (z. B. eine Spielkarte in der Domäne Poker) in einem Kontext (z. B. die kontextbezogene Gruppierung wie ein Spiel) platzieren, um die Komplexität zu bewältigen.

Organisation einer DDD-Website
Domain-Driven Design ist speziell für die Bewältigung der Komplexität wachsender Websites konzipiert, wenn mehr und mehr Modelle hinzugefügt werden. Es ergibt eigentlich keinen Sinn für eine Website mit einem Modell. Sobald Sie etwa vier Modelle haben, ist es ein guter Zeitpunkt, um Ihre Modelle an mehrere Kontexte zu binden. Dies ist keine feste Regel, also haben Sie nicht das Gefühl, dass Sie müssen, aber sobald Sie über vier Modelle hinausgehen, werden diese kontextbezogenen Gruppierungen auftauchen.
Beginnen Sie mit der Organisation Ihrer Domänen
Nehmen wir Twitter als Beispiel für unsere zu organisierende Website. Eine Möglichkeit, Domänen innerhalb von Twitter zu trennen, ist die Aufteilung unserer Modelle zwischen der Blog-Plattform, die die Tweets antreibt, und den Interaktionselementen, die es ermöglichen, dass Microblogging sich verbreitet und gedeiht.

Ist das die einzige Möglichkeit, Verantwortlichkeiten in Twitter zu trennen? Definitiv nicht! Ein wichtiger Aspekt von DDD ist, dass es keinen einzig richtigen Weg gibt, Domänen zu erstellen. Es gibt viele Möglichkeiten, die begrenzten Kontexte einer Anwendung aufzuteilen. Konzentrieren Sie sich also nicht zu sehr auf die von uns gewählte Architektur. Nutzen Sie dies stattdessen als Sprungbrett, um zu verstehen, wie wir DDD auf die Organisation unseres Front-End-Codes anwenden können.
Das gesagt, wird unser Code nun wie folgt strukturiert sein (vorausgesetzt, Sie beginnen mit etwas wie create-react-app)
twitter/
├── App.css
├── App.js
├── App.test.js
├── blog/
└── interaction/
Definieren Sie die Komponenten und Container in jeder Domäne
Nachdem wir unsere grundlegende Ordnerstruktur eingerichtet haben, ist es an der Zeit, einige echte Komponenten hinzuzufügen! Wenn wir uns unser Domänen-UML-Diagramm oben ansehen, wäre es nützlich, mit Containern zu beginnen, die Daten auf einer bestimmten Seite abrufen, und Komponenten, die die Vorlagen organisieren, aus denen diese Seiten bestehen. Wenn wir unsere App erweitern, haben wir nun die folgende Struktur (die begleitenden test.js-Dateien werden der Einfachheit halber weggelassen)
twitter/
├── App.css
├── App.js
├── App.test.js
├── blog/
│ ├── HomePage.js
│ ├── TweetCard.js
│ ├── TweetDialog.js
│ ├── TweetList.js
│ ├── TweetListItem.js
│ ├── UserPage.js
│ └── UserCard.js
└── interaction/
├── FollowButton.js
├── LikeButton.js
└── ShareButton.js
Wir behalten unsere App-Datei, um React mit unserem Root-HTML-Tag zu initialisieren. Mit unseren Domänen an Ort und Stelle beginnen wir, unsere Container (wie HomePage und UserPage) und Komponenten (wie TweetCard und TweetListItem) zu erstellen. Alternativ könnten wir die Modelle innerhalb unserer Domänen weiter segmentieren, so dass sie wie folgt aussehen würden
twitter/
└── blog/
├── user/
│ ├── HomePage.js
│ ├── UserCard.js
│ └── UserPage.js
└── tweet/
├── TweetCard.js
├── TweetDialog.js
├── TweetList.js
└── TweetListItem.js
Aber angesichts der Größe der Anwendung ist dies zu diesem Zeitpunkt nicht notwendig.
Fügen Sie bei Bedarf Helfer hinzu
Mit zunehmender Komplexität unserer Anwendung wird unsere Benutzeroberfläche immer komplexer. Um damit umzugehen, haben wir zwei Methoden, um Verantwortlichkeiten zu trennen und Logik aus unseren Komponenten-Vorlagen auszulagern: Presenter und Utilities. Presenter lagern die gesamte visuelle Präsentationslogik aus den Vorlagen aus, um die View-Schicht so sauber und einfach wie möglich zu halten. Utilities sammeln gemeinsam genutzte Funktionalitäten für alle anderen Logiken im Front-End, die nicht spezifisch mit den Vorlagen zusammenhängen. Betrachten wir diese genauer.
Vorlagen mit Presentern bereinigen
Denken Sie an ein Twitter-Profil. Welche Elemente sehen Sie hier auf meinem Konto?

Es gibt Informationen, die direkt mit meinem Benutzer zusammenhängen: Name, Handle, Beschreibung, Ort, Website, Geburtstag, Startdatum. Es gibt auch Zählungen von Assoziationen zwischen anderen Modellen – wie viele andere Benutzer folgen mir? Wie vielen anderen Benutzern folge ich? Es gibt zusätzliche Logik, die nicht einmal auf der Seite erfasst ist, wie meine Tweets, Antworten, Medien-Uploads und von mir gelikte Inhalte. Um all diese Präsentationslogik angemessen zu erfassen, können wir eine zusätzliche Datei in unserem Dateibaum hinzufügen, um unser Presenter-Muster vom JSX-Komponenten zu isolieren
twitter/
└── blog/
├── user/
│ ├── UserCard.js
│ ├── UserCard.presenter.js
Logik in Utilities auslagern
Bestimmte Präsentationslogik ist so grundlegend, dass sie für Anwendungen nützlich sein könnte, unabhängig davon, ob sie im Rendering verwendet wird oder nicht. Formatierung von Währungen, Validierungen und Zeitstempelformatierung sind alles Anwendungsfälle, bei denen wir von isolierten Utility-Funktionen in unserer Anwendung profitieren könnten. Wo leben diese? Da sie Domänen umfassen, können Utilities in ihrem eigenen Ordner liegen
twitter/
├── App.css
├── App.js
├── App.test.js
├── blog/
│ ├── HomePage.js
│ ├── TweetCard.js
│ ├── TweetDialog.js
│ ├── TweetList.js
│ ├── TweetListItem.js
│ ├── UserCard.js
│ ├── UserCard.presenterjs
│ └── UserPage.js
├── interaction/
│ ├── FollowButton.js
│ ├── LikeButton.js
│ └── ShareButton.js
└── utils/
├── currency.js
├── time.js
└── validation.js
Es gibt keinen falschen Weg, Ihre App zu organisieren!
Letztendlich liegt die Wahl bei Ihnen. Dies ist nur ein Beispiel für unzählige Möglichkeiten, wie Sie Ihre Anwendung arrangieren könnten. Domain-Driven Design ist ein wertvolles Werkzeug, da es Geschäftslogik auf sinnvolle Weise trennt, eine klarere Unterscheidung für Domänenexpertise unter Entwicklern schafft und Regeln für die einfache Organisation und Skalierung Ihres Codes bietet.
Aber wenn Sie nach einer Alternative zum traditionellen Chaos von React-Anwendungsdateistrukturen suchen, werfen Sie einen Blick auf Domain-Driven Design. Es könnte genau das Richtige sein.
Zuletzt, wenn Ihnen diese Art von Inhalt gefällt und Sie mehr über Front-End, UI-Entwicklung und UX-Design und -Forschung lernen möchten (organisiert nach Ihrer Branchenerfahrung), betreibe ich einen kostenlosen Newsletter, den Sie sich vielleicht ansehen möchten.
Ich würde gerne DDD im Kontext einer komplexeren Anwendung angewendet sehen. Unser Team verwendet DDD auf der Backend-Seite, daher denke ich, dass es sinnvoll ist, das gleiche Modell für die Organisation des Codes im Front- und Backend zu verwenden.
Danke für den interessanten Artikel, Adam. Können Sie Open-Source-Projekte empfehlen, die diesen Organisationsstil verwenden? Ich würde gerne tiefer in dieses Thema eintauchen.
Sollte dies nicht eher Kontext-getriebenes Design genannt werden, da der Kontext hier die Datenmodelle verschiedener Domänen gruppiert?
Obwohl interessant, denke ich, dass dieser Artikel weit davon entfernt ist, was DDD sein soll.