MVC und das Repository-Muster: Rollen von Controllern, Modellen und Repositories?

8

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:

  1. Ist dies eine korrekte Implementierung des Repository-Musters?
  2. Ich verstehe, dass der Controller die Informationen des Benutzers aus der Anfrage übernehmen und in das Modell eingeben sollte. Wie kommt das normalerweise vor? Soll der Controller ein User-Objekt erstellen und dieses dann in das Modell übernehmen? Ich will aber nicht einfach ein Array von Werten in das Modell einreichen - noch möchte ich 15 Argumente an die Modellmethode übergeben, die einen Benutzer erstellt.
  3. Damit dieses Muster wirklich funktioniert, sieht es so aus, als müsste ich ein Domänenobjekt haben, das nur eine einfache Datenstruktur ohne Verhalten ist. Wenn ich ein ORM verwende, würde ich ein ORM haben Objekt, das beschreibt, wie das Objekt beibehalten wird. Anfangs habe ich mich dagegen gewehrt, weil es sich anfühlt wie doppelter Code, aber wenn ich Persistenz wirklich von der Geschäftslogik trennen würde, wäre das nötig, oder? Zum Beispiel, was ist, wenn ich mit einem In-Memory-Speicher gehe? Ich würde das ORM-Objekt nicht mehr verwenden.

Darf ich hier richtig denken? Ist das akzeptabel? Bitte hilf mir, die Punkte in meinem Kopf zu verbinden.

    
Jesse Bunch 09.09.2012, 23:57
quelle

2 Antworten

1
  

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:

%Vor%
  

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.

    
casablanca 10.09.2012, 00:43
quelle
14

1. Ist dies eine korrekte Implementierung des Repository-Musters?

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.

2. Soll der Controller ein Benutzerobjekt erstellen und dieses dann in das Modell übernehmen?

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:

  1. 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.

  2. 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.

3. (..) Hauptobjekt, das ist nur eine einfache Datenstruktur ohne Verhalten und dann (..)

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.

    
tereško 10.09.2012 01:04
quelle