GRASP – 6 – Controller a jak GRASP používat

V tomto díle o návrhových principech GRASP (General Responsibility Assignment Software Patterns) se budeme zabývat posledním principem Controller, který nám dává doporučení ohledně spolupráce uživatelského rozhraní a doménových objektů.

Seriál: Principy objektově orientovaného návrhu (12 dílů)

  1. Návrhové principy: SOLID 9.5.2012
  2. Návrhové principy: Deméteřin zákon 18.5.2012
  3. Návrhové principy: DRY 30.5.2012
  4. GRASP – 1 – Úvod a Protected variations 20.6.2012
  5. GRASP – 2 – High cohesion 2.7.2012
  6. GRASP – 3 – Low coupling 16.7.2012
  7. GRASP – 4 – Polymorphism, Pure fabrication a Indirection 30.7.2012
  8. GRASP – 5 – Information expert a Creator 15.8.2012
  9. GRASP – 6 – Controller a jak GRASP používat 17.9.2012
  10. GRASP – 7– Modelové příklady 15.10.2012
  11. Návrhové principy: Tvorba balíčků (1/2) – Soudržnost 14.11.2012
  12. Návrhové principy: Tvorba balíčků (2/2) – Závislosti a provázanost 14.1.2013

Princip Controller je nejkonkrétnějším z principů GRASP, a proto jej probereme až jako poslední.

Controller

Princip Controller nám dává odpověď na otázku, kdo by měl být zodpovědný za zpracování systémových událostí?

Systémová událost (system event) je událost, která je generována nějakým vnějším aktérem. Přichází do našeho systému zvnějšku a nemáme je pod kontrolou. Systémové události tedy jsou vstupem našeho systému z pohledu vnějšího uživatele.

Systémové operace (system operation) jsou pak ty činnosti systému, které probíhají jako reakce na systémové události.

Součástí našeho systému přijímající systémové události je jeho uživatelské rozhraní (ať už jde o grafické rozhraní nebo příkazovou řádku). Tato součást by ale neměla být místem, kde bude probíhat zpracování těchto událostí.

Pokud by zpracování systémových událostí probíhalo v uživatelském rozhraní (kód zajišťující provedení systémové operace by tedy byl umístěn například v metodě reagující na stisk tlačítka) vznikl by problém v závislosti na uživatelském rozhraní. Logika doménové vrstvy by byla roztroušena v jednotlivých částech uživatelského rozhraní. Rozhraní by pak nebylo možné vyměnit za jiné, protože bychom spolu s původním uživatelským rozhraním přišli i o kód vykonávající systémové operace.

Změny uživatelského rozhraní jsou obvykle nejčastější změny v systému a podle principu Protected variations bychom se měli snažit, aby tyto změny neovlivňovaly zbytek systému. Toho dosáhneme tím, že přidáme mezi tyto dvě součásti stabilní rozhraní.

Podle principu controller bychom měli vytvořit speciální třídu nebo třídy, které budou za zpracování systémových událostí zodpovědné. Tyto třídy pak nazýváme právě controller.

Controller není součástí ani uživatelského rozhraní ani doménové vrstvy. Jde o objekty představující Pure fabrication vložené mezi tyto dva subsystémy. V podstatě tvoří rozhraní systému z pohledu uživatelského rozhraní. Jde tedy o aplikaci návrhového vzoru Facade.

Uživatelské rozhraní pak při zachycení systémové události pouze volá metody controlleru, který zařídí jejich zpracování. Obvykle zpracování neprovádí sám, ale deleguje jej na další součásti systému v doménové vrstvě. Controller tedy zpracování pouze deleguje a koordinuje.

Častou chybou právě bývá, že controller provádí zpracování sám místo toho aby jej delegoval. Vzniká pak tzv. Bloated controller, který toho dělá příliš mnoho a ztrácí tak soudržnost.

Díky tomu, že je logika zpracování systémových událostí umístěna ve zvláštní třídě, lze ji snadno znovu-použít a je možné snadno vyměnit uživatelské rozhraní za jiné. Nové rozhraní bude pouze volat stejné metody controlleru jako to původní.

Controller je také vhodným místem, kde udržovat stavové informace o interakcích uživatele se systémem. Pokud například uživatel prochází jednotlivými kroky nějakého průvodce, je controller nejvhodnějším místem, kde ukládat informace o tomto postupu.

Rozlišujeme dva druhy controllerů, podle toho, jaké systémové události zpracovávají:

Facade controller představuje zpracování systémových událostí celého systému. Je vhodné jej použít, pokud systémových událostí není příliš mnoho.

Use-case controller zpracovává události související s konkrétním případem užití. Použijeme jej v případě, kdy by použití Facade controller znamenalo vznik controlleru s příliš nízkou soudržností

Controller tak, jak popisuje Craig Larman v GRASP, je velmi podobný tomu, jak je tento pojem obvykle chápán ve známém architektonickém vzoru MVC.

Tímto jsme probrali poslední GRASP princip. Zbývá už tedy jen vše dát do souvislostí.

Stručné shrnutí principů GRASP

  • Protected variations – Chráněné změny
    • Identifikujte místa pravděpodobných změn a nestability a zodpovědnosti přiřaďte stabilním rozhraním, která kolem nich vytvoříte.
  • High cohesion – Vysoká soudržnost
    • Přiřazujte zodpovědnosti tak, aby zůstala zachována vysoká soudržnost (aby třída nedělala více nesouvisejících věcí).
  • Low coupling – Slabá provázanost
    • Zodpovědnosti přiřazujte tak, aby provázanost zůstala co nejmenší. (Pokud jsou prvky provázané, změny jednoho z nich ovlivňují i druhý.)
  • Pure fabrication – Pouhá konstrukce
    • Pokud by přiřazení zodpovědnosti některé třídě představující objekt z problémové domény narušilo ostatní principy, je vhodné vytvořit novou třídu, která nepředstavuje nic z oblasti domény – třídu vytvořenou pouze jako konstrukční prvek pro zlepšení kvality návrhu.
  • Polymorphism
    • Pokud chování závisí na typu objektu (třídě), přiřaďte zodpovědnost za toto chování pomocí polymorfických metod třídě, na které toto chování závisí.
  • Indirection – Nepřímé vazby
    • Pokud se potřebujete vyhnout přímé vazbě, přiřaďte zodpovědnost prostředníkovi, takže prvky nebudou muset být propojeny přímo.
  • Information expert – Informační expert/Expert
    • Zodpovědnost přidělte prvku, který má informace potřebné pro splnění této zodpovědnosti.
  • Creator – Tvůrce
    • Přiřaďte třídě B zodpovědnost za vytváření instancí třídy A, pokud platí jedno nebo více z následujících:
      • B je agregátor objektů A
      • B obsahuje objekty A
      • B uchovává záznamy o objektech A
      • B úzce spolupracuje s objekty A
      • B má inicializační data pro A (B je informační expert pro inicializaci A)
  • Controller
    • Zodpovědnost za zpracování systémových událostí přiřaďte speciální třídě nebo třídám, které nebudou součástí ani uživatelského rozhraní ani doménové vrstvy, ale budou sloužit jako rozhraní mezi nimi.

Jak používat GRASP?

V posledních pěti dílech seriálu jsme jednotlivé principy GRASP probírali jednotlivě a spíše z teoretického pohledu. Jak ale začít tyto principy skutečně aplikovat při tvorbě kódu?

Nejobecnější rada zní: vzpomeňte si na tyto vzory, kdykoliv zvažujete, jak rozdělit zodpovědnosti. Pokud uvažujete, kam umístit metodu, zda danou funkci přidat nějaké existující třídě nebo zda vytvořit třídu novou a podobně, zkuste si vybavit jednotlivé vzory GRASP a jejich doporučení.

Výsledné rozhodnutí bude vždy na vás, ale GRASP vám může pomoci vyhnout se slepým uličkám, které by mohly přinést problémy v budoucnosti. Slouží tedy jako vodítko, které vám pomůže zúžit možnosti a snadněji je porovnat.

Pokud přiřazujeme konkrétní zodpovědnost, měli bychom postupovat přibližně podle následujícího schématu:

  1. Jedná-li se o systémovou událost, použijeme princip Controller. Rozdělení těchto zodpovědností jednotlivým controllerům by se mělo zvažovat z pohledu jejich High cohesion.
  2. Pro ostatní případy si sestavíme seznam možností, které přicházejí v úvahu. Jedná-li se o vytváření instancí, řídíme se principem Creator. Pokud ne, nastupuje princip Information expert. Pokud se chování může lišit u podtříd, je nutné zvážit ještě princip Polymorphism.
  3. Jednotlivé možnosti pak porovnáme z pohledu principů High cohesion a Low coupling.
  4. Pokud některá řešení vykazují problémy s přímou vazbou, zvážíme jejich odstranění použitím Indirection.
  5. Pokud ani pak z možností není žádná možnost dostatečně kvalitní, zkusíme přidání Pure fabrication.
  6. Princip Protected variations bychom měli mít na mysli během všech rozhodnutí a tvořit systém tak, aby dopady změn byly co nejmenší.

Pokračování příště

Tímto dílem jsme již probrali všechny části GRASP z teoretického pohledu. V příštím posledním díle si ještě ukážeme příklad použití GRASP na modelovém příkladu.

Zdroje a další informace

Martin Jonáš pracuje jako projektový manažer v GrowJOB institute. Vystudoval Informační systémy na Fakultě informačních technologií VUT.

Komentáře: 2

Přehled komentářů

Podbi Pěkný článek.
langpa NoWiki
Zdroj: https://www.zdrojak.cz/?p=3712