Jak správně používat inject?
- czm4rty
- Člen | 29
(Nette 2–1dev)
Ahoj, mám dotaz ohledně správného používání inject. Pokud chci injectovanou službu využít ve všech presenterech, stačí tedy injectnout jednou v BasePresenteru a promennou nastavit na protected? A poté tedy jen ostatní presentery dědit od BasePreseneter.
2. dotaz: Je nutné pro zachování závislostí vyčleňovat formuláře, které používám v AdminModulu a každý vždy jen jednou, do zvláštních tříd a obsáhnout do konfiguračního souboru (config.neon)? Upřednostňuji rychlejší způsob, ale zas nechci mít každý kus kódu jiným způsobem.
3. dotaz: Pro datagrid(nifty) používám továrničky, které injectuji do presenteru. Existuje jiný způsob jak injectnou a vytvořit instanci továrničky než přes interface? Nechce se mi pro každý soubor definovat interface. Pokud jsem nevytvořil interface, tak to hlásilo: „No service of type AdminModule\ArticleGrid found. Make sure the type hint in AdminModule\ArticlePresenter::injectGrids() is written correctly and service of this type is registered.“;
Díky
Editoval czm4rty (12. 1. 2013 10:13)
- Filip Procházka
- Moderator | 4668
czm4rty napsal(a):
Pokud chci injectovanou službu využít ve všech presenterech, …
Ano, ale nedělej to tak u všeho, BasePresenter se ti pak bude nepěkně nafukovat.
2. dotaz: Je nutné pro zachování závislostí vyčleňovat formuláře, které používám v AdminModulu a každý vždy jen jednou, do zvláštních tříd a obsáhnout do konfiguračního souboru (config.neon)? Upřednostňuji rychlejší způsob, ale zas nechci mít každý kus kódu jiným způsobem.
Nutné to není, ale je velice dobrý způsob.
Nechce se mi pro každý soubor definovat interface.
Definovat interface není nic hrozného ;) A tohle by ti mohlo usnadnit používání.
- vvoody
- Člen | 910
Ja mám každý jeden formulár vo vlastnej triede a ku každému mám
továrničku (celú triedu <ComponentName>Factory
s metódou
create) ktorá si drží DI container. K továrničkám nevytváram interface,
registrujem si ich klasicky do configu ako anonymné služby. Presenter ich
obdrží cez inject autowire na základe typehintu.
K tomu ešte má môj BasePresenter upravenú metódu createComponent tak, aby po nenájdení továrničky createComponent<ComponentName> vyhľadala protected property s anotáciou @componentFactory a @componentName s názvom požadovanej komponenty
/**
* @componentFactory
* @componentName newsForm
* @var \App\Factories\NewsFormFactory
*/
protected $newsFormFactory;
Možno by bolo lepšie
@componentFactory(name="newsForm")
aj to len optional, predsa názov môžeme odvodiť z názvu triedy továrničky. :D Nepreháňam to už trochu?
- Filip Procházka
- Moderator | 4668
vvoody napsal(a):
K továrničkám nevytváram interface, registrujem si ich klasicky do configu ako anonymné služby. Presenter ich obdrží cez inject autowire na základe typehintu.
Víš proč je to špatně? Protože v jednom presenteru nemůžeš takovou komponentu použít 2×.
- vvoody
- Člen | 910
V podstate hej, len účel mojich továrničiek je len vytvoriť inštanciu
a predať jej závislosti. Čiastočne automaticky (v BaseFactory)
vyhľadávaním public inject<Cokolvek> metód tak ako v presenteroch.
Logika formulára je až v triede inštancovanej továrničkou, ktorá dedí od
BaseForm a tá od UI\Control. Takže od UI\Form nededím, ten mám ako
subkomponentu.
BaseForm:
protected function createComponentForm()
{
$form = new Nette\Application\UI\Form;
// some magic
return $form;
}
public function getForm()
{
return $this['form'];
}
Zachoval som si defaultné renderovanie lebo ho najčastejšie využívam (s tvojím BootstrapRenderer-om)
public function render()
{
// some magic
$this->getForm()->render();
}
Len ma štve ten dlhý zoznam anonymných služieb s továrničkami a vlastne aj s väčšou časťou repozitárov. Továrničky sú u mňa vždy ako anonymné služby, lebo pri nich nikdy nepotrebujem predať žiaden parameter, kedže aj tak obdržia v konštruktore BaseFactory DI kontainer z ktorého si vytiahnem všetko čo potrebujem a hlavne lazy. Preto ich tam často zabudnem napísať, najradšej by som ich tam vôbec nepísal, ale neviem či je to dobrý nápad to načítavať podla zoznamu súborov v adresári.
- Oli
- Člen | 1215
Zkusím navázat na téma s mou otázkou.
1) Pokud vytvářím komponentu, jaký je rozdíl mezi tím,
vytvořit si ji přes konstruktor a jako službu? Teď to vytvářím přes
konstruktor, ale na spoustě míst na foru vidím, že se to dělá spíš přes
služby.
public function createComponentEditPage()
{
return new Form\PagesForm($this->getAuthorModel(), $this->getPagesModel(), $this->getLang());
}
vs.
public function __construct(EditPageFormFactory $formFactory)
{
$this->formFactory = $formFactory;
}
protected function createComponentEditPage()
{
return $this->formFactory->createForm($this->getAuthorModel(), $this->getPagesModel(), $this->getLang());
}
2) Jaký je rozdíl mezi inject<neco> metodou a konstruktorem? Zase, používám konstruktor a ty inject metody mě přijdou jako spousta metod navíc. Když potřebuju připojit třeba 4 služby do presenteru, tak bych měl vytvořit 4 metody? Jaká je teda výhoda?
public function __construct(\PageModel $pages, \AuthorModel $author)
{
$this->pagesModel = $pages;
$this->authorModel = $author;
}
vs
public function injectPage(\PageModel $pages)
{
$this->pagesModel = $pages;
}
public function injectAuthor(\AuthorModel $author)
{
$this->authorModel = $author;
}
U obou případů mě přijde nepoužití konstruktoru jako víc psaní. Předpokládám, že tam nějaká přidaná hodnota bude, ale jaká? A proč je použití mimo konstruktor „správnější“? Předpokládám, že správnější je, když na to vznikly ty metody…
- Filip Procházka
- Moderator | 4668
Pokud vytvářím komponentu, jaký je rozdíl mezi tím, vytvořit si ji přes konstruktor a jako službu? Teď to vytvářím přes konstruktor, ale na spoustě míst na foru vidím, že se to dělá spíš přes služby.
Oba přístupy jsou naprosto v pořádku. Na vytváření pomocí
new
(například v presenterech) není z hlediska čistoty kódu
vůbec nic špatně. Rozdíl je v tom, že kdy budeš třídu vytvářet pres
DIC (tedy přes továrničku, kterou ti generuje) tak budeš moci velice
jednoduše změnit například konstruktor třídy a přidat ji závislost.
A najednou místo nutnosti hledat všechna použití třídy v aplikaci se
změna projeví úplně všude, protože máš konfiguraci na jednom
místě ;)
Proto existuje DI Container.
Jaký je rozdíl mezi inject<neco> metodou a konstruktorem? Zase, používám konstruktor a ty inject metody mě přijdou jako spousta metod navíc. Když potřebuju připojit třeba 4 služby do presenteru, tak bych měl vytvořit 4 metody? Jaká je teda výhoda?
U obou případů mě přijde nepoužití konstruktoru jako víc psaní. Předpokládám, že tam nějaká přidaná hodnota bude, ale jaká? A proč je použití mimo konstruktor „správnější“? Předpokládám, že správnější je, když na to vznikly ty metody…
Vždy je lepší použít konstruktor! Kromě presenterů.
Příště prosím založ nové téma
- duke
- Člen | 650
@Oli Bod 1 se týká problematiky dědičnosti vs kompozice (viz příklad zde), kdy v případě kompozice je lepší daný objekt (v uvedeném případě formulář) sestavovat ve zvláštní tovární třídě než přímo v nadřazené komponentě (či přímo presenteru). Tato tovární třída pak umožňuje využívat formulář i v jiných komponentách, aniž by docházelo k redundancím v kódu.
Bod 2 pak souvisí s problémem dědičnosti při použití constructor dependency injection, kde při změně v konstruktoru předka je třeba upravovat konstruktory všech jeho potomků. Inject metody jsou workaroundem tohoto problému.
Editoval duke (15. 3. 2013 19:45)