10 Stimmen

DI-Container, Fabrik oder neu für flüchtige Objekte?

Wenn es sich um Objekte handelt, die Daten erfordern, die nur zur Laufzeit bekannt sind, wie z. B. Benutzername und Kennwort, wo sollte die Objektinstanziierung erfolgen: mit new, in einer Fabrik oder in einem DI-Container?

Ich könnte zum Beispiel einfach new ein Objekt, sobald ich die Daten habe:

UserCredentials creds =
    new UserCredentials(dialog.getUsername(), dialog.getPassword());

Oder ich könnte eine Fabrik benutzen:

UserCredentials creds =
    CredentialsFactory.create(dialog.getUsername(), dialog.getPassword());

Oder ich könnte einen Provider innerhalb eines DI-Containers verwenden (der in diesem Fall im Wesentlichen eine parametergesteuerte Fabrik wäre). [Beispielcode ausgelassen].

Es scheint sowohl falsch, den DI-Container für etwas so Einfaches zu verwenden, als auch falsch, ihn nicht in vollem Umfang zu nutzen.

9voto

Mark Seemann Punkte 216836

Wie immer kommt es darauf an, aber in der Regel ist eine statische Fabrik wie Ihre zweite Option nur selten eine gute Idee.

new Die Erstellung eines UserCredentials-Objekts scheint eine gute Wahl zu sein, da die Klasse UserCredentials wie eine in sich geschlossene, konkrete Klasse aussieht, die vollständig mit all ihren Invarianten aus dem Benutzernamen und dem Kennwort instanziert werden kann.

In anderen Fällen kann der Typ, den Sie erstellen möchten, eine Abstraktion an sich darstellen. Wenn dies der Fall ist, können Sie nicht die new Schlüsselwort, sondern muss ein Abstrakte Fabrik stattdessen.

Die Verwendung einer abstrakten Fabrik ist oft sehr wertvoll, da sie es Ihnen ermöglicht, eine Instanz aus einer Kombination von Laufzeitwerten und anderen Abhängigkeiten zusammenzustellen. Siehe aquí für weitere Informationen.

Die Verwendung einer abstrakten Fabrik hilft auch bei Unit-Tests weil Sie einfach testen können, ob der Rückgabewert oder Endzustand oder was auch immer Sie interessiert, mit der Ausgabe der abstrakten Fabrik zusammenhängt - wofür Sie einfach eine Test Double weil sie... abstrakt ist.

3voto

Wim Coenen Punkte 64891

Der Google Testing Blog hat ein Beitrag, der diese Frage zu beantworten versucht . Der Grundgedanke ist, dass Sie jede Ihrer Klassen als "newable" oder "injectable" klassifizieren können und dass es in Ordnung ist, nur die newables "neu zu machen".

Ich unterscheide 2 Hauptkategorien von "Newables":

  • Werte wie int , string , DateTime und so weiter.
  • Einrichtungen wie Customer , Order , Employee und so weiter. Ich denke, Ihr UserCredentials Klasse fällt unter diese Rubrik.

Es ist wichtig zu erkennen, dass Newables können (testbares) Verhalten haben . Wenn Sie den Fehler machen, zu denken, dass neue Variablen keine Verhaltens- oder Einheitstests haben sollten, werden Sie mit dem anämisches Domänenmodell Anti-Muster.

Ein Nebeneffekt von "newables" mit Verhalten ist, dass dieses Verhalten nicht in den Unit-Tests Ihrer injectables abstrahiert werden kann. Das ist in Ordnung; es ist normal, dass es eine starke Kopplung zwischen Ihrem Domänenmodell und dem Rest Ihrer Anwendung gibt.

Auch Neuankömmlinge dürfen über Injektionsmittel Bescheid wissen, aber sie arbeiten nur vorübergehend mit ihnen zusammen. Zum Beispiel, UserCredentials sollte nicht eine IUserDatabase als Argument für den Konstruktor. Stattdessen könnte es eine UserCredentials.Verify(IUserDatabase) Methode.

bearbeiten: Ich bin mir jetzt nicht mehr so sicher, was ich oben geschrieben habe. Entitäten können auch über (injizierbare) Fabriken konstruiert werden, anstatt ihren Konstruktor direkt aufzurufen. Die Fabrikimplementierung kann dann Dinge in die Entität injizieren.

0voto

Tony The Lion Punkte 59566

Ich verwende DI, um eine lose Kopplung zwischen Objekten herzustellen. Wenn Ihre Objektabhängigkeiten durch die Erstellung eines Objekts mit new stark beeinträchtigt werden, sehe ich nicht ein, warum Sie nicht DI verwenden oder die Objekterstellung an eine Factory weiterleiten sollten. Das gibt Ihnen mehr Kontrolle und hält Ihre Klassen locker gekoppelt.

Es kommt wirklich darauf an, wann und wo Sie dieses Objekt benötigen und ob sich daraus unnötige Abhängigkeiten ergeben.

0voto

D.C. Punkte 15161

Wenn Sie bereits einen DI-Container für Ihre Anwendung eingerichtet haben, können Sie diesen Ansatz verwenden. Wenn nicht, verwenden Sie eine Factory-Methode.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X