Frage

In meinem Profiler Bericht Ich sehe immer die Ergebnisse der Mock-basierten Tests mit Dependency Injection. Viele der Abhängigkeiten waren statisch, sondern weil wir in Isolation testen Methoden wollen sie zu Instanzmitglieder, wie im folgenden Beispiel geändert:

class ShortLivedThing {
   IDependency1 dep1;
   IDependency1 dep2;
   IDependency1 dep3;
   ...

   int TheRealData;

   // Constructor used in production 
   public ShortLivedThing() {
     dep1 = new Dep1(); dep2 = new Dep2(); dep3 = new Dep3();
   }

   // DI for testing 
   public ShortLivedThing(IDependency1 d1, IDependency2 d2, IDependency3 d3) { 
     dep1 = d1(); dep2 = d2(); dep3 = d3();
   }
}

die Abhängigkeiten die meiste Zeit haben wiederum andere Abhängigkeiten und so weiter. Daraus ergibt sich die Instanziierung eines Baumes von (meist „statisch“) Objekte jedes Mal ein Methodenaufruf wird außerhalb von Tests durchgeführt. Jedes der Objekte sind sehr klein (nur ein paar Zeiger), aber der Baum-Effekt stellt sich dies in einer ständig wachsenden Leistungseinbußen.

Was können wir dagegen tun?

War es hilfreich?

Lösung

Es scheint mir, wie Sie die Eigenschaften eine richtige Dependency Injection-Framework Sie geben können, nutzen, benötigen. Verwenden Sie keine unterschiedliche Konstruktionslogik für die Prüfung / Produktion.

Mit dem Frühling sind Singletons Injektionen nur bei Containerstart ausgeführt. Prototype Injektionen werden jedes Mal getan. Die vollständige Verdrahtung wird auch jedes Mal getan Sie einen Komponententest ausführen, wenn es verdrahtet ist wird. So Tests Einheit Profilierung ist in der Regel keine gute Idee.

Vielleicht sind Sie mit zu wenig von Einzelreagenten Bereiche und zu viel Prototyp Umfang? (Prototyp = neue Instanz jedes Mal)

Das Schöne an Feder Injektion ist, dass Sie Umfang Proxies verwenden können, Ihren Objektgraph Sinn kann wie folgt aussehen:

 A Singleton
 |
 B Singleton
 |
 C Prototype (per-invocation)
 |
 D Singleton
 |
 E Session scope (web app)
 |
 F Singleton

Und würde jeder Anfrage nur erstellen 1 Instanz von C und eine Instanz von E pro Sitzung. A, B, D und F sind singletons. Wenn es nicht ein Webapp ist nicht du Sitzungsbereich standardmäßig, aber Sie können auch benutzerdefinierte Bereiche (ein „Fenster“ scope klingt cool für ein Fenster Desktop-Anwendung) machen. Der Schlüssel hier ist, dass Sie „einführen“ Bereiche auf jeder Ebene können, effektiv können Sie zehn Schichten von Singleton-Objekte haben und ganz plötzlich etwas Sitzung scoped auftaucht. (Dies kann wirklich revolutionieren, wie Sie einige Querschnittsfunktionen in einer geschichteten Architektur implementieren, aber das ist eine andere Geschichte)

Das gibt wirklich die minimale Objekterstellung möglich innerhalb eines DI-Modells, denke ich.

Obwohl in diesem Frühjahr für Java I ist eine Reihe von anderem DI-Frameworks glauben sollte ähnliche Funktionen unterstützen. Vielleicht nicht gerade die minimalistisch diejenigen.

Andere Tipps

Ich glaube, Sie sollten nur den „DI-Konstruktor“ haben. Sie rufen diesen Konstruktor für die Prüfung sowie in der Produktion.

class ShortLivedThing {
   IDependency1 dep1;
   IDependency1 dep2;
   IDependency1 dep3;
   ...

   int TheRealData;

   public ShortLivedThing(IDependency1 d1, IDependency2 d2, IDependency3 d3) { 
     dep1 = d1; dep2 = d2; dep3 = d3;
   }
}

Auf diese Weise können nicht das Problem der haben einen Baum von Objekten jedes Mal, wenn ein Methodenaufruf außerhalb des Tests erfolgt Instanziierung. Natürlich für die Produktion müssen Sie Ihre Objekte korrekt außerhalb die teilnehmenden Objekte selbst, was eine gute Sache ist verdrahten.

Zusammengefasst:. Gehen Sie nicht für 50% DI / 50% Hardcoding, gehen Sie für 100% DI

Wenn Ihr Anliegen die langsamen Tests ist, versuchen sie parallel laufen und lassen Sie sich nicht den Testprozess Ihre Programmierer unterbrechen.

Automatisieren diesen Prozess:

  • Wenn jemand in überprüft, macht einen Build aus dem Repository.
  • Ausführen Tests auf diesem Build.
  • E -. E-Mail an die Ergebnisse an den Entwickler, der im aufgegebenen

Es ist besser, wenn die erste Prüfung in nicht den tatsächlichen Repository erfolgt. Machen Sie es zu einem temporären ein und machen den Build aus diesem. Mail - Optional können Sie Performance-Tests, Stil Schecks usw. und sind diese in der E auszuführen. Wenn Sie dies tun, fügen Sie einen Schritt zu automatisierten Prozess:

  • Wenn Tests bestanden (und optional Kriterien erfüllt sind), um den neuen Code mit dem eigentlichen Repository zusammenführen.

Durch diese Weise sind langsam Tests keine Sorge. Auch wenn ein Entwickler muss wissen, ob ihr Code etwas brach oder machte den Leistungsschub sie erwartet, sie nur überprüft in und wartet auf die e -. Mail für sie erzeugt

Wie wäre es in Referenzen vorbei?

Das Beste, was ich mit oben kommen kann ist es, alle Abhängigkeiten in einem „Kontext“ Objekt zu setzen, die dann unter allen Instanzen gemeinsam genutzt wird. Dies sollte das Leistungsproblem etwas mildern.

Wenn Sie .NET Targeting Besuche die Autofac . Es hat verschiedene Bereiche (Singleton, Fabrik, Container) die Schaffung Aspekte, deterministisch Verfügung zu optimieren die Ressourcennutzung in Schach zu halten und ermöglicht GeneratedFactories und Lambda-Ausdrücke zu verwenden, um Komponenten zu konfigurieren und die Kosten für die Reflexion zu vermeiden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top