Prezentace se nahrává, počkejte prosím

Prezentace se nahrává, počkejte prosím

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

Podobné prezentace


Prezentace na téma: "Ať se postará někdo jiný, najmeme si programátory z Číny. Čuníkům vstup zakázán."— Transkript prezentace:

1 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 Dependency Injection 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? Dependency Injection ≠ čistý kód DI + ≠ jen k němu vede

4 Dependency Injection Vychází z návrhového vzoru Inversion of Control. 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 public class Computer() { private OsuNetwork network; public Computer() { this.network = new OsuNetwork(); } Připojení k síti je služba, ne součást počítače. Vzniká připojení k síti uvnitř počítače?

6 Použití DI public class Computer() { private OsuNetwork network; // Constructor Injection public Computer(OsuNetwork network) { this.network = network; } // Setter Injection public void setOsuNetwork(OsuNetwork network) { this.network = network; } Kde seženu připojení k síti? „Ať se postará někdo jiný.“ 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í public class Computer() { private Network network; // Constructor Injection public Computer(Network network) { this.network = network; } // Setter Injection public void setNetwork(Network network) { this.network = network; }

8 Dependency Injection 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. new Class() 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í public class Application { public Application() { Article article = new Article(); 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 Article nemá žádné viditelné závislosti, ale opravdu je nemá? Co se stane, když smažeme všechny ostatní třídy? article->save(); // ERROR: Class MysqlStorage not found // ERROR: Class DatabaseConfig not found Kdo by to čekal?

13 Statické peklo v akci public class Article { private String headline; private String text; public void save() { MysqlStorage storage = 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í? public class Article { private String headline; private String text; public void save(MysqlStorage storage) { 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. public MysqlStorage() { DatabaseConfig config = new DatabaseConfig(); this.server = config.getServer(); // some code } Je to v pořádku? Jsou všechny závislosti nahlášeny?

16 Je to v pořádku? public MysqlStorage(DatabaseConfig config) { this.server = config.getServer(); // some code }

17 K zamyšlení … public class Article { private String headline; private String text; public void save(MysqlStorage storage) { 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 public class Article { private String headline; private String text; public void save(Storage storage) { storage.save(this); } Nesmíte zasáhnout do třídy MysqlStorage ani FileStorage

19 Jak zajistit společné rozhraní? public class FileStorage { public void save(Article article) { System.out.println("Article was saved to file"); } public class MysqlStorage { public void executeQuery(String query) { 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ší? public Application() { Article article = new Article(); article.setHeadline("Nadpis článku"); article.setText("Text článku"); DatabaseConfig config = new DatabaseConfig(); MysqlStorage mysqlStorage = new MysqlStorage(config); DatabaseStorage databaseStorage = new DatabaseStorage(mysqlStorage); article.save(databaseStorage); }

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

23 @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 public DatabaseStorage(MysqlStorage storage) { 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!


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

Podobné prezentace


Reklamy Google