Reader-Monade für Dependency Injection: mehrere Abhängigkeiten, geschachtelte Aufrufe

Wenn Sie gefragt werden über Dependency Injection in Scala eine ganze Menge von Antworten zeigen auf die mit der Reader-Monade, sei es der von Scalaz oder einfach nur Ihre eigenen Rollen. Es gibt eine Reihe von sehr klaren Artikel beschreibt die Grundlagen des Ansatzes (z.B. Runar sprechen, Jason ' s blog), aber ich schaffte es nicht zu finden, ein vollständigeres Beispiel, und ich kann nicht erkennen, die Vorteile der Herangehensweise über beispielsweise einen mehr traditionellen, "manuellen" DI (siehe die Anleitung, die ich schrieb). Die meisten wahrscheinlich ich bin fehlen einige wichtige Punkt, daher die Frage.

Nur als Beispiel, stellen wir uns vor, wir haben diese Klassen:

trait Datastore { def runQuery(query: String): List[String] }
trait EmailServer { def sendEmail(to: String, content: String): Unit }

class FindUsers(datastore: Datastore) {
  def inactive(): Unit = ()
}

class UserReminder(findUser: FindUsers, emailServer: EmailServer) {
  def emailInactive(): Unit = ()
}

class CustomerRelations(userReminder: UserReminder) {
  def retainUsers(): Unit = {}
}

Hier bin ich Modellierung Dinge Verwendung von Klassen und Konstruktor-Parameter, die spielt sehr schön mit den "traditionellen" DI Ansätze, aber das design hat ein paar gute Seiten:

  • jede Funktion hat klar aufgezählt Abhängigkeiten. Wir vermuten, dass die Abhängigkeiten sind wirklich notwendig für die Funktionalität, um richtig zu arbeiten
  • die Abhängigkeiten versteckt über Funktionalitäten, z.B. die UserReminder hat keine Ahnung, dass FindUsers muss ein datastore. Die Funktionalitäten können auch in separaten kompilieren Einheiten
  • wir verwenden nur reines Scala; die Implementierungen nutzen können unveränderliche Klassen höherer Ordnung Funktionen, die "business-Logik" Methoden können Werte zurückgeben, eingehüllt in die IO Monade, wenn wir wollen, erfassen die Auswirkungen etc.

Wie konnte dies sein, modelliert mit der Reader-Monade? Es wäre gut, behalten die Eigenschaften oben, so dass klar ist, welche Art von Abhängigkeiten, die jede Funktion benötigt, und verstecken sich Abhängigkeiten von Funktionalität von einem anderen. Beachten Sie, dass die Verwendung classes ist eher ein detail, vielleicht die "richtige" Lösung mit der Reader-Monade würde etwas anderes verwenden.

Habe ich einen etwas Verwandte Frage die vermuten lässt, entweder:

  • mit einer einzelnen environment-Objekt, mit all den Abhängigkeiten
  • mit lokalen Umgebungen
  • "parfait" Muster
  • Typ-indizierte Karten

Jedoch, abgesehen davon, dass (aber das ist subjektiv) ein wenig zu Komplex für eine so einfache Sache, in allen diesen Lösungen z.B. die retainUsers - Methode (die Anrufe emailInactive fordert inactive zu finden die inaktiven Benutzer) müssten wissen über die Datastore Abhängigkeit, in der Lage sein, um richtig zu nennen, der verschachtelte Funktionen - oder bin ich da falsch?

In welche Aspekte würden mit der Reader-Monade für so ein "business-Anwendung" besser sein als nur mit Konstruktor-Parameter?

  • Die Reader-Monade ist keine silberne Kugel. Ich denke, wenn Sie eine Menge von Ebenen von Abhängigkeiten, Ihr design ist ziemlich gut.
  • Es wird jedoch oft beschrieben als eine alternative zu Dependency Injection; vielleicht sollte es dann beschrieben werden als Ergänzung? Ich bekomme manchmal das Gefühl, dass DI entlassen durch "true funktionale Programmierer", daher wurde ich gefragt, "was statt dessen" 🙂 so oder so, ich denke, mit mehreren Ebenen von Abhängigkeiten, oder besser mehrere externe Dienste, die Sie benötigen, zu sprechen ist, wie jedes medium-large "business-Anwendung" aussieht (nicht der Fall für Bibliotheken sicher)
  • Ich habe immer gedacht, über die Reader-Monade als etwas lokales. Zum Beispiel, wenn Sie haben einige module, die spricht, nur um eine DB, die Sie implementieren können dieses Modul im Reader-Monade Stil. Jedoch, wenn Ihre Anwendung erfordert viele verschiedene Datenquellen, die kombiniert werden sollen, zusammen, ich glaube nicht, dass die Reader-Monade ist gut für die.
  • Ah, das könnte eine gute Richtschnur, wie eine Kombination der beiden Konzepte. Und dann in der Tat scheint es, dass DI-und RM-ergänzen einander. Ich denke, es ist in der Tat Recht Häufig auf Funktionen, die den Betrieb auf einer Abhängigkeit nur, und mit RM hier würde helfen zu klären, die Abhängigkeit/Daten Grenzen.
InformationsquelleAutor adamw | 2015-03-20
Schreibe einen Kommentar