Dagger 2 - Ny generation av dependency injection?

Permalänk

Dagger 2 - Ny generation av dependency injection?

Jag har aldrig hållit på med dependency injection, men jag är tvungen att lära mig. Men det verkar vara så komplext och så mycket information så jag vet inte vart jag ska börja.

Jag tänkte därför börja med ett tillämpat ett exempel. Sedan kan vi diskutera kring hur bra Dagger 2 är, om det är en framtid eller inte.
Jag vet om vad dependency injection är för något och det verkar riktigt superbra och jag har användning för det.

Jag vet om att Spring Ramverk använder .xml filer där man deklarerar alla klasser i ett enda. Detta kallas för Spring IOC. Nu finns det något som heter Dagger 2, version 2 med andra ord. Där man inte behöver någon .xml fil. Alltså en ny generation av dependency injection.

Vi säger att jag har en kod som ser ut så här:

public class MinKlass { private A a private B b; private C c; private D d; private E e; private F f; private String h; public MinKlass(){ a = new A(h); h = a.geth(); b = new B(); c = new C(a); d = new D(c); f = E.build(); // Statisk } }

Hur skulle ni göra här om ni använde Dagger 2?
Meningen är att jag ska kunna använda MinKlass i andra DI-klasser så jag har åtkomst till varenda metod.

Tolka MinKlass som en klass i ett paket till en Javaapplikation.

Permalänk
Medlem
Skrivet av heretic16:

Jag har aldrig hållit på med dependency injection, men jag är tvungen att lära mig. Men det verkar vara så komplext och så mycket information så jag vet inte vart jag ska börja.

Dependency injection innebär att du skickar beroenden istället för att låta "den beroende delen" (en klasskonstruktor, en metod; i andra språk funktioner, moduler etc.) skapa eller leta efter dem själv.

Utan dependency injection:

class Korv { private final Bröd bröd; public Korv() { this.bröd = new Knäckebröd(); // beroendet skapas inuti klassen } } // användning: Korv korv = new Korv();

Med dependency injection:

class Korv { private final Bröd bröd; public Korv(Bröd bröd) { this.bröd = bröd; // beroendet skickas in av den som instansierar klassen } } // användning: Bröd bröd = new GlutenfrittBröd(); // GlutenfrittBröd ärver Bröd; Korv korv = new Korv(bröd);

Det är det hela.

Det Dagger, Guice, Spring DI etc. tillför är olika metodiker för att automagiskt göra precis det jag skrev i exemplet ovan.

Visa signatur

Kom-pa-TI-bilitet

Permalänk
Skrivet av Teknocide:

Dependency injection innebär att du skickar beroenden istället för att låta "den beroende delen" (en klasskonstruktor, en metod; i andra språk funktioner, moduler etc.) skapa eller leta efter dem själv.

Utan dependency injection:

class Korv { private final Bröd bröd; public Korv() { this.bröd = new Knäckebröd(); // beroendet skapas inuti klassen } } // användning: Korv korv = new Korv();

Med dependency injection:

class Korv { private final Bröd bröd; public Korv(Bröd bröd) { this.bröd = bröd; // beroendet skickas in av den som instansierar klassen } } // användning: Bröd bröd = new GlutenfrittBröd(); // GlutenfrittBröd ärver Bröd; Korv korv = new Korv(bröd);

Det är det hela.

Det Dagger, Guice, Spring DI etc. tillför är olika metodiker för att automagiskt göra precis det jag skrev i exemplet ovan.

Fick inte Dagger 2 att fungera på Linux tydligen. Jag tror att jag råkande köra den statiska klassen ApplicationContext i main.

Hur som helst så testade jag Spring IOC för första gången nu och livet blev så mycket bättre. Dock så använder man allt i en .xml fil.

Jag vet inte riktigt vad som är bäst. Dagger 2 eller Spring som använder .xml filer?
Jag såg en film som använde Dagger 2, men det var rätt komplext tyckte jag. @inject, @component @autowiring osv tycker jag är rätt komplicerat. Har inte förstått syftet med detta förutom att det handlar om att göra livet enklare.

Spring IOC så kunde man deklarera ALLT i en enda .xml fil.

Spring finns ju till GluonHQ's JavaFX också.
https://gluonhq.com/labs/ignite/

Permalänk
Medlem

@heretic16: Jag föreslår att du struntar i IoC-ramverk tills du förstår hur konstruktorargument fungerar, och vad deras poäng är. Om du skriver kod som i ditt första exempel så gör du bara livet svårt för dig själv.

Visa signatur

Kom-pa-TI-bilitet

Permalänk
Skrivet av Teknocide:

@heretic16: Jag föreslår att du struntar i IoC-ramverk tills du förstår hur konstruktorargument fungerar, och vad deras poäng är. Om du skriver kod som i ditt första exempel så gör du bara livet svårt för dig själv.

Jag har skrivit kod varje dag i ca 4 år nu
Dock inte i Java.

Permalänk
Medlem

Grejen med DI är att det är löst couplat. Vilket gör att det är enkelt att mocka och skriva test för sin kod.
Om du gör som i exemplet överst så kan du inte skapa en instance av klassen utan att få med allt i constructorn, vilket är svår testat och kan skapa problem.

Oftast kodar du mot ett interface och säger att hej, jag behöver detta interface här, men hur det är implementerat bryr jag mig inte om. Sen under runtime så skickas klassen som du implementerat för interfacet in via constructorn.

Detta gör att om du skriver test kan du mocka en klass mot interfacet och skicka in. T.ex. en in memory databas istället för din riktiga databas.

Skickades från m.sweclockers.com

Permalänk
Skrivet av zaibuf:

Grejen med DI är att det är löst couplat. Vilket gör att det är enkelt att mocka och skriva test för sin kod.
Om du gör som i exemplet överst så kan du inte skapa en instance av klassen utan att få med allt i constructorn, vilket är svår testat och kan skapa problem.

Oftast kodar du mot ett interface och säger att hej, jag behöver detta interface här, men hur det är implementerat bryr jag mig inte om. Sen under runtime så skickas klassen som du implementerat för interfacet in via constructorn.

Detta gör att om du skriver test kan du mocka en klass mot interfacet och skicka in. T.ex. en in memory databas istället för din riktiga databas.

Skickades från m.sweclockers.com

I detta fall så behöver jag behov av lite "lättåtkommpliga fält"

Jag har ett litet problem med DI nu.

Jag har skapat en bean för en klass CSV. Nu vill jag anropa klassens method load med ett argument String filePath och methoden retunerar objektet file med klassen File.

Hur gör jag här?

fileHandler = new FileHandler(); // Denna har jag i min .xml fil File file = fileHandler.loadFile(NetworkTablePath); // Men hur gör jag här? cSVHandler = new CSVHandler(file, Delimieter); // Här vet jag redan att man ska anropa constructor-arg i Spring .xml filen.

Måste jag ha File file som fält och sedan en metod som heter "setFile(String filePath)" ?

Finns det annat sätt som jag kan göra?

Permalänk
Medlem

Lite otydlig kod, jag förstår inte riktigt problemet, annat än att på 3 rader kod gör du 2 st "new" vilket luktar som problem redan där. Nu är ju metoden (och klassen) hårt kopplad mot "FileHandler" och "CSVHandler", vilket kanske inte är ett problem men men.

Du får nog förklara lite tydligare

Permalänk
Medlem
Skrivet av Ernesto:

Lite otydlig kod, jag förstår inte riktigt problemet, annat än att på 3 rader kod gör du 2 st "new" vilket luktar som problem redan där. Nu är ju metoden (och klassen) hårt kopplad mot "FileHandler" och "CSVHandler", vilket kanske inte är ett problem men men.

Du får nog förklara lite tydligare

Varför skulle new på två av tre rader vara ett problem?

Visa signatur

Kom-pa-TI-bilitet

Permalänk
Medlem

@Teknocide: Hela tråden handlar ju om dependency injection, så jag fann det ironiskt att den enda koden som postats var på 3 rader och två av dom använde inte dependency injection.

Permalänk
Medlem
Skrivet av Ernesto:

@Teknocide: Hela tråden handlar ju om dependency injection, så jag fann det ironiskt att den enda koden som postats var på 3 rader och två av dom använde inte dependency injection.

Det finns ingen motsättning i att använda dependency injection och att skapa instanser av klasser (med new). Som jag skrev ovan, dependency injection är att skicka med beroenden till beroende funktioner/metoder/konstruktorer. Enklare uttryckt: Att skicka argument till funktioner. Vare sig mer eller mindre

Även om man använder ramverk för att få tillgång till finesser likt Guices Injector#getInstance är det inte det enda man kan göra. Exempelvis används fortfarande new String för att skapa en sträng av en byte-array, new ArrayList<String>(), etc. i oändlighet. Att inte blir bunden till en specifik variant är liksom hela poängen.

Visa signatur

Kom-pa-TI-bilitet