Vytváření repository pomocí továrniček
- danielseek
- Člen | 42
Jsem s nette takový pokročilejší začátečník. Jediné co mi na něm vadí je spousta formalismů, které trvá dlouho napsat.
Nevím nakolik to je košér, ale některá repository vyvářím pomocí továrničky a na některá složitější vyvářím složitější třídu dědící od Repository().
class RepositoryFactory {
public function __construct(\Nette\Database\Connection $db) {
$this->db = $db;
}
public function createRepository($table){
return new Repository($this->db, $table);
}
public function createUser(){
$rep = $this->createRepository("user");
$rep->setDemandedKeys("login");
$rep->setAllowedKeys("login, password, role, name, firstname, lastname, email");
return $rep;
}
(
Říkám si ale jestli by nebylo vhodné mít userRepository v di kontejneru jako service, aby se zbytečně nevytvářela nová instance pokaždé, když potřebuji Repository, které jsem už někde použil.
Něco ve smyslu (vím, že je to velká ptákovina):
services:
repositoryFactory: RepositoryFactory
userRepository: @repositoryFactory->createUser();
userService: UserService(@userRepository)
Tímto postupem bych totálně zabil dependency injection. Vytvářet ale třídu kvůli každé funkci uvnitř továrničky mi přijde poněkud zhůvěřilé.
Co si o tomto přístupu myslíte? Jak by bylo nejvhodnější to vyřešit?
Editoval danielseek (16. 11. 2013 10:55)
- Šaman
- Člen | 2668
Nevím, kde jsi přišel na ten způsob s továrnou, ale já používám (a
ve všech příkladech jsem viděl) obyčejnou službu, která se do presenterů
dá injectovat i pomocí property injection extrémně jednoduše pomocí
anotace.
Navíc v configu nemusí být ani pojmenovaná (pracujeme s rozhraním a
závislost UserService na UserRepository pořeší autowiring.)
services:
- App\Model\UserRepository;
- App\Model\UserService;
<?php
use App\Model\UserService; # tohle tu ani není potřeba, ale mám rád vyjmenované všechny závislosti v sekci use
class UserPresenter extends BasePResenter
{
/**
* @var App\Model\UserService <-- tady zatím MUSÍ být plný NS
* @inject
*/
public $users;
public function renderUserList()
{
$this->template->users = $this->users->findAll();
}
}
?>
Editoval Šaman (16. 11. 2013 13:14)
- arron
- Člen | 464
V té továrně musíš nějak skladovat ty instance a vracet je, když už jsou vytvořené. Takže takový malý kontainer. Funguje to skvěle u repository, kde do každé instance předáváš stejné závislosti, ale začne to selhávat tam, kde každá instance potřebuje nějaké jiné závislosti. Tam už pak musíš definovat ty služby explicitně v configu bez ohledu na to, kolik jich je a že jsou si třeba docela podobné.
- danielseek
- Člen | 42
arron napsal(a):
V té továrně musíš nějak skladovat ty instance a vracet je, když už jsou vytvořené.
Jj, to mě napadlo. Domníval jsem se ale, že je to porušením návrhového vzoru factory. Takový věci by měl řešit spíš DI kontejner, je to takový hybrid. Ale z utilitářského hlediska je to asi nejrychlejší řešení.
Factory používám u jednodušších tabulek, kde nejsou žádné složitější závislosti a stačí mi obyčejné CRUD operace…
Editoval danielseek (17. 11. 2013 23:11)
- danielseek
- Člen | 42
Šaman napsal(a):
Ty injecty pomocí anotací jsou zbytečná magie. Domnívám se, že i sám David Grudl říká, že kde je to možné, doporučuje užít injekci v konstruktoru.
Editoval danielseek (17. 11. 2013 23:15)
- Šaman
- Člen | 2668
danielseek napsal(a):
Šaman napsal(a):
Ty injecty pomocí anotací jsou zbytečná magie. Domnívám se, že i sám David Grudl říká, že kde je to možné, doporučuje užít injekci v konstruktoru.
To rozhodně, teď se bavíme JEN o injectování do
presenteru. Tam se dají použít buď magické property injection (viz
příklad), nebo magické method injection (metoda injectFooBar).
Ve vlastním modelu a v naprosté většině komponent se doporučuje
používat constructor injection (a rozhodně ne public property, porušuje to
zapouzdření).
- arron
- Člen | 464
danielseek wrote:
Jj, to mě napadlo. Domníval jsem se ale, že je to porušením návrhového vzoru factory. Takový věci by měl řešit spíš DI kontejner, je to takový hybrid. Ale z utilitářského hlediska je to asi nejrychlejší řešení.
Porušení návrhového vzoru factory to možná je, na druhou stranu, ta factory stále vrací objekty, což je to, co já od ní chci a fakt mě nezajímá, jak to dělá (proto používám create:-)). Krom toho je t ovelmi jednoduché a přímočaré řešení, takže bych se toho tolik nebál :-) Refaktorovat to na dvě třídy jde vždycky, když se ukáže, že je to fail :-)
- bazo
- Člen | 620
danielseek napsal(a):
Jediné co mi na něm vadí je spousta formalismů, které trvá dlouho napsat.
tak to si asi este nevidel symfony2 :) nette absolutne ulahcuje zapisovanie akychkolvek konfiguracii.
ale k problemu, urcite ti doporucujem si vytvorit pre kazdu repository zvlast triedu a zaregistrovat si kazdu zvlast ako service. repository potom mozu obsahovat vsetky mozne query ktore potrebujes
- danielseek
- Člen | 42
bazo napsal(a):
tak to si asi este nevidel symfony2 :)
To je pravda :)
Jde o to, že od devadesáti procent repository nevyžaduji nic náročnějšího než CRUD operace, o zbytek se mi buďto stará servisní třída, nebo to prasím přímo do presenteru, když to není náročná aplikace. Jediné v čem se v praxi liší jsou sloupce v db.
Dělám ještě jednu takovou další prasárnu a to takovou, že z formuláře všechny values předám rovnou repository a ono si samo vyfiltruje, které jsou pro něj (některé samozřejmě předtím upravím). proto tam mám ten výčet sloupců mysql tabulky.
Moje repozitory víceméně vychází z té co je začátečníkům prezentována v Quickstartu
Editoval danielseek (20. 11. 2013 1:37)