Service vrstva Doctrine (1/2)

Patrik Votoček

Když jsem se rozhodoval , jakou knihovnu použít pro modelovou část “Nelly”((tehdy ještě nerozdělené na Framework a CMS)), byla jednou z možností Doctrine ORM. Původně jsem si Doctrine ORM 2 nevybral a “začal jsem”((jako jeden z mnoha)) psát vlastní ORM, postavené nad dibi. Po přibližně měsíční práci jsem dospěl do fáze, kdy to nějak fungovalo, ale čekala mě hromada další práce, jako například optimalizace, celkový refaktoring a hlavně otestování v praxi. V tu dobu jsem své předchozí stanovisko nepoužít Doctrine znovu přehodnotil a začal ji používat.

V těchto dnech tomu bude rok, co používám Doctrine. Je to výborná knihovna a autoři na ní odvedli velký kus práce. Nicméně ani Doctrine není kompletní řešení modelové vrstvy aplikace. Schází jí totiž poslední “kostička do skládačky”. Tou je *modelová Service vrstva*.

Tato chybějící vrstva je věc, která mi nedává spát. Snažím se totiž nalézt “ideální”((čti takové, se kterým bych byl spokojen)) řešení a zkouším co se dá. Dospěl jsem do bodu, kdy prostě nevím, jak dál a tak se chci poradit. V zásadě jsem dospěl ke dvěma možným řešením a nemůžu se rozhodnout, které z nich zvolit, či zda jít úplně jinou cestou.

Doctrine mimo jiné implementuje repository pattern. To znamená, že načítání dat z databáze má následující životní cyklus. 1. repository chci článek číslo 1 2. repository se ptá IM((Identity Map)) máš u sebe článek číslo 1? 3. UoW odpovídá nemám 4. repository se říká mapperu načti mi článek číslo 1 5. maper načte článek číslo 1 a pošle ho repository 6. repository ho uloží do IM 7. repository mi vrátí článek číslo 1 Jinak řečeno máme specializovanou část modelu, která se stará o načítání dat a optimalizaci načítání. Tj pokud budu chtít podruhé načíst článek číslo 1. repository ho už načte z paměti a nebude sahat do databáze.

S tím souvisí implementace service vrstvy. Dá se totiž podle toho oddělit její odpovědnost.

U obou následujících variant je instance service třídy to jediné, k čemu má Presenter / Controler přístup.

Varianta “manželé”

V této variantě se service třída stará pouze o úpravy entit. O načítání se stará repository. Ukázka řekne více než 1000 slov:

$service = new ArticleService(...);
$article = $service->repository->find(1);
$articles = $service->repository->findByCategory($category);
$articles = $service->repository->findAll($offset, $limit, $order);

Načítání dat se provádí vždy pomocí přímého dotazu do repository. Service třída se tedy dělí o práci s repository.

Shrnutí

Varianta “superman”

V této variantě se naopak service třída stará o vše a Presenter / Controler by se k repository vůbec neměl dostat. Opět ukázka:

$service = new ArticleService(...);
$article = $service->find(1);
$articles = $service->findByCategory($category);
$articles = $service->findAll($offset, $limit, $order);

Service třída vládne všemu a stává se z ní tak “super” třída.

Shrnutí

Kterou z těchto variant zvolit a proč?

« »