1 / 28

Dependency Injection

Dependency Injection. Ať se postará někdo jiný, najmeme si programátory z Číny. Čuníkům vstup zakázán. Co budeme dneska dělat?. Zopakujeme si základní principy DI. Dozvíme se, jak může DI usnadnit programování. Ukážeme si, jak psát přehlednější a čitelnější kód.

orrin
Download Presentation

Dependency Injection

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. DependencyInjection Ať se postará někdo jiný, najmeme si programátory z Číny. Čuníkům vstup zakázán

  2. Co budeme dneska dělat? • Zopakujeme si základní principy DI. • Dozvíme se, jak může DI usnadnit programování. • Ukážeme si, jak psát přehlednější a čitelnější kód. • Předvedeme si, jak se zbavit skrytých závislostí v kódu a statického volání. • Vše si demonstrujeme na příkladu z praxe, který si společně zkritizujeme a opravíme. V čem je to dobré? Minimálně se vyznáte ve vlastním kódu, i když se na něj podíváte třeba za půl roku.

  3. DependencyInjection • Jak poznám, že je třída závislá na jiné třídě? • Co je to skrytá závislost? • V čem nám DI pomáhá? • Jaké znáte typy DI? DependencyInjection ≠ čistý kód DI + ≠ jen k němu vede

  4. DependencyInjection • Vychází z návrhového vzoru InversionofControl. • Odebírá třídám odpovědnost za vytváření objektů, na kterých jsou závislé. • Řízení je delegováno na nadřazený objekt.

  5. Klasický přístup Vzniká připojení k síti uvnitř počítače? publicclassComputer(){ privateOsuNetwork network; publicComputer(){ this.network=newOsuNetwork(); } } Připojení k síti je služba, ne součást počítače.

  6. Použití DI Kde seženu připojení k síti? „Ať se postará někdo jiný.“ publicclassComputer(){ privateOsuNetwork network; // ConstructorInjection publicComputer(OsuNetwork network){ this.network= network; } // SetterInjection publicvoidsetOsuNetwork(OsuNetwork network){ this.network= network; } } Výrobce počítače se nemusí starat o připojení k síti, to řeší uživatel počítače (třídy počítač)

  7. Použití DI a rozhraní publicclassComputer(){ private Network network; // ConstructorInjection publicComputer(Network network){ this.network= network; } // SetterInjection publicvoidsetNetwork(Network network){ this.network= network; } }

  8. DependencyInjection • Závislost na jiných objektech jasně deklarujeme v konstruktoru třídy nebo v jejich metodách. • Použití operátoru new uvnitř třídy je skrytá závislost. • Použití statického volání uvnitř třídy je skrytá závislost. • Výjimku tvoří primitivní typy a nativní třídy jazyka. newClass() Class.getInstance()

  9. Homer a závislosti

  10. Příklad na cvičení • Příklad ke cvičení je ke stažení na následující adrese • http://tinyurl.com/mo4omp3

  11. Příklad na cvičení publicclassApplication{ publicApplication(){ Articlearticle=newArticle(); article.setHeadline("Nadpis článku"); article.setText("Text článku"); article.save(); } } • Kam se článek uloží? Do souboru nebo do databáze? • Jakou databázi používám? • Jaké jsou parametry připojení?

  12. Já myslel/a, že to víš … • Když něco potřebuju, tak si o to řeknu! • Třída Articlenemá žádné viditelné závislosti, ale opravdu je nemá? • Co se stane, když smažeme všechny ostatní třídy? article->save(); // ERROR: ClassMysqlStorage not found // ERROR: ClassDatabaseConfig not found Kdo by to čekal?

  13. Statické peklo v akci publicclassArticle{ privateStringheadline; privateString text; publicvoidsave(){ MysqlStoragestorage=MysqlStorage.getConnection(); storage.executeQuery("INSERT INTO articles…“); } } Jaký návrhový vzor jsme použili? Nápověda: Class.getInstance(); Jedná se o porušení DI? Jaké je řešení?

  14. Řešení? publicclassArticle{ privateStringheadline; privateString text; publicvoidsave(MysqlStoragestorage){ storage.executeQuery("INSERT INTO articles…“); } } Bude to fungovat? Co ještě musíme upravit?

  15. Zase o krok dále… Třída MysqlStorage je singleton. Převedeme ji na klasickou třídu s veřejným konstruktorem. publicMysqlStorage(){ DatabaseConfigconfig=newDatabaseConfig(); this.server=config.getServer(); // somecode } Je to v pořádku? Jsou všechny závislosti nahlášeny?

  16. Je to v pořádku? publicMysqlStorage(DatabaseConfigconfig){ this.server=config.getServer(); // somecode }

  17. K zamyšlení … publicclassArticle{ privateStringheadline; privateString text; publicvoidsave(MysqlStoragestorage){ storage.executeQuery("INSERT INTO articles…“); } } Je správné, aby třída Article věděla o struktuře DB? Co když budeme chtít uložit článek do souboru?

  18. Upravte kód publicclassArticle{ privateStringheadline; privateString text; publicvoidsave(Storagestorage){ storage.save(this); } } Nesmíte zasáhnout do třídy MysqlStorage ani FileStorage

  19. Jak zajistit společné rozhraní? publicclassFileStorage{ publicvoidsave(Articlearticle){ System.out.println("Article was saved to file"); } } publicclassMysqlStorage{ publicvoidexecuteQuery(Stringquery){ System.out.println("Record was saved to database ("+ query +")"); } }

  20. Použijeme adapter • Návrhový vzor adaptér použijeme, pokud potřebujeme, aby třída měla jiné rozhraní než to, které právě má. • Adaptér slouží jako prostředník mezi prostředím, které požaduje nějaké rozhraní, a třídou, jejíž rozhraní neodpovídá požadovanému. Umožňuje tedy spolupráci třídám, které by spolu jinak nespolupracovaly.

  21. Je to lepší? publicApplication(){ Articlearticle=newArticle(); article.setHeadline("Nadpis článku"); article.setText("Text článku"); DatabaseConfigconfig=newDatabaseConfig(); MysqlStoragemysqlStorage=newMysqlStorage(config); DatabaseStoragedatabaseStorage=newDatabaseStorage(mysqlStorage); article.save(databaseStorage); }

  22. Sestavení závislostí pomocí containeru Application DI container

  23. DI container • @Inject– ohlášení DI containeru, že má obsloužit třídu. • @Singleton– označení třídy jako singleton • @ImplementedBy(ServiceImplementation.class)

  24. S použitím DI containeru @Inject public Application(Article article, Storage storage){ article.setHeadline("Nadpis článku"); article.setText("Text článku"); article.save(storage); }

  25. Úkol • Vytvořte jinou třídu, která má závislost na rozhraní Storage. • Přihlašte se k závislosti a sledujte v konzoli, kolikrát se vytvoří připojení k DB. • Jak použít singleton spolu s DI?

  26. A jak to dopadlo se singletonem? @Inject @Singleton publicDatabaseStorage(MysqlStoragestorage){ this.storage=storage; } Hurá, singleton se vrátil! Win: databázové připojení se vytvoří jen jednou. Win: žádné skryté závislosti.

  27. Rekapitulace: proč zvolit DI? • Jasné vazby mezi objekty, • pravdivý a předvídatelnější kód, • přehlednější, lépe upravitelný, • žádné statické volání, • znovu použitelnost kódu, • mnohem lepší testovatelnost.

  28. Zvládli jsme to!

More Related