Ich habe also die Rolle des Repository-Musters untersucht, um die Persistenzschicht von meinen Modellen in einem MVC-Framework zu entkoppeln. Zuvor könnte ich meine UserModel
aktive Record-Methoden direkt aufrufen, um Domain-Objekte zu speichern / abzurufen.
Hier ist eine Skizze dessen, was ich in Bezug auf den Call-Stack in einer Anfrage denke, die ein neues User
erstellen sollte:
Hier sind meine Fragen:
Darf ich hier richtig denken? Ist das akzeptabel? Bitte hilf mir, die Punkte in meinem Kopf zu verbinden.
Soll der Controller ein Benutzerobjekt erstellen und dieses dann an das Modell übergeben?
Ich bin nicht sicher, was Sie meinen, indem Sie "das in das Modell übergeben" - das User
object ist das Modell. "Controller" und "Modell" repräsentieren verschiedene Ebenen im Design, sie sind keine spezifischen Objekte, und es sollte kein separates UserModel
-Objekt wie erwähnt geben.
Die Repository-Schnittstelle selbst wird im Allgemeinen als Teil des Modells betrachtet, obwohl die Domänenobjekte nicht selbst gespeichert werden sollten - dies sollte im Controller erfolgen.
Der Job Ihres Controllers wäre dann, die Anfrage zu interpretieren und ein User
-Objekt zu erstellen. Verwenden Sie dann das Repository, um den Benutzer zu speichern:
es sieht für mich aus Ich müsste ein Domain-Objekt haben, das ist nur eine einfache Datenstruktur ohne Verhalten
Dies ist nicht wahr, Sie können und sollten das Verhalten in Ihren Domänenobjekten kapseln. Was die Persistenz betrifft, sollte ein gutes ORM die meisten Details berücksichtigen und Sie sollten keine zusätzlichen Klassen manuell erstellen müssen.
Ich bin mir nicht sicher, wo Sie diese Forschung gemacht haben, aber Sie haben es falsch verstanden.
Repositories zur Trennung von Domain-Objekte von Data-Mappern .
Es gibt keine "Modelle". Modell im MVC-Entwurfsmuster ist einer der Hauptschichten: Präsentationsschicht und Modellschicht .
Und das Repository-Muster ist nicht mit dem aktiven Datensatz (anti) pattern kompatibel, der Domänen- und Speicherlogik kombiniert in einem einzelnen Fall, was zu einem großen SRP Verstoß führt.
Ein Beispiel aus der realen Welt für, wann und wie man ein Repository benutzt, ist ein Beispiel:
Sie erstellen ein Dokumentverwaltungstool, bei dem die Dokumente aus verschiedenen Quellen stammen können (z. B. lokale SQL-Datenbank, SOAP-Dienst und Cache). In diesem Fall erstellen Sie ein Repository, das sich mit dem "Routing" des Speichers beschäftigt. Es ist der Teil der Anwendung, der entscheidet, welcher Datenmapper zum Speichern / Abrufen jedes Dokuments verwendet werden soll.
Das Ziel des Repository besteht darin, die Domänenlogik von der Interaktion mit dem Speicher zu trennen. Für das System, das oben beschrieben wurde, würde ein Repository auch neue Datenquellen hinzufügen, ohne dass große Mengen an Code (falls vorhanden) neu geschrieben werden müssen. Sie könnten einfach einen anderen Mappertyp für das Dokument hinzufügen.
Zunächst sollte der Controller selbst nichts erstellen. Stattdessen sollte Ihr Controller eine Factory zum Erfassen der Instanz des Objekts verwenden, das Sie benötigen. Diese Fabrik kann der Steuerung durch einen Konstruktor oder eine andere Methode zur Verfügung gestellt werden. Das nennt man: Dependency Injection (um mehr darüber zu erfahren, diesen Vortrag ansehen ) .
Wie oben erwähnt, ist das Modell auch eine Ebene, keine bestimmte Klasse oder ein bestimmtes Objekt. Die Verantwortung des Controllers besteht darin, den Status der Modellschicht zu ändern (indem Daten an ihn weitergegeben werden). Sie könnten mit Domänenobjekten und Mappern (oder Repositorys) direkt in der Steuerung interagieren, aber es würde bedeuten, dass einige der Geschäftslogik in der Steuerung verloren gehen. Es wird empfohlen, stattdessen Dienste zu verwenden, die dann die Domänenobjekte und speicherbezogenen Strukturen manipulieren.
Was das Problem mit dem Parameter 10+ betrifft, das Sie für die Erstellung eines neuen Benutzerkontos benötigen würden, nehmen wir an, Sie haben eine Aktion mit folgendem Footprint:
%Vor% Wenn die Aktion mit einer bestimmten Request
-Instanz aufgerufen wird, haben Sie zwei Möglichkeiten, mit einer großen Anzahl von Parametern umzugehen:
Umschließen Sie die Instanz in einem Dekorierer , damit Sie eine einzige Methode zum Erstellen der Daten aus der Anforderung aufrufen können ein spezifisches Array Dann übergeben Sie dieses Array an die Dienste.
Bilden Sie das Array innerhalb der Aktion des Controllers und übergeben Sie es, wo die Daten benötigt werden.
Die erstgenannte Lösung eignet sich eher für groß angelegte Anwendungen, bei denen eine solche Datenbildung während des gesamten Codes wiederholt erforderlich wäre. Aber in einem kleinen / mittleren Projekt ist die zweite Option der Common-Sense-Ansatz.
Die Aufgabe des Controllers besteht darin, die Benutzereingabe zu übernehmen und sie an die Modellschicht und die aktuelle Ansicht zu verteilen. Und die Bildung eines solchen Arrays passt genau zu diesem Mandat.
Nein. Domänenobjekt ist nicht "einfache Daten". Hier befindet sich der Großteil der Geschäftslogik der Domäne in der Anwendung.
Und vergessen Sie magische ORMs. Der erste Schritt zur Implementierung eines Repositories besteht darin, die Domänen- und Speicherlogik zu trennen. Domain-Objekt behandelt die Validierungs- und Geschäftsregeln, Mapper beschäftigt sich mit Persistenz und Datenintegrität (kleines Beispiel hier ).
Eine weitere Sache, die Sie beachten müssen, ist, dass Repositories für Web-Anwendungen nicht wirklich mit In-Memory-Persistenz interagieren (abgesehen vom Cache). Stattdessen würde Ihr Repository Mapper für verschiedene Datenquellen jonglieren.
Tags und Links php model-view-controller design-patterns repository-pattern