Wie würde man eine Abhängigkeitsinjektion in Scala durchführen?

75

Ich bin noch am Anfang darin, neben Java auch Scala zu lernen, und ich habe es nicht verstanden, wie soll man dort DI machen? Kann oder sollte ich eine vorhandene DI-Bibliothek verwenden, sollte dies manuell erfolgen oder gibt es einen anderen Weg?

Fabian
quelle

Antworten:

60

Standard-Java-DI-Frameworks funktionieren normalerweise mit Scala. Sie können jedoch auch Sprachkonstrukte verwenden, um den gleichen Effekt ohne externe Abhängigkeiten zu erzielen .

Dan Story
quelle
Der Link gibt mir einen wirklich guten Überblick mit vielen Beispielen. Vielen Dank.
Fabian
4
fwiw, dieser Artikel war eine der stärksten Inspirationen, die ich hatte, als ich anfing, Scala zu lernen.
Daniel C. Sobral
Ich bin gespannt, wie das Kuchenmuster implementiert wird, wenn ein Dienst oder eine Registrierung möglicherweise eine unterschiedliche Anzahl von Instanzen einer Komponente benötigt. Was wäre zum Beispiel, wenn WarmerComponentImpl im verknüpften Beispiel zwei verschiedene Instanzen einer OnOffDeviceComponent benötigt, um ihre Arbeit zu erledigen?
Mitch Blevins
1
@MitchBlevins, werfen Sie einen Blick auf den Abschnitt "Mehrere Implementierungen" im Handbuch " Abhängigkeitsinjektion in Scala" .
Adamw
Für einen allgemeinen Überblick über DI in Scala. Werfen
Sky
15

Eine neue Abhängigkeitsinjektionsbibliothek speziell für Scala ist Dick Walls SubCut .

Während der Artikel von Jonas Bonér, auf den in der Antwort von Dan Story verwiesen wird, gebundene Instanzen zur Kompilierungszeit und statische Injection (über Mix-Ins) hervorhebt, basiert SubCut auf der Laufzeitinitialisierung unveränderlicher Module und der dynamischen Injection durch Abfragen der gebundenen Module nach Typ, String-Namen, oder scala.Symbolnamen.

Weitere Informationen zum Vergleich mit dem Kuchenmuster finden Sie im GettingStarted- Dokument.

Allan Erskine
quelle
9

Die Abhängigkeitsinjektion selbst kann ohne Unterstützung von Tools, Frameworks oder Containern durchgeführt werden. Sie müssen nur news aus Ihrem Code entfernen und in Konstruktoren verschieben. Der einzige mühsame Teil, der übrig bleibt, ist die Verkabelung der Objekte am "Ende der Welt", wo Container viel helfen.

Mit den 2.10-Makros von Scala können Sie den Verdrahtungscode zur Kompilierungszeit generieren und verfügen über eine automatische Verdrahtung und Typensicherheit.

Siehe die Abhängigkeitsinjektion im Scala-Handbuch

Adamw
quelle
2
So wenige Leute merken das, dass ich es als Interviewfrage benutze.
Tim Barrass
2

Ein aktuelles Projekt zeigt einen DI, der ausschließlich auf der Konstruktorinjektion basiert: zalando / grafter

Was ist wieder falsch an der Konstruktorinjektion?

Es gibt viele Bibliotheken oder Ansätze für die Abhängigkeitsinjektion in Scala. Grafter kehrt zu den Grundlagen der Abhängigkeitsinjektion zurück, indem er nur die Konstruktorinjektion verwendet : keine Reflexion, keine XML, keine Anmerkungen, keine Vererbung oder Selbsttypen.

Dann fügt Grafter der Konstruktorinjektion nur die notwendige Unterstützung hinzu, um:

  • Instanziieren einer komponentenbasierten Anwendung aus einer Konfiguration
  • Feinabstimmung der Verkabelung (Singletons erstellen)
  • Testen Sie die Anwendung, indem Sie Komponenten austauschen
  • Anwendung starten / stoppen

Grafter zielt auf jede mögliche Anwendung ab, da es sich darauf konzentriert, nur drei Ideen zu verknüpfen:

  • Fallklassen und Schnittstellen für Komponenten
  • Reader-Instanzen und formlos für die Konfiguration
  • Baumumschreibung und Kiama für alles andere!
VonC
quelle
1

Ich habe es selbst nicht getan, aber die meisten DI-Frameworks arbeiten auf Bytecode-Ebene (AFAIK), sodass es möglich sein sollte, sie mit jeder JVM-Sprache zu verwenden.

Marcelo Cantos
quelle
2
Ein Standard-Java-DI-Framework, das ich in den letzten Jahren in Scala erfolgreich verwendet habe, ist PicoContainer. (Und Sie können Konstruktorinjektion anstelle von Setterinjektion verwenden, um die Unveränderlichkeit aufrechtzuerhalten.)
Seth Tisue
Spring ME ist ein Abhängigkeitsinjektionsframework, das die Quellcodeanalyse verwendet, um das meiste zu erreichen, was Full zur Laufzeit tut. Infolgedessen erhalten Sie einen Anwendungskontext mit nahezu null Footprint, der nicht von externen Bibliotheken abhängt. Ich bin mir nicht sicher, ob ich es für Scala verwenden würde.
Wilfred Springer
1

In früheren Beiträgen wurden die Techniken behandelt. Ich wollte einen Link zu Martin Oderskys Vortrag vom Mai 2014 über die Ziele der Scala-Sprache hinzufügen. Er identifiziert Sprachen, die einen DI-Container "benötigen", um Abhängigkeiten einzufügen, als schlecht implementiert. Ich stimme dem persönlich zu, aber es ist nur eine Meinung. Es scheint darauf hinzudeuten, dass das Einfügen einer DI-Abhängigkeit in Ihr Scala-Projekt nicht idiomatisch ist, aber auch dies ist eine Meinung. Selbst mit einer Sprache, die darauf ausgelegt ist, Abhängigkeiten nativ einzufügen, wird durch die Verwendung eines Containers praktisch eine gewisse Konsistenz erzielt. Es lohnt sich, beide Gesichtspunkte für Ihre Zwecke zu berücksichtigen.

https://youtu.be/ecekSCX3B4Q?t=1154

Eric Aldinger
quelle
1

Ich würde Ihnen vorschlagen, Distage zu versuchen (Haftungsausschluss: Ich bin der Autor).

Es ermöglicht Ihnen viel mehr als ein typischer DI und hat viele einzigartige Eigenschaften :

  1. distage unterstützt mehrere Konfigurationen (z. B. können Sie Ihre App mit verschiedenen Komponentenimplementierungen ausführen).
  2. Mit distage können Sie Abhängigkeiten zwischen Ihren Tests korrekt teilen und problemlos dieselben Tests für verschiedene Implementierungen Ihrer Komponenten ausführen.
  3. distage unterstützt Rollen, sodass Sie mehrere Dienste innerhalb desselben Prozesses ausführen können, die Abhängigkeiten zwischen ihnen teilen.
  4. Die Verzerrung hängt nicht davon ab scala-reflect (unterstützt jedoch alle erforderlichen Funktionen des Scala-Typensystems, z. B. höherwertige Typen).

Sie können sich auch unseren Vortrag auf der Functional Scala 2019 ansehen , in dem wir einige wichtige Möglichkeiten der Distage besprochen und demonstriert haben.

Pavel S.
quelle
0

Ich habe hier gezeigt, wie ich mit 2.10 einen sehr einfachen funktionalen DI-Container in Scala erstellt habe.

J Pullar
quelle
0

Zusätzlich zur Antwort von Dan Story habe ich über eine DI-Variante gebloggt , die ebenfalls nur Sprachkonstrukte verwendet, aber in Jonas 'Beitrag nicht erwähnt wird: Value Injection on Traits (jetzt Link zu web.archive.org). Dieses Muster funktioniert sehr gut für mich.

Rintcius
quelle
Der Blog-Link ist tot, können Sie mehr ausarbeiten
sas1138