Stáhnout prezentaci
Prezentace se nahrává, počkejte prosím
ZveřejnilFrantišek Novák
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!
Podobné prezentace
© 2024 SlidePlayer.cz Inc.
All rights reserved.