Wie man zirkuläre Abhängigkeiten zwischen Repositories bricht

9

Um zu beginnen, nein, ich benutze kein ORM und darf es auch nicht. Ich muss meine Repositories mit ADO.NET manuell rollen.

Ich habe zwei Objekte:

%Vor%

Beachten Sie die Referenzen zueinander, eine Firma hat eine Liste von Benutzern, jeder Benutzer hat nur eine Firma.

Nun möchte ich meine Repositories entwerfen:

%Vor%

So weit, so gut. Ich möchte die Firma für jeden Benutzer von meinem UserRepository laden. Das FirmRepository weiß, wie man eine Firma aus Persistenz erstellt, also möchte ich dieses Wissen mit dem FirmRepository behalten.

%Vor%

Wenn ich jetzt einen Benutzer über das UserRepository laden möchte, kann ich das FirmRepository bitten, die Benutzerfirma für mich zu erstellen. Bis jetzt, nichts zu verrückt hier.

Jetzt das Problem.

Ich möchte eine Liste von Benutzern aus meinem FirmRepository laden. Das UserRepository weiß, wie man einen Benutzer aus Persistence erstellt, also möchte ich dieses Wissen mit dem UserRepository behalten. Also gebe ich einen Verweis auf IUserRepository an das FirmRepository weiter:

%Vor%

Aber jetzt haben wir ein Problem. Das FirmRepository hängt von einer Instanz von IUserRepository ab und das UserRepository hängt nun von einer Instanz von IFirmRepository ab. Ein Repository kann also nicht ohne eine Instanz des anderen erstellt werden.

Wenn ich IOC-Container außerhalb dieser Gleichung halte (und ich sollte, b / c-Komponententests sollten keine IoC-Container verwenden), gibt es keine Möglichkeit für mich, das zu erreichen, was ich versuche.

Kein Problem, aber ich werde nur einen FirmProxy erstellen, um die Users-Sammlung aus Firm zu laden! Das ist eine bessere Idee, b / c Ich möchte nicht ALLE Benutzer die ganze Zeit laden, wenn ich gehe, um eine Firma oder eine Liste von Firmen zu bekommen.

%Vor%

Also, jetzt habe ich ein nettes Proxy-Objekt, um das Lazy-Loading zu erleichtern. Wenn ich also im FirmRepository aus Persistenz eine Firm erstellen will, gebe ich stattdessen einen FirmProxy zurück.

%Vor%

Aber das funktioniert immer noch nicht !!!

Um einen FirmProxy anstelle einer Firma zurückzugeben, muss ich einen FirmProxy in meiner FirmRepository-Klasse neu erstellen können. Nun, der FirmProxy nimmt eine IUserRepository-Instanz b / c. Das UserRepository enthält das Wissen, wie ein Benutzerobjekt aus der Persistenz erstellt wird. Da FirmProxy ein IUserRepository benötigt, benötigt mein FirmRepository jetzt auch ein IUserRepository, und ich bin gleich wieder am Anfang!

Wie kann ich also angesichts dieser langwierigen Erklärung / meines Quellcodes eine Instanz eines Benutzers aus dem FirmRepository und eine Instanz von Firm aus dem UserRepository erstellen ohne:

  1. den Benutzererstellungscode in das FirmRepository eingeben. Ich mag das nicht. Warum sollte das FirmRepository etwas über das Erstellen einer Instanz eines Benutzers wissen? Dies ist für mich eine Verletzung von SoC.
  2. Das Service Locator-Muster wird nicht verwendet. Wenn ich diesen Weg gehe, empfinde ich das als notorisch schwer zu testen. Außerdem machen Konstruktoren von Objekten, die explizite Abhängigkeiten verwenden, diese Abhängigkeiten offensichtlich.
  3. Eigenschaft Injektion anstelle von Konstruktor Injektion. Das behebt nichts, ich brauche immer noch eine Instanz von IUserRepository, wenn ich einen FirmProxy neu aufbaut, egal wie die Abhängigkeit in FirmProxy eingefügt wird.
  4. Sie müssen entweder das Firm- oder das User-Objekt "dumb down" machen und eine Firm-ID für den Benutzer anzeigen, zum Beispiel für eine Firma. Wenn ich nur ids mache, dann verschwindet die Anforderung, eine Firma aus dem UserRepository zu laden, aber mit ihr geht die Fülle, das Firm-Objekt nach etwas fragen zu können, was den Kontext einer bestimmten Benutzerinstanz betrifft.
  5. Rückgriff auf ein ORM. Ich möchte es wieder tun, aber ich kann nicht. Keine ORMs. Das ist die Regel (und ja, es ist eine beschissene Regel)
  6. Behalte alle meine injizierbaren Abhängigkeiten als Abhängigkeiten von der untersten Ebene der Anwendung, die die Benutzeroberfläche ist (in meinem Fall ein .NET-Webprojekt). Kein Betrug und Verwendung von IoC-Code im FirmProxy, um die entsprechende Abhängigkeit für mich neu zu erstellen. Das verwendet im Grunde genommen das Service Locator-Muster.

Ich denke über NHiberante und Enitity Framework nach, und es scheint, dass sie kein Problem haben, herauszufinden, wie man sql für ein einfaches Beispiel erzeugt, das ich vorgestellt habe.

Hat noch jemand andere Ideen / Methoden / etc ..., die mir helfen, das zu erreichen, was ich ohne ein ORM machen möchte?

Oder vielleicht gibt es einen anderen / besseren Weg, um das zu erreichen? Will ich nicht verlieren, ist die Fähigkeit, von einem Benutzer auf eine Firma zuzugreifen oder eine Liste von Benutzern für eine bestimmte Firma zu erhalten

    
Michael McCarthy 09.03.2012, 16:23
quelle

1 Antwort

5

Sie müssen klarer über Ihre gesamten Stammobjekte nachdenken, d. h. den Fokus jedes Repositorys. Sie erstellen kein Repository für jede Tabelle in Ihrer Datenbank, das ist nicht das Ziel. Die Absicht besteht darin, das aggregierte Stammobjekt zu identifizieren, mit dem Sie arbeiten müssen, einschließlich der untergeordneten Tabellen / Datensätze, d. H. Benutzer (Firma, Adresse, Zugriffsrechte). Das wird Ihr Repository zu Ihrer App zurückgeben.

Die Schwierigkeit, die Sie haben, zeigt Ihnen, dass Ihre Repositories nicht richtig strukturiert sind. Jedes Mal, wenn ich feststelle, dass mein Code zu schwierig wird, weckt das bei mir die Warnung, dass ich es wahrscheinlich falsch mache. Ich lebe mein Leben damit;)

    
Lazarus 09.03.2012 16:28
quelle