[JAVA] Fassen Sie Ruby und Dependency Injection zusammen

Bei der Entwicklung mit Laravel bin ich auf einen DI-Container gestoßen, und ich dachte, ich hätte DI während der Entwicklung mit Rails nie verwendet. Daher werde ich zusammenfassen, warum DI in Ruby (Rails) nicht häufig vorkommt.

TL;DR ――Da Ruby die Abhängigkeit von der Instanz dynamisch ändern kann, ist DI grundsätzlich nicht erforderlich. ―― Lesen Sie fast den folgenden Artikel. Wenn Sie also Englisch sprechen können, lesen Sie bitte diesen Artikel. LEGOs, Play-Doh, and Programming

DI DI (Dependency Injection) ist eine Technologie, die die Abhängigkeit zwischen Instanzen beseitigt, die als Abhängigkeitsinjektion bezeichnet werden. Es ist praktisch, Scheinobjekte während des Tests zu ersetzen, da Sie abhängige Instanzen von außen einfügen können. Das DI-Framework ist eine Technik, die lose Kopplung und hohe Aggregation realisiert, indem der DI-Container Instanzen erstellen und injizieren lässt. Es gibt einige DI-Frameworks, die häufig für native Apps verwendet werden (ich kenne iOS nicht). Nehmen wir also Java als Beispiel.

Java

public class A {
    //Die B-Instanz wird in A generiert und der Verbindungsgrad ist hoch
    public Client client = new B();
}

interface Client {
    String outputSelf();
}

public class B implements Client {
    @Override 
    public String outputSelf() {
        return "B";
    }
}

public class C implements Client {
    @Override 
    public String outputSelf() {
        return "C";
    }
}

DI löst dieses Problem, und es gibt verschiedene Typen. Am Beispiel der Konstruktorinjektion sieht es jedoch wie folgt aus. A verliert die Substanz von B und wird lose gekoppelt.

public class A {
    public Client client;
    public void A(Client client) {
        this.client = client;
    }
}

In diesem Fall ist der Aufrufer jedoch dafür verantwortlich, die Instanz zu erstellen, die in A eingefügt werden soll, und die Verantwortlichkeiten werden verteilt. Wenn Sie also den DI-Container (z. B. Dagger2) verwenden, sieht dies folgendermaßen aus. Der DI-Container ist für das Injizieren der Abhängigkeit von der Aktivität verantwortlich, einschließlich A.

public class A {
    public Client client;
    @Inject
    public void A(Client client) {
        this.client = client;
    }
}

Ruby Wie bisher erläutert, erleichtert DI das Ersetzen von Objekten, indem es von der Schnittstelle anstelle der konkreten Klasse (Instanz) abhängig gemacht wird. Was bedeutet es dann als Schlussfolgerung am Anfang, dass ein Mechanismus wie ein DI-Container in Ruby nicht erforderlich ist? Selbst wenn Sie eine Injektion durchführen möchten, können Sie mit der ursprünglichen Sprachfunktion von Ruby eine ausreichend lockere Kopplung und eine hohe Aggregation erreichen. Es scheint, dass die Verwendung eines DI-Containers nur die Komplexität erhöhen kann.

Wie im Java-Beispiel sieht es wie folgt aus, wenn eine Konstruktorinjektion durchgeführt wird.

class A 
  def initialize(options={})
    @client_impl = options[:client] || B
  end
  def new_client
    @client_impl.new
  end
end
class B end
class C end

Reflection Eine Technologie, die die Struktur des Programms selbst während der Ausführung des Programms liest oder neu schreibt. In diesem Artikel handelt es sich um eine Methode zum dynamischen Umschreiben der Entität des Clients, der Mitglied der Klasse A ist, von außen.

Ruby

Der ursprüngliche Artikel besagt, dass Ruby die folgende Sprache ist.

The very Ruby language itself is designed for this: closures, super-simple introspection of objects, runtime modification of existing objects, and the use of modules for extending classes and objects all tend to result in an environment that is simple, malleable, and extensible.

Wenn Sie also dynamisch wie Ruby schreiben,

class A
  def new_client
    client.new
  end
  def client
    B
  end
end

class B end
class C end

Sogar die erstellte Instanz kann leicht geändert werden.

#Die Instanzmethode kann dynamisch geändert werden
def A.new.client
  C
end

Java Reflection wird auch in Java unterstützt, sodass Sie die Mitglieder der Instanz wie folgt ersetzen können, aber ...

class D {
    public static void main(String args[]){
        try {
            A a_instance = new A();
            Class a = a_instance.getClass();
            Field field = a.getDeclaredField("client");
            System.out.println("before reflection:" + ((Client) field.get(a_instance)).outputSelf());
            field.setAccessible(true);
            field.set(a_instance, new C());
            System.out.println("after reflection:" + ((Client) field.get(a_instance)).outputSelf());

        } catch (Exception e) {}
    }
}

Im Vergleich zur Injektion ist es überwiegend schwer zu verstehen und die Komplexität nimmt zu.

Fazit

Ruby ist dynamischer als Sprachen wie Java, und selbst wenn es einmal erstellt wurde, ist es einfach, Abhängigkeiten zu ändern und zu ändern. Daher scheint die Einführung eines Mechanismus wie eines DI-Containers, der in einer statischen Sprache erforderlich war, die Komplexität nur zu erhöhen.

Recommended Posts

Fassen Sie Ruby und Dependency Injection zusammen
Rubin und Edelstein
[Ruby] Klassen und Instanzen
Symbole und zerstörerischer Rubin
[Ruby] Big Decimal und DECIMAL
Ruby-Klassen und -Instanzen
Ruby-Vererbung und -Delegierung
Dolch2 - Android-Abhängigkeitsinjektion
DI: Was ist Abhängigkeitsinjektion?
Ruby-Syntaxfehler und Gegenmaßnahmen
Über Ruby-Hashes und -Symbole
Dolch2 - Android-Abhängigkeitsinjektion
DI: Was ist Abhängigkeitsinjektion?
Fassen Sie Ruby und Dependency Injection zusammen
Ruby C Erweiterung und flüchtig
Über Ruby und Objektmodell
[Ruby] Singuläre Methoden und singuläre Klassen
Informationen zu Ruby-Klassen und -Instanzen
Ruby-Methoden und -Klassen (grundlegend)
Erstellen von Ruby-Klassen und -Instanzen
[Ruby] Unterschied zwischen get und post
[Ruby] Unterschied zwischen is_a? Und instance_of?
Ruby-Standardeingabe und verschiedene Methoden
Über Ruby einfache Anführungszeichen und doppelte Anführungszeichen
[Ruby-Grundlagen] Split-Methode und to_s-Methode
Informationen zum Ruby-Produktoperator (&) und zum Summenoperator (|)
Schreiben Sie Schlüssel und Werte in Ruby
Upgrade der Ruby- und Rails-Version des Projekts
Über objektorientierte Vererbung und über Ertrag Ruby