Diskusia – Facade (fasáda)
SpäťUpozorňujeme, že diskusie pod našimi online kurzami sú nemoderované a primárne slúžia na získavanie spätnej väzby pre budúce vylepšenie kurzov. Pre študentov našich rekvalifikačných kurzov ponúkame možnosť priameho kontaktu s lektormi a študijným referentom pre osobné konzultácie a podporu v rámci ich štúdia. Toto je exkluzívna služba, ktorá zaisťuje kvalitnú a cielenú pomoc v prípade akýchkoľvek otázok alebo projektov.
Jak se toto lisi od klasickeho interface? Tady jste vpodstate krasne popsali co dela interface, ale to bylo v kurzu o objektovem programovani. Zadnou pridanou hodnotu tento clanek nema.
Martin Dráb:16.6.2019 1:01
Jak se toto lisi od klasickeho interface? Tady jste vpodstate krasne popsali co dela interface, ale to bylo v kurzu o objektovem programovani. Zadnou pridanou hodnotu tento clanek nema.
Cílem návrhových vzorů (včetně fasády) je nabídnout rozumná řešení pro různé problémy menšího rozsahu. Ač se obvykle ukazují na třídách, rozhraních a jiných konceptech z OOP, nejsou vázány ani programovacím jazykem ani paradigmatu (OOP). Jedná se zkrátka o návody ve stylu "když máš problém X, měl bys jej řešit právě způsobem Y".
Interface je koncept z OOP světa, takže se nachází na nižší úrovni abstrakce. Může být použit k implementaci některých návrhových vzorů, ale nezdá se mi, že by zrovna pokrýval hlavní myšlenku fasády (schovat skupinu tříd a závislosti mezi nimi před okolním světem a ubrat mu tím plno starostí).
Ako je to z rýchlosťou pri tomto návrhovom vzore? PHP modul(parsing engine) načíta celý subsystém , teda všetky triedy , alebo len tie triedy ktorých metódy a atribúty sú volané.
Tohle je na třídě/kódu reprezentující/m fasádu, a tedy na programátorovi. Návrhové vzory nedávají vyčerpávající odpověď na problémy, pro jejichž řešení jsou určeny – obvykle existuje více možností jejich implementace a je třeba se rozhodnout podle konkrétní instance problému. Když se třeba podíváš původní knížky o návrhových vzorech od Gang of Four, zjistíš, že za popisem myšlenky návrhového vzoru vždy následuje celkem dlouhá diskuze o tom, jak jej implementovat.
Patrik Pastor:16.6.2019 9:09
Napsal jsi: "schovat skupinu tříd a závislosti mezi nimi před okolním světem a ubrat mu tím plno starostí" , ale toto presne interface dela. Je to "kostra" pro implementaci dalsich (jez by z tohoto interface dedily) trid, tedy v teto kostre mohou byt ony zavislosti, ktere ubyvaji na starosti. Jako navrhovy vzor to chapu, ale stale se zastavam toho ze implementace fasady je prosty interface (tak jak to programator skutecne zavede, fasadu). Jinak sem nepochopil, napsal jsi ze OOP snizuje abstrakci.. Nezvysuje ji spis nahodou?(kdyz muzes dedit, apod)/.
Martin Dráb:16.6.2019 10:54
OOP snizuje abstrakci.. Nezvysuje ji spis nahodou?
Bylo myšleno ve srovnání s návrhovými vzory, které považuji za obecnější (k jejich použití nepotřebuješ OOP).
ale toto presne interface dela
Ta skupina tříd, kterou fasáda schovává před okolním světem, nemusí dodržovat žádný interface, což je právě pro okolní svět obtížné. Fasáda, dalo by se říci, může pomoci v tom, žepro přístup ke třídám ten interface sjednocuje.
Jako příklad z neOOP světa si třeba můžeme vzít zsíkávání systémových informací (a třeba i informací týkající se aktuálního vytížení systému) na Windows. Můžeš k tomu využít sadu všelijakých funkcí s naprosto nejednotným rozhraním. Pokud chceš jednotné rozhraní pro přístup k těmto informacím, můžeš využít
- pseudoklíč registru HKEY_PERFORMANCE_DATA,
- knihovnu Performance Data Helper,
- pravděpodobně i WMI.
Tyhle tři fasády (druhý je adaptérem nad prvním) ti poskytují jednotné rozhraní k něčemu, co bys mohl nazvat skupinou tříd (ve skutečnosti je vše implenentováno v C, takže se jedná o skupinu různorodých funkcí).
Patrik Pastor:16.6.2019 11:50
pochopil jsem to tak, ze fasada je jeste jakoby "nad interfacem"? Tedy co to je (jak vypada implementace)? Je to classa? Co muze byt na interfacem, ktery je "kostrou" pro dalsi implementace? Kdyz rikas ze fasada SJEDNOCUJE interface (ale nemel by sjednocoval prave interface classy)?
Michal Šmahel:16.6.2019 13:00
Ahoj, koukám, že tomu celkově moc nerozumíš. Pokusím se ti to vysvětlit, abys to v budoucnu špatně neimplementoval. On je totiž rozdíl mezi rozhraním a fasádou poměrně značný.
Rozhraní (interface) - coby prvek OOP
Rozhraní se dá využít na více věcí, ale nyní se zaměřím pouze na
tvorbu abstrakce. V tomto případě (jak již název napovídá) je tvořeno
rozhraní (přes které lze k něčemu přistupovat) pro komunikaci s dalšími
třídami. Rozhraní (OOP) nařizuje třídám, které ho implementují,
povinnost vlastnit určitou veřejnou funkcionalitu. Z toho vyplívá, že se
všechny těmito třídami mohu komunikovat stejně, a dostat stejný formát
(datový typ) výsledku. Každá tato třída si však může data získávat,
jak chce. Také může vracet jiné výsledky. Důležité je, že dodržuje
stejný formát vstupu a výstupu. Rozhraní (OOP) tedy umožňuje k
několika třídám přistupovat stejným způsobem (skrz jejich společné
rozhraní).
Fasáda (Facade)
Fasáda narozdíl od rozhraní (OOP) není prvkem OOP, ani ho nemusí
dodržovat. Může fungovat klidně s funkcemi a jejich soubory. Jedná se
totiž o návrhový vzor (toto již konstatoval Martin Dráb). Já se omezím
pouze na použití v OOP. Narozdíl od rozhraní (OOP) poskytuje rozhraní
(přístup) k několika třídám, které spolu tvoří určitý subsystém
(celek tříd, které mezi sebou spolupracují a poskytují tak nějakou
komplexní funkcionalitu). Fasádu tvoří jedna nebo více tříd, které
poskytují základní funkcionalitu (rozhraní ve smyslu přístupu) totoho
subsystému. To ale však neznamená, že je jedná o jedno nebo více rozhraní
(OOP), ale o třídu, která obsahuje několik metod z různých tříd
subsystému a sjednocuje je v menší jednodušší celek. Tato třída
(fasáda) má závislost na všech třídách subsystému, s nimiž přímo
spolupracuje. V případě použití fasády v kódu dojde k vybrání správné
závislosti a zavolání správné metody, která jí patří. Třídy
subsystému však o fasádě neví, narozdíl od rozhraní (OOP), kdy musí
dodržovat jeho zásady.
Abych to nějak shrnul. Rozhraní (OOP) zastřešuje několik tříd stejně jako fasáda. Rozdíl je však v tom, že fasáda třídám, které zastupuje, nic nenařizuje, ale řídí se jejich strukturou. Rozhraní (OOP) poté nastavuje, jak se budou jemu podřazené třídy chovat, aby s nimi bylo možné vždy pracovat jako s jednou třídou (daným rozhraním ve smyslu OOP).
Snad jsem ti nezamotal hlavu ještě více. Pokud ano, ještě napiš, pokusím se to ukázat na příkladech.
Patrik Pastor:16.6.2019 14:01
precetl jsem si to vickrat a trochu mi to zacalo davat smysl. Akorat bych mel
pouze jednu poznamku k predposlednimu odstavci (kde shrnujes vyznam obou):
Interface narizuje metody, to mas pravdu a fasada dava rozhrani (strukturu) to
bych taky pochopil. Jenom me napada, pokud tedy jde o to, aby to nebylo "povinna
implementace", tak, jak to interface (oop) ma, nestacilo by potom pouzit
Abstraktni tridu? Nemohla by abstraktni trida nahradit fasadu (nebo jeji
implementaci), protoze ta zadnou nucenou implementaci nema(narozdil od
interface).
Martin Petrovaj:16.6.2019 15:06
Ďalší možný spôsob vysvetlenia (dosť zjednodušený a polopatistický):
Interface
Ak objekt implementuje nejaký interface, tak tento interface mu dáva
povinnosť implementovať nejakú funkcionalitu - napr. metódu, ktorá berie
vstup typu X a vracia výstup typu Y. Pri dodržaní interfacom stanovených
pravidiel ho môže implementovať ktokoľvek a akokoľvek. Ak trieda
implementuje interface, v podstate oznamuje zvyšku sveta "nemusíte sa starať
o to, kto presne som, ale viem robiť toto a tamto".
Hlavný význam interfacov je v tom, že zvyšku programu obvykle stačí pracovať s objektom cez jeho rozhranie a nestarať sa o to, aká konkrétna trieda sa za tým rozhraním skrýva. Ak som zapisovač do textového súboru, je mi jedno, či mi príde na vstupe pole čísel alebo objekt Lietadlo, dôležité je, či implementujú nejaké mnou požadované rozhranie napr. s metódou Serialize.
Povedzme, že nejaký účtovný program počíta náklady firmy na jednotlivých zamestnancov. Na to logicky potrebuje poznať aj ich plat. Takže v metóde na to určenej si vyžiada parameter, ktorý implementuje rozhranie Pracovnik (alebo IPracovnik pre C# folks). Rozhranie obsahuje metódu decimal VratPlatZaPoslednyMesiac(). Program na výpočet zamestnancov si ju len zavolá a má informácie, ktoré potrebuje. Pod tým rozhraním pritom mohli byť rôzne konkrétne triedy, ktoré si tú metódu implementovali inak. Napr. objekty triedy BeznyZamestnanec ju implementovali tak, že len vždy vrátili fixnú čiastku; objekty triedy PartTimeZamestnanec vrátili polovicu z fixnej čiastky, objekty triedy Externista mali vnútorné počítadlo hodín a vynásobili ním hourly rate, vynásobí to DPH atď. Ale zmieňovaný program o ničom z toho nemusí vedieť a nestará sa o to. Len komunikuje s rozhraním každého pracovníka a nestará sa o implementáciu pod ním.
Facade
Niekedy je požadovaná funkcionalita zložitá a na jej implementovanie
potrebujeme použiť viac rôznych tried (ak nie sme prasáci a nepíšeme v
roku 2019 40000-riadkové programy celé v static int Main()). Lenže kvôli
prehľadnosti a udržateľnosti kódu nechceme, aby zvyšok programu / softvéru
musel komunikovať so všetkými týmito triedami. Vytvoríme preto jednu,
ktorá poskytuje už výsledné výstupy (tým, že vnútorne komunikuje s tými
ostatnými triedami a prevoláva ich metódy), a táto jedna trieda predstavuje
návrhový vzor fasáda. Jej účelom je poskytnúť abstrakciu nad
zložitejším systémom a zjednodušiť prístup k nemu.
Napr. skôr zmienený účtovný program môže v nejakom dashboarde zobraziť používateľovi celkové náklady firmy (napr. pre jednoduché porovnanie so ziskami, whatever). Na to nestačí spočítať len náklady na mzdy, ale treba zarátať aj nájom priestorov, energie, materiál, infraštruktúru atď. O kalkuláciu mzdových nákladov sa stará trieda SalaryCalculator, metódu pre získanie nákladov na nájom a energie obsahuje OfficeManager, zakúpený materiál a jeho cenu treba vytiahnuť a spočítať z faktúr v databázi cez InvoiceRepository atď. Proste kopa práce cez X subsystémov.
Aby frontend a UI aplikácie nemuselo riešiť to, ako sa celkové náklady vlastne spočítajú a odkiaľ sa získavajú (podľa Single Responsibility Principle a Law of Demeter), tak vytvoríme jednu kompaktnú triedu, ktorá sa o toto všetko postará sama, napr. ExpensesCalculator. Frontend potom len zavolá jednu alebo dve metódy z tejto novej triedy a bude mať všetky informácie, ktoré pre ten dashboard potrebuje. Vďaka ExpensesCalculatoru nie je frontend nijako viazaný na kvadrilión ďalších tried z backendu, nevykonáva sám žiadne kalkulácie a ExpensesCalculator je implementáciou návrhového vzoru fasáda.
Oba tieto pojmy sú si významovo dosť podobné, ide hlavne o to rozlíšiť kontext. Interface sa týka OOP a vzťahuje sa na jednotlivé triedy, Facade je návrhový vzor, ktorý už rieši vzťahy medzi viacerými triedami v širšom kontexte.
Michal Šmahel:17.6.2019 6:23
Díky za doplnění z praktické stránky věci. Já se to snažil držet v teoretické rovině, ale jak je vidět, praktické uplatnění často poví více než teorie.
Zatiaľ nikto nevložil komentár - buď prvý!