+ All Categories
Home > Documents > Dependency injection

Dependency injection

Date post: 14-Feb-2017
Category:
Upload: jiri-matula
View: 12 times
Download: 0 times
Share this document with a friend
21
Dependency injection Jiří Matula Neruším? Ráda bych vám pomohla s Vaší závislostí na ostatních!
Transcript
Page 1: Dependency injection

Dependency injectionJiří Matula

Neruším? Ráda bych vám pomohla s Vaší závislostí na ostatních!

Page 2: Dependency injection

Obsah

1.Co je to Dependency Injection (DI) 2.Motivace proč se zabývat DI3.Typy DI4.Problémy5.DI Container6.Závěr - testík

Page 3: Dependency injection

Dependency injection (DI)

• Návrhový vzor z rodiny IoC (Inversion of Control).• Problém : Skryté závislosti třídy (skryté = těžce

kontrolovatelné).• Řešení: zřejmé předávání závislostí = odebrání třídám

zodpovědnosti za získávání objektů, které potřebují ke své činnosti.• Uplatňuje se princip popisu závislostí pomocí API třídy. • Lze si jej představit pod mottem - “Když něco chceš, tak si o

to řekni!”

Page 4: Dependency injection

Vizualizace závislostí

(Satisfied person)

(Water)

(Alcohol)

(Friends)

(Vegetable)(Meat)

(Cheese)

Page 5: Dependency injection

Proč se obtěžovat s DI?

Zvolnění vazeb mezi objekty,jednodušší testovatelnost,nutí programátora řešit vazby mezi objekty = čistější přehlednější kód,pomáhá dodržovat správný objektový návrh,pravdivé API tříd.

Junior programmer Garry – “Whatever, I love my spaghetti !”

Page 6: Dependency injection

Constructor Injection• Hlášení závislosti přímo v konstruktoru třídy.• Problémy: • Lazy loading (vytváření objektů v momentě, kdy jsou opravdu

potřeba), • Constructor hell (příliš mnoho závislostí v konstruktoru třídy).

public void Company() { this.worker = new Worker(); this.slacker = new Slacker();

}

// constructor injectionpublic void Company(Worker worker, Slacker slacker) {

this.worker = worker; this.slacker = slacker;

}

Page 7: Dependency injection

Setter Injection

• Hlášení závislostí přímo při volání setter funkce. • Lze dobře uplatnit pro inicializaci objektu mimo konstruktor

třídy.@Injectpublic void setHelper(Helper helper) {

this.helper = helper; }

Page 8: Dependency injection

Property injection• Je velmi podobné constructor injection. K hlášení závislostí se

používá anotací přímo u deklarace proměnné. Výhodou je stručnost.• Nutností je DI container, který bude umět s touto anotací

pracovat a nastavit odkazující proměnnou na již inicializovaný objekt.

public class ClientsController {

// Property injection@Inject private final UserDAO

userDAO;

public ClientsController() {

} }

public class ClientsController {

private UserDAO userDAO;

public ClientsController(UserDAO userDao) { this.userDao = userDao;

// constructor injection}

}

Page 9: Dependency injection

Interface Injection• Nehlásíme závislost na konkrétní třídu, hlásíme závislost pouze na interface,• jedná se o velmi silný nástroj – zvyšuje úroveň abstrakce v

kódu.

public void setHelper(Employee helper) { this.helper = helper;

}

public Company(Employee worker, Employee slacker) { this.worker = worker; this.slacker = slacker;

}

interface Employee { public void work();

public void pretendWorking(); }

Page 10: Dependency injection

Spaghetti code, je v souladu s DI?public class Company{

protected Worker worker;

protected Slacker slacker;

public Companz() { this.worker = new Worker();this.slacker = new Slacker();

}

public void open(){this.worker.work(); this.slacker.pretendWorking();

customer = new Customer(); System.out.println(“<h1> Welcome! How can I help you?</h1>”);this.worker.serverCustomer();System.out.println(“<p>” + customer.wish + ”</p>”);

} }

Senior programmer John - “Garry, you are fired!”

Page 11: Dependency injection

Problémy - Constructor hell

public function Controller(IHttpRequest request, IHttpResponse response,User user, UserModel userModel, Language

language, DataSource dataSource, ....) {

// rest of the code}

• Přílišné množství parametrů již přímo v konstruktoru třídy,• odhaluje tak nesprávné rozvržení tříd,• řešit lze za pomocí refaktoringu tříd.

Jesus Christ, so many dependencies!!

Page 12: Dependency injection

Problémy - DI vs. Lazy loading• Lazy loading – návrhový vzor, kdy se vytváření instance

objektu se odkladá do doby než je opravdu potřeba,• z důvodu optimilizace je přínosné tento návrhový vzor

používat,• naopak DI požaduje pro své třídy již vytvořené instance

(závislosti).

Junior Garry – No way, they troll me all the time!

Page 13: Dependency injection

Service Locator – zlé dvojče DI

• Jedná se také o návrhový vzor, nicméně jde proti smyslu DI (antipattern)• Třída se totiž nehlásí k jednotlivým závislostem. Všechny

závislosti získává skrze globální objekt (service locator).• Nicméně lze přejít pak jednoduše k DI.public class ClientsController {

private final UserDAO userDAO;

public ClientsController(ServiceContainer $services) { this.userDao = (UserDao)$services-

>getService("UserDAO"); }

}Hell yeah, your classes are liars again!

Page 14: Dependency injection

DI Container (DIC)

• Příliš mnoho závislostí (závislé třídy) => potřebujeme je spravovat, k těmto účelům slouží právě DI kontejner,• DI kontejner dává již připravené instance tříd vždy jeho

žadateli,• pravidlem je, že o existencí DI kontejneru by mělo vědet

minimální množství kódu,• příklad: Google Guice Cointainer (není jediný).

Page 15: Dependency injection

Pohled na aplikaci jako stavbu tříd

Application

Database

Connection

DaoServices

Resources

DataSource

GUI

Other Clasess…

Page 16: Dependency injection

Na co teda DI container? • Pokud svou aplikaci popíšete jako strom závislostí. Není nic

jednoduššího než si ji nechat sestavit právě DI Containerem.• Ten drží konfiguraci tříd celé aplikace, nahrazuje pokoutné

Environment objekty.

Hey container, gimme the Application!

Yess, sir!

Page 17: Dependency injection

Konfigurace DI containeru• Slouží k správné inicializaci prostředí aplikace, resp. jejich tříd. To,

jakým způsobem se konfigurace provádí, záleží na konkrétní implementaci containeru (anotace, třídní objekt, xml soubor...)import com.google.inject.Binder; import com.google.inject.Module; import com.google.inject.Scopes;

public class DependencyConfig implements Module { @Override public void configure(Binder binder) {

binder.bind(Storage.class).to(DatabaseStorage.class).in(Scopes.SINGLETON);}

//example of Google Guice Container configuration}

Page 18: Dependency injection

DIC a persistence objektů • DI kontejnery nám umožňují řídit životnost objektů =>

obrovský potenciál DI• Problém návrhového vzoru Singleton:• Nikdy nemůžeme dopředu vědět zda třída bude opravdu Singletonem

či nikoli. • Není přímou zodpovědností třídy se starat zda bude jedináčkem či

nikoli.• Za pomocí DI kontejneru se tyto problémy dají vyřešit.

Page 19: Dependency injection

DIC – není Singleton jako Singleton

@Singletonpublic class Company {

protected Worker worker;

protected Slacker slacker;

public Firma() { this.worker = new Worker();this.slacker = new Slacker();

}

}

public class Company { private static Company instance = null;

private Company() {}

public static Company getInstance() { if (instance == null) {

instance = new Singleton(); } return instance;

} }

Page 20: Dependency injection

Kontrolní otázky1.V čem je podstata návrhového vzoru Dependency injection

(DI)?2. Jaké výhody přináší DI?3. Jaké máme typy DI?4. Jaké problémy mohou nastat při aplikování vzoru DI?5.K čemu slouží Dependency Injection Container? 6.Dalo vám to něco?

Page 21: Dependency injection

Questions?


Recommended