Die MVC-Services-Architektur ist in Symfony-Projekten so verbreitet, dass es sich wie die einzige Möglichkeit anfühlt. Es ist einfach, vertraut und funktioniert ... bis es nicht mehr funktioniert. Wenn Ihr Projekt wächst, beginnen sich Risse zu zeigen: Ihre Geschäftslogik ist überall, das Verhalten der App ist unklar und die Codepflege wird mühsam. Obwohl dies der gängigste Ansatz ist, zwingt Sie Symfony nicht dazu, dabei zu bleiben.
Was wäre, wenn es einen besseren Weg gäbe?
Wenn ein Projekt wächst, verteilt sich die Geschäftslogik tendenziell über die gesamte Codebasis. Jede Ebene des Projekts – Controller, Dienste, Formulare, Entitäten – enthält letztendlich Teile des Domänenmodells. Dadurch wird es immer schwieriger, sich auf einen bestimmten Teil zu konzentrieren.
Wenn Ihre Architektur auf technischen Ebenen organisiert ist, wird es mit zunehmendem Projekt schwieriger, klare Grenzen zwischen verschiedenen Kontexten zu erkennen. Dieser Mangel an Klarheit kann zu eng gekoppelten Code- und Wartungsherausforderungen führen.
Da die Standardarchitektur den Schwerpunkt auf technische Schichten legt, wird es ziemlich schwierig, das Verhalten des Projekts zu verstehen. Sie könnten daraus schließen, dass bestimmte Entitäten von bestimmten Diensten verwaltet werden, oder das Datenbankschema erraten, aber das tatsächliche Verhalten des Projekts, das die wichtigsten Aspekte darstellt, bleibt unklar und implizit.
Wenn die Geschäftslogik über das gesamte Projekt verteilt und mit Implementierungsdetails vermischt ist, wird es schwierig, sie unabhängig weiterzuentwickeln. Im Laufe der Zeit ist der Lebenszyklus der Geschäftslogik tendenziell viel länger als der der Implementierungsdetails (z. B. Frameworks, APIs von Drittanbietern oder Datenbanken). Diese Nichtübereinstimmung zwingt Sie dazu, große Teile des Codes neu zu schreiben, wenn auch nur geringfügige Änderungen in einer Abhängigkeit auftreten.
Um es einfacher zu machen, sich bei Bedarf auf die Geschäftslogik zu konzentrieren, besteht der erste Schritt darin, sie vom Rest des Projekts zu isolieren. Erstellen Sie dazu einen Ordner Domain. Dieser Ordner wird zum Kern des Projekts, in dem die Geschäftslogik mithilfe reiner PHP-Objekte modelliert wird, frei von Abhängigkeiten von Implementierungsdetails. Während der Rest des Projekts von diesem Ordner abhängt, ist der Domänenordner von niemandem abhängig.
Im Domänenordner sollten Dateien nach Domänenzweck und nicht nach technischem Zweck gruppiert werden. Dies bedeutet, dass es hier keine Ordner für Entitäten, Dienste oder Controller gibt, sondern nur Ordnernamen, die Funktionen oder Domänenkonzepten entsprechen.
Der wichtigste Aspekt eines Projekts ist, was es macht, die Aktionen, die es bewältigen kann. Diese Aktionen stellen das Verhalten des Projekts dar und sollten als einzige Möglichkeit dienen, auf die Geschäftslogik zuzugreifen. Um dies widerzuspiegeln, erstellen Sie einen Ordner Anwendung, der alle Verhaltensweisen des Projekts explizit anzeigt. Als neuer Entwickler des Projekts sollte ich beispielsweise in der Lage sein, auf einen Blick zu verstehen, wozu das Projekt in der Lage ist, indem ich mir diesen Ordner ansehe.
Mit den Ordnern App und Domain können Sie sich ganz einfach auf die Geschäftslogik konzentrieren. Irgendwann muss diese Geschäftslogik jedoch mit externen Systemen interagieren. Um dies zu bewältigen, erstellen Sie einen dritten Ordner mit dem Namen Infrastructure, der alle Implementierungsdetails wie Framework-spezifischen Code, Datenbankverbindungen und Bibliotheken enthält.
Dateien im Infrastrukturordner hängen von den App- und Domänendateien ab. Beispielsweise könnten sie einen Anwendungshandler aus dem App-Ordner aufrufen oder eine im Domänenordner definierte Schnittstelle implementieren.
Konkret geht es in Symfony darum, den Controller-Ordner zu ändern und zu deklarieren, welche Dienste welche Schnittstellen implementieren.
# config/routes.yaml controllers: resource: path: ../src/Catalog/Infrastructure/Controller/ namespace: App\Catalog\Infrastructure\Controller type: attribute
Während sich Ihr Projekt weiterentwickelt, stellen Sie möglicherweise fest, dass einige Teile der Geschäftslogik ihren eigenen Platz in der Architektur verdienen. Ein guter Indikator ist, wenn derselbe Begriff je nach Kontext unterschiedliche Bedeutungen hat. Beispielsweise könnte sich das Wort „Produkt“ auf ein Fabrikprodukt, ein Lagerprodukt oder ein E-Commerce-Produkt beziehen, die jeweils ein eigenes Modell erfordern. Ein Gottobjekt kann ebenfalls ein guter Indikator sein; Die User-Klasse weist in Symfony-Projekten häufig solche Probleme auf.
Wenn dies geschieht, ist es an der Zeit, es zu extrahieren und seine Geschäftslogik unabhängig weiterentwickeln zu lassen.
Einige Kontexte bilden den Kern Ihres Projekts, während andere es unterstützen. Generische Kontexte wie Auth können eine einfachere Architektur verwenden, da sie für Ihre Domain nicht von zentraler Bedeutung sind
In diesem Bild können wir sehen, dass der Auth-Kontext eine Standard-Symfony-Struktur verwendet, die Bestell- und Katalogkontexte eine domänenorientierte Architektur verwenden und der Versandkontext eine funktionsorientierte Architektur verwendet.
Wenn ein bestimmter Kontext so weit wächst, dass er unabhängig skaliert werden muss, sollten Sie erwägen, ihn in eine separate Bereitstellungseinheit aufzuteilen.
Überstürzen Sie diesen Schritt jedoch nicht. Beginnen Sie damit, Ihr Projekt modular zu gestalten. Wenn Sie feststellen, dass ein Kontext individuell skaliert werden muss, stellen Sie ihn separat bereit.
Teilen Sie die Codebasis nur auf, wenn organisatorische Herausforderungen auftreten, z. B. wenn zwei Teams Schwierigkeiten haben, an derselben Codebasis zusammenzuarbeiten.
Bei der Erkundung dieser Lösungen haben wir verschiedene handwerkliche Konzepte angewendet. Lassen Sie uns sie benennen und kurz erläutern, damit Sie tiefer in sie eintauchen können.
Hinter diesem ungewöhnlichen Begriff verbirgt sich ein sehr einfaches Konzept. Die allgegenwärtige Sprache ist das Vokabular, das Ihr Team zur Beschreibung Ihres Domänenmodells verwendet. Dieses Vokabular sollte überall dokumentiert und konsequent verwendet werden, in Produktgesprächen, in der Codebasis und darüber hinaus.
Konkret: Erstellen Sie eine Markdown-Datei an der Wurzel eines begrenzten Kontexts und bringen Sie Produktleute, Fachexperten und Technologieteams zusammen, um jedes Konzept Ihres Projekts zu definieren.
Ein begrenzter Kontext definiert die sprachliche Grenze innerhalb Ihres Projekts und trennt Teile des Systems, in denen die allgegenwärtige Sprache nicht mehr passt. Tools wie Kontextkarten und Event Storming können dabei helfen, diese Grenzen zu identifizieren.
Ein begrenzter Kontext ist ein abstraktes Konzept; Es kann auf viele Arten implementiert werden, von einem einfachen Ordner in einem modularen Monolithen bis hin zu einem Cluster in einer Microservices-Architektur.
Alle diese Architekturen zielen darauf ab, die Geschäftslogik von den Implementierungsdetails zu isolieren. Unabhängig davon, ob Sie Ports und Adapter, Hexagonal oder Clean Architecture verwenden, besteht die Kernidee darin, die Geschäftslogik Framework-unabhängig und einfach zu testen zu machen.
Sobald Sie dies im Kopf haben, gibt es ein umfassendes Spektrum an Implementierungen, und die beste hängt von Ihrem Kontext und Ihren Vorlieben ab. Ein großer Vorteil dieser Architektur besteht darin, dass sie durch die Isolierung Ihrer Geschäftslogik wesentlich effizientere Tests ermöglicht.
Die Idee, Ordner und Dateien so zu organisieren, dass sie die Geschäftslogik „schreien“, wird als Screaming Architecture bezeichnet. Dieses Konzept betont, dass die Struktur Ihres Codes den Zweck des Projekts sofort klar machen sollte. Das Ziel besteht darin, dass ein neuer Entwickler auf einen Blick versteht, was das Projekt bewirkt.
Ich empfehle dringend, Onkel Bobs Artikel zu diesem Thema zu lesen – sein Vergleich mit einem Hausplan ist besonders aufschlussreich.
Vertikales Slicing organisiert Ihr Projekt nach Features, sodass sich jedes Feature unabhängig weiterentwickeln kann. Es ermöglicht Ihnen, je nach Komplexität und Reife unterschiedliche Architekturen auf unterschiedliche Funktionen anzuwenden.
Obwohl die Idee interessant ist, erfordert sie hochqualifizierte Ingenieure, um eine solche Architektur effektiv zu implementieren und zu warten.
Die Art und Weise, wie Sie Ihr Symfony-Projekt strukturieren, hat einen tiefgreifenden Einfluss auf dessen Skalierbarkeit, Wartbarkeit und Klarheit. Indem Sie Ihre Geschäftslogik isolieren und Verhaltensweisen explizit machen, schaffen Sie ein System, das leichter zu verstehen und weiterzuentwickeln ist.
Wenn Sie mit diesen Ideen noch nicht vertraut sind, machen Sie sich keine Sorgen, Software-Handwerkskunst ist eine Reise, kein Ziel. Die Konzepte mögen auf den ersten Blick überwältigend erscheinen, aber jedes einzelne wird Ihnen dabei helfen, mehr Wert für Ihr Unternehmen zu schaffen.
Haben Sie Fragen oder möchten Sie Ihre Erfahrungen teilen? Schreib sie in die Kommentare! Und bleiben Sie gespannt auf den nächsten Artikel ?
Das obige ist der detaillierte Inhalt vonEine andere Möglichkeit, Ihr Symfony-Projekt zu strukturieren. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!