So funktioniert der Hand DI mit tiefen Objektgraphen und viele Abhängigkeiten zu tun richtig

StackOverflow https://stackoverflow.com/questions/2425458

  •  19-09-2019
  •  | 
  •  

Frage

Ich glaube, diese Fragen wurde in einem oder anderen Art und Weise gefragt, aber ich bin immer noch nicht.

Wir haben ein GWT-Projekt und mein Projektleiter nicht erlaubt zu GIN / Guice als DI Rahmen (neue Programmierer nicht gehen, es zu verstehen, argumentierte er), damit ich versuche zu tun, die DI manuell.

zu verwenden

Jetzt habe ich ein Problem mit tiefen Objektgraphen. Die Objekthierarchie aus der Benutzeroberfläche sieht wie folgt aus:

AppPresenter-> DashboardPresenter-> GadgetPresenter-> GadgetConfigPresenter

Der GadgetConfigPresenter Weg nach unten der Objekthierarchie Baum hat einige Abhängigkeiten wie CustomerRepository, ProjectRepository, MandatorRepository, etc.

So ist der GadgetPresenter die die GadgetConfigPresenter schaffen auch diese Abhängigkeiten haben und so weiter, bis zum Eintrittspunkt der App, die die AppPresenter erstellt.

  • Ist das die Art und Weise manuell DI funktionieren soll?
  • bedeutet dies nicht, dass ich alle Abhängigkeiten beim Booten schaffen auch ich sie nicht brauchen?
  • wäre ein DI Framework wie GIN / Guice mir helfen hier?
War es hilfreich?

Lösung

Sie schreiben, dass

  

die GadgetPresenter, die die GadgetConfigPresenter schafft [.]

Statt direkt die Schaffung GadgetConfigPresenter Fällen GadgetPresenter sollte nimmt eine Abhängigkeit von einem Abstract Factory dass GadgetConfigPresenter Instanzen für sie schaffen. Dies drückt die inneren Abhängigkeiten von GadgetConfigPresenter zur Fabrik.

Mit Constructor Injection den ganzen Weg, Ihre Poor Man DI Verkabelung sollte wie folgt (Entschuldigung für die C # Syntax) aussehen:

var customerRepository = new CustomerRepository(/*...*/);
var projectRepository = new ProjectRepository(/*...*/);
var mandatorRepository = new MandatorRepository(/*...*/);

var gadgetConfigPresenterFactory = 
    new GadgetConfigPresenterFactory(
        customerRepository,
        projectRepository,
        mandatorRepository);

var gadgetPresenter = new GadgetPresenter(gadgetConfigPresenterFactory);
var dashboardPresenter = new DashboardPresenter(gadgetPresenter);
var appPresenter = new AppPresenter(dashboardPresenter);

Beachten Sie, wie wir bricht die Abhängigkeitskette häufig, um sicherzustellen, dass die Anzahl der Abhängigkeiten für jeden Verbraucher nie zu groß wird.

Im Prinzip bedeutet dies, dass Sie alle Abhängigkeiten beim Booten erstellen müssen, wenn Sie ein faul Beladestrategie .

Solche Dinge wie die Verwaltung von Lebensdauern sind genau die Art von Dingen, wo ein DI Container enorm hilfreich sein kann, aber es ist durchaus möglich, die gesamte Anwendung zu schreiben, indem nur folgende dI Muster und Prinzipien .

Alles in allem aber ich würde immer noch einen DI-Container, wenn überhaupt möglich empfehlen.

Andere Tipps

Sie können DI tun Context Schnittstellen. Es ist nicht schwer, und ziemlich geradlinig.

Ein Context-Interface ist eine Klasse, die alle Bindungen aus der guice Modulkonfiguration aussetzt.

Dies ist ein Beispiel dafür, wo ich gehe davon aus, dass AppPresenter + DashboardPresenter in einem Paket und muss einen „Kontext“, während GadgetPresenter und GadgetConfigPresenter in einem anderen Paket und muss eine anderen „Kontext“. Die Anzahl von Kontexten, und wie sie zu handhaben, liegt ganz an den Benutzer.

/**
 * The dependencies that need to be injected for package1
 */
public interface SomePackageContext {
  GadgetPresenter getGadgetPresenter();
  GadgetConfigPresenter getGadgetConfigPresenter();
}

/**
 * The dependencies that need to be injected for package2
 */
public interface OtherPackageContext {
  // These methods can take arguments..
  AppPresenter getAppPresenter(Args..);
  DashboardPresenter getDashboardPresenter(Args..);
}

/**
 * All of the DI needed in our project.
 *
 * <p>We don't need the two interfaces above, we can put 
 * everything in this interface if we have a small
 * project where layering is not a big issue.
 */
public interface PresenterContext 
    extends SomePackageContext, OtherPackageContext {
}


public class MockPresenterContext implements PresenterContext {
  ...
}

public class RealPresenterContext implements PresenterContext {
  // This is similar to bind(...) in guice
  public AppPresenter getAppPresenter(Args..) {
    return new AppPresenter(this, otherargs...);
  }
  public DashboardPresenter getDashboardPresenter(Args..) {
    return new DashboardPresenter(this, otherargs...);
  }
  public GadgetPresenter getGadgetPresenter() {
    return new GadgetPresenter(this);
  }
  public GadgetConfigPresenter getGadgetConfigPresenter() {
    return new GadgetConfigPresenter();
  }
}

public class DashboardPresenter {

  // @Inject
  private final GadgetPresenter gadgetPresenter;

  /*
   * We inject everything using the SomePackageContext.
   */
  public DashboardPresenter(SomePackageContext ctxt) {
    this.gadgetPresenter = ctxt.getGadgetPresenter();
  }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top