Dependency Injection ve 2.1: Anotace @inject
- David Grudl
- Nette Core | 8227
(Navazuji na starší příspěvek)
Navrhuji používat v dokumentaci jako preferovaný typ injektování
konstruktor a právě anotace @inject
. Naopak bych zcela
(v příkladech, dokumentaci) opustil metody inject–
. Ty vznikly
čistě jako workaround kvůli problémům s konstruktorem a dědičností a
jejich použití jinde je nešťastné. A protože ho vídám čím dál tím
častěji, aby by bylo vhodné mu udělat přítrž.
Anotaci @inject
vnímám čistě jako syntax sugar pro rutinní
předání závislostí přes konstruktor. Z toho důvodu by měla existovat
i varianta pro volitelný inject, zapsaná buď jako @inject?
nebo
možná ještě lépe jako @var My\Class|NULL @inject
.
- Filip Procházka
- Moderator | 4668
Já jsem pro a klidně bych z fleku začal přepisovat dokumentaci, ale zase mi někteří budou vyčítat, že chci psát dokumentaci pro nestabilní verzi, nebo dokonce, že bychom měli dokumentaci psát pro 2.0.0 a né pro 2.0.10 (nebo .11 ?).
- Majkl578
- Moderator | 1364
Já jsem pro a klidně bych z fleku začal přepisovat dokumentaci
Domnívám se, že ve chvíli, kdy 2.1 vstoupí do beta fáze, dokumentace by se měla rozdělit na verzi pro 2.0 a 2.1.
Stále považuji za zásadní problém chybějící podporu use statementů. Mám zkusit připravit pull?
- hrach
- Člen | 1838
Domnívám se, že ve chvíli, kdy 2.1 vstoupí do beta fáze, dokumentace by se měla rozdělit na verzi pro 2.0 a 2.1.
Idealne aby to bylo na gitu, to se pak bude delat jedna basen :)
Stále považuji za zásadní problém chybějící podporu use statementů. Mám zkusit připravit pull?
Urcite prosim :)
- Filip Procházka
- Moderator | 4668
@inject do private/protected nemá nic společného s DI.
Editoval Filip Procházka (23. 4. 2013 22:32)
- duke
- Člen | 650
Svůj příspěvek jsem nepsal proto, abych obhajoval @inject do private/protected metod, ale proto, abych se dozvědel, čím chce David nahradit aktuální použití inject* metod (kterým chce učinit přítrž) v případech, kdy tyto metody nastavují private či protected proměnné objektu. Navíc jeho poznámka, že @inject vnímá jako syntaktický cukr pro rutinní předání závislostí přes konstruktor naznačuje možnost, že hodlá podporovat i tuto formu injektáže (neboť konstruktor ji také umožňuje).
Odpověď „@inject do private/protected nemá nic společného s DI“ je pro mě v tomto ohledu naprosto k ničemu. Navíc s ní ani nelze souhlasit, protože to injektáž závislostí (tedy DI) nepochybně je (neříkám že se neprohřešuje proti určitým principům – jde o jakousi násilnou formu DI – a nijak ji nepropaguji), ale je tím, čím je.
- Majkl578
- Moderator | 1364
Podle mě by možnost injectu do protected/private měla být přinejmenším konfigurovatelná. V Javě je to běžná, osvědčená, přímočará a jednoduchá praktika, jak do objektu dostat závislost.
@inject do private/protected nemá nic společného s DI.
Nesmysl. DI je to stejně tak jako injectování do public property. Jediný rozdíl je pouze ten, že třída explicitně neuvádí závislosti skrze své API. Dokážu si představit, že v aplikaci bez testů a/nebo v presenterech to kdekdo rád oželí.
Náhražkou inject metod je právě použití public property.
Ne plnohodnotná, jelikož s sebou přináší problémy.
Vyžadování public property je sice hezké z akademického hlediska, ale
zároveň to (bez nativních property accessorů) porušuje zapouzdřenost
objektu, poněvadž kdokoliv může kdykoliv za běhu (třeba i omylem) změnit
hodnotu a objekt se o tom vůbec nedozví.
- Šaman
- Člen | 2661
Vyžadování public property není hezké z akademického
hlediska, právě kvůli porušení zapouzdření.
Přes setter (injector) jsem schopen nějaké základní kontroly, při
přímém zápisu do property nikoliv.
Anebo jsem špatně pohopil stávající @inject
. Znamená to,
že $database
, $cache
apod budou veřejné
property?
- Tharos
- Člen | 1030
Já teda vnímám pečlivé zapouzdření jako jeden z klíčových aspektů robustního návrhu. Takže pokud by @inject vyžadovalo zrušit zapouzdření, sám bych to rozhodně nepoužíval (nabourání zapouzdření by pro mě byla až příliš vysoká oběť). Pokud by šlo injektovat do privátních proměnných, v např. presenterech bych to určitě používal (za cenu drobného hacku, oželení akademické čistoty a de facto vytvoření závislosti na konkrétním DI kontejneru si významně ušetřím psaní).
Kdykoliv přijdu ke kódu, kde je nějaká veřejná třídní proměnná, tak chvíli tápu, co si o ní mám myslet a co si s ní mohu dovolit dělat. U nějakých „value objektů“ se zorientuji rychle, ale pokud je to instance nějaké „normální třídy“, jak s tou proměnnou mohu pracovat? Mohu tam jen tak něco frknout? Rozbije se to nebo ne? Co když tam frknu null? Nebo úplně jiný typ, než to předpokládá? Poznám vůbec, že jsem to rozbil? Jsou na to testy?
Editoval Tharos (24. 4. 2013 10:41)
- enumag
- Člen | 2118
Osobně mám s tím public taky problém, inject* metody a zapouzdření je mi příjemnější. Problém je, že kdyby se mělo injectovat do private, muselo by se vyřešit injectování do stejně pojmenovaných private vlastností na různých úrovních dědičnosti. Inject* metody tohle řeší bez problému.
Kvůli tomu zapoudření ty inject metody v presenterech vnímám jako better-practice než anotace. Podobně constructor injection mimo presentery.
Editoval enumag (24. 4. 2013 10:47)
- Filip Procházka
- Moderator | 4668
Majkl578 napsal(a):
@inject do private/protected nemá nic společného s DI.
Nesmysl. DI je to stejně tak jako injectování do public property. Jediný rozdíl je pouze ten, že třída explicitně neuvádí závislosti skrze své API. Dokážu si představit, že v aplikaci bez testů a/nebo v presenterech to kdekdo rád oželí.
Pokud máš aplikaci bez testů, nevidím problém v psaní pár public properties. To je jako umývat okna hořícího domu – nic to nezmění :)
Náhražkou inject metod je právě použití public property.
Ne plnohodnotná, jelikož s sebou přináší problémy.
Vyžadování public property je sice hezké z akademického hlediska, ale zároveň to (bez nativních property accessorů) porušuje zapouzdřenost objektu, poněvadž kdokoliv může kdykoliv za běhu (třeba i omylem) změnit hodnotu a objekt se o tom vůbec nedozví.
Krásně si tady protiřečíš.
- „třída explicitně neuvádí závislosti“
- „zároveň to porušuje zapouzdřenost objektu“
Injektování do private/protected zapouzdřenost neporušuje?
Stále mi přijde jako nejlepší řešení tohle.
Editoval Filip Procházka (24. 4. 2013 15:18)
- Majkl578
- Moderator | 1364
Filip Procházka napsal(a):
Pokud máš aplikaci bez testů, nevidím problém v psaní pár public properties. To je jako umývat okna hořícího domu – nic to nezmění :)
Návrh a implementace aplikace může být kvalitní bez ohledu na to, jestli tam je milion nebo nula testů.
Krásně si tady protiřečíš.
- „třída explicitně neuvádí závislosti“
- „zároveň to porušuje zapouzdřenost objektu“
Injektování do private/protected zapouzdřenost neporušuje?
Jelikož se to děje jen a pouze ve chvíli inicializace objektu (tj. bezprostředně po volání konstruktoru), považuji to spíše za součást inicializace objektu, jelikož objekt ještě nemá konzistentní vnitřní stav.
Editoval Majkl578 (24. 4. 2013 15:35)
- David Grudl
- Nette Core | 8227
Ad public property a porušení zapouzdření: nechci se opakovat, vše najdete tady.
Jen doplním: anotace @inject
zapouzdřuje proměnnou na úrovni
dohody. Stejně jako anotace @return
nekontroluje, zda
funkce vrací to, co má, ale věříme tomu. Nebo stejně, jako nekontrolujeme,
zda někdo nepřepisuje závislosti uložené v privátních proměnných tím,
že by nad objektem znovu zavolal metodu __construct
a předal
jiné závislosti. Nebo dokonce potlačil E_RECOVERABLE_ERROR a protlačil
objekty jiného typu, než je typehint.
Samozřejmě pokud vám úroveň dohody nevyhovuje, použijte privátní proměnné a konstruktor injection.
- duke
- Člen | 650
Z wikipedie cituji, ohledně zapouzdření: „Zapouzdření v objektech znamená, že k obsahu objektu se nedostane nikdo jiný, než sám vlastník.“
Řešení pomocí public properties znamená, že se k dané proměnné (která je součástí obsahu objektu) dostane kdokoli. Trik s unset popsaný v odkazovaném článku řeší zapouzdření pouze částečně, tj. řeší problém možného následného přepsání zvenčí (zajišťuje, že proměnná je write-once), ale už neřeší problém přístupu pro čtení (znemožňuje její privátnost, tj. kompletní zapouzdření).
Inject* metody kompletní zapouzdření umožňují, byť je s nimi trochu více psaní…
- Majkl578
- Moderator | 1364
Jen doplním: anotace @inject zapouzdřuje proměnnou na úrovni dohody.
Následujíc tuto myšlenku, můžeme všude a) zrušit gettery a settery ve prospěch public properties, b) zrušit non-public viditelnost metod a označit obojí za dohodu. To je ale přeci nesmysl.
Stejně jako anotace @return nekontroluje, zda funkce vrací to, co má, ale věříme tomu.
To je míchání jablek s hruškama. Nijak to totiž neovlivňuje stav/zapouzdřenost daného objektu – je jen a pouze na volajícím, zda tomu věří nebo ne, a ať se rozhodne jakkoliv, stav volaného objektu se tím nijak nezmění.
Nebo dokonce potlačil E_RECOVERABLE_ERROR a protlačil objekty jiného typu, než je typehint.
Tohle je za normálních okolností neproveditelné a pokud by to někdo
dělal, je to jako střílet se do vlastní paty. (http://3v4l.org/UgLuj)
Rozhodně je to, narozdíl např. od neúmyslného zápisu do public property,
naprosto okrajový případ (ještě krajnější, než aby si dotyčný upravil
hodnotu property reflexí).
Samozřejmě pokud vám úroveň dohody nevyhovuje, použijte privátní proměnné a konstruktor injection.
Stále zapomínáš, že ještě lze použít, po vzoru Javy, kde se to velice osvědčilo, private property a property injection. To je totiž z hlediska napsání nejúspornější a zároveň z hlediska zapouzdřenosti nejbezpečnější cesta, která řeší všechny tebou zmínené problémy (a to i včetně hypotetického – ač nereálného – potlačení E_RECOVERABLE_ERROR nebo opakované volání konstruktoru). ;)
@duke: Vesměs souhlasím.
Editoval Majkl578 (25. 4. 2013 2:32)
- Filip Procházka
- Moderator | 4668
Majkl578 napsal(a):
Stále zapomínáš, že ještě lze použít, po vzoru Javy, kde se to velice osvědčilo, private property a property injection.
Stále zapomínáš, že to s Dependency Injection nemá nic společného.
- David Grudl
- Nette Core | 8227
Majkl578 napsal(a):
Stále zapomínáš, že ještě lze použít, po vzoru Javy, kde se to velice osvědčilo, private property a property injection.
Nezapomínám! Jen mi stále PHP při zápisu do private property vyhazuje fatal error. Nejspíš používáš nějakou jinou verzi.
- Elijen
- Člen | 171
Injectnout private property by šli přes Reflection, ale to je asi ta vůbec nejhorší možnost předání závislostí.
Osobně se mi nejvíc líbí constructor injection v kombinaci se setter
injection. U presenteru bych klidně přežil public property s anotací
@inject
, ale u služeb mi to přijde snad ještě horší než
metody inject*
.
Jaká je vůbec motivace pro zrušení inject*
metod kromě
méně psaní v presenterech? Aneb v čem je @inject
lepší? To
tu podle mě vůbec nezaznělo.
Editoval Elijen (25. 4. 2013 11:17)
- Filip Procházka
- Moderator | 4668
Imho tenhle
příspěvek je stále aktuální. @inject
je línější
varianta pro inject* metody. Méně psaní.
Každopádně, tahle debata je jenom o presenterech, v modelech a komponentách téměř nemá smysl používat cokoliv jiného, než constructor injection.
- pekelnik
- Člen | 462
…PHP při zápisu do private property vyhazuje fatal error. Nejspíš používáš nějakou jinou verzi.
Jo! Jmenuje se Nette ;)
Co použít setter-injection made by Nette\Object:
use Nette\Object;
use Nette\Caching\Cache;
class Foo extends Object
{
/**
* @inject
* @var Cache
*/
private $bar;
public function getBar()
{
return $this->bar;
}
public function setBar($bar)
{
$this->bar = $bar;
}
}
Povšimněte si stupidních getterů a setterů…
Editoval pekelnik (25. 4. 2013 15:52)
- Honza Marek
- Člen | 1664
Když už, tak:
use Nette\Object;
use Nette\Caching\Cache;
class Foo extends Object
{
private $bar;
/** @inject */
public function setBar(Cache $bar)
{
$this->bar = $bar;
}
}
- Šaman
- Člen | 2661
Inject metody jsou podle mě dobré řešení, ale vůbec by se nemusely
psát, stačilo by je definovat v anotacích a volat je magicky. Sice na
úrovni kodu jsou to skryté závislosti, ale každé IDE které umí napovídat
si s tím poradí a pokud programátor dostane třídu, má hned nahoře seznam
těchto magicky nastavovaných závislostí. Pro mě by to byl přijatelný
kompromis.
Rovnou by to mohlo zvládat i obyčejné settery a gettery.
<?php
/**
* @method void injectFoo($foo)
* @method void setBar($bar)
* @method int getBar()
*/
class FooBar extends Object
{
/** @var classFoo */
protected $foo; // proměnná bude přístupná pro zápis a navíc bude automaticky injectovaná
protected $bar; // proměnná bude přístupná ke čtení i zápisu magicky
protected $i; // proměnná není přístupná
}
?>
// edit: doplněna třída, která se má injectovat, díky
@castamir
On by ten typ proměnné měl být uveden všude, ale u injectované
být musí
// edit2: Viditelnost změněná na protected kvůli nastavování v předkovi. Stejně private nepoužívám kvůli prolémům s děděním, jen jsem použil příklad výše..
Editoval Šaman (27. 4. 2013 10:21)
- stekycz
- Člen | 152
Osobně nevidím důvod, proč by pro Presenter
y měl být
problém porušení zapouzdřenosti použitím public property. Zapouzdřenost
potřebuji pouze pokud pracuji s danou třídou jako uživatel
zvenčí. Pokud ji zvenčí používá jen framework, může mi
být v podstatě jedno, jestli používá public property injection nebo
použije nějaký setter či konstruktor. Já tyhle metody stejně volat nebudu.
Navíc jsem líný a chci psát co nejúsporněji to lze, tedy anotace je asi to
nejjednodušší.
Nevím jak kdo tady, ale já zatím neměl potřebu vytvářet si instanci
Presenter
u sám a přistupovat k ní zvenku. Jedinou výjimkou
může být přímé testování Presenter
ů, o čemž psal
nedávno David. V tomhle případě se ale přikláním k
@Hosiplanovi, který upřednostňuje testování
Presenter
ů rovnou s celou aplikací pomocí Selenia (jak psal na Twitteru).
Ještě jednou ale upozorňuji, že předpokládám tuto funkcionalitu
jen a pouze v Presenter
ech.
Nette\Application\UI\PresenterComponent
ani
Nette\Application\UI\Control
tuto funkcionalitu umožňovat IMHO
nemá. Proč? Protože k instancím těchto tříd chci
přistupovat zvenčí a vytvářím si jejich
instance sám.
Osobně teď používám na jednom projektu od
@Hosiplana úpravený BasePresenter
pro
použití anotace @autowire
a jsem spokojen. Jediný rozdíl
(alespoň co vím) oproti @inject
je v tom, že Filip používá
protected property a injektace se provádí až při přístupu k dané
službě/property.
- Majkl578
- Moderator | 1364
David Grudl napsal(a):
Nezapomínám! Jen mi stále PHP při zápisu do private property vyhazuje fatal error. Nejspíš používáš nějakou jinou verzi.
Stačí přeci použít reflexi. ;)
stekycz napsal(a):
Osobně nevidím důvod, proč by pro
Presenter
y měl být problém porušení zapouzdřenosti použitím public property.
Tahle diskuze nicméně není pouze o Presenterech, ale o DI obecně.
Zapouzdřenost potřebuji pouze pokud pracuji s danou třídou jako uživatel zvenčí. Pokud ji zvenčí používá jen framework …
Opravdu? A co například použití presenteru v komponentě nebo šabloně?
Navíc jsem líný a chci psát co nejúsporněji to lze, tedy anotace je asi to nejjednodušší.
Souhlasím. Jako nejúspornější a zároveň nejbezpečnější vychází property injection do non-public property, že? :)
Osobně teď používám na jednom projektu od @Hosiplana úpravený
BasePresenter
pro použití anotace@autowire
a jsem spokojen. Jediný rozdíl (alespoň co vím) oproti@inject
je v tom, že Filip používá protected property a injektace se provádí až při přístupu k dané službě/property.
Je krásné vidět, že vlastně i HosipLan, který private property injection odmítá, sám používá její obdobu, dokonce zkombinovanou se zatracovaným service locatorem. ;)
@Šaman: Nemyslím si, že podobné přespříliš magické věci by měly být přímo součástí Nette a už vůbec ne Objectu. Shodou náhod je to jedno z řešení, které jsem i já už dříve navrhoval.
Nicméně jak property injection, tak setter injection (pro nutné závislosti) mají jeden zásadní drawback – inicializují objekt dvoukrokově, tudíž v určitou chvíli se nachází v ne-plně-inicializovaném stavu. Co když například někdo bude vyžadovat závislosti pouze skrze properties a v konstruktoru bude mít nějakou (ač jakkoliv jednoduchou) logiku? S constructor injection by tenhle problém řešit nemusel. Kdysi jsme se o tom s někým bavili a jako možné řešení padlo vytvoření instance bez volání konstruktoru, nasetování vlastností / zavolání inject setterů a až následně zavolání konstruktoru.
Editoval Majkl578 (26. 4. 2013 0:47)
- mishak
- Člen | 94
@Šaman: private atribut potomka nemůžeš nastavit
v jeho rodiči, leda přístupem přes ReflectionProperty.
Pak další problém s použitím soukromých atributů je při vícenásobném
dědění, inject pak musíš provést pro celou linii předků.
Public a unset je celkem elegantní řešení a nejspíš jediné možné
ostatní zavádějí daleko více okrajových případů, které je třeba
řešit.
+1 Pokud bude podporovat i NULL
parametry.
Zároveň neúmyslně řeší používání stejných služeb rodičem a
potomkem. – Nevím jestli je to správné, nebo jestli je to třeba
vůbec řešit.
Pokud jde o inject i mimo presentery z továrny, zde stále zbývá
vyřešit kontrolu konzistence objektu, jinak každý test bude muset obsahovat
Object::assertRequiredInjections($object). :( Chápu, že to je problém, ale
bez vyřešení kontroly samotné řešení, může napáchat více škody
(vyžaduje důslednost a nepadá okamžitě při chybném stavu).
Část řešení by byla zavést počítadlo nastavených povinných atributů,
ale nepřišel sem na vhodný okamžik života objektu, kdy ho zkontrolovat.
Šlo by to řešit přes generovanou proxy pro každou třídu, ale to mi
přijde jako kanón na vrabce a navíc je třeba ručně balit nebo továrny
(opět ta důslednost).
Editoval mishak (26. 4. 2013 0:57)
- David Grudl
- Nette Core | 8227
Asi by bylo záhodno povolit metody inject jen pro presentery.
Šaman napsal(a):
Rovnou by to mohlo zvládat i obyčejné settery a gettery.
Tohle už v Nette existuje, viz třeba tady https://github.com/…r/Method.php (ale pravda, je to ve formě konceptu, commitnu full verzi).
- enumag
- Člen | 2118
Asi by bylo záhodno povolit metody inject jen pro presentery.
Tak to ani náhodou. Dejme tomu pokud by totéž platilo i pro @inject anotace. Nutnost public properties mimo presentery bych opravdu nerozdejchal. Je pravda že mimo presentery inject* ani @inject nepoužívám, ale v případě mnoha závislostí a dědičnosti (ala Presenter) se to může hodit. Samozřejmě v takovém případě je vhodný refactoring, rozbití na více tříd a snížení počtu závislostí, ale to už je druhá věc a nemyslím, že by Nette mimo presentery mělo umět pouze constructor injection.
- pekelnik
- Člen | 462
@David pravděpodobně jsi myslel DIC – DI umí všechny myslitelné injektáže už z podstaty věci ;)
Rád bych aby se tady diskutující přestali ohánět presentery. O presentery v této diskusi nejde ani okrajově.
Bavíme se tady o tom, zda jako doporučovaný způsob injektáže mimo constructor injection začít tlačit anotace @inject na úkor inject metod a dále o způsobu zápisu volitelné injektáže. To je taková injektáž, která se neprovede pokud závislost (služba) s daným rozhraním (daného typu) neexistuje.
/**
* @inject @var Cache|NULL
*/
public $cache;
Nic lepšího tady nepadlo. Otazník za anotací nepovažuji za šťastný a vzhledem k tomu, že inject metody byly od začátku pouze workaround zdá se mi toto jako čistější náhrada.
K tématu zapouzdření bych dodal pouze to, že nemůžete chtít všechno najednou. Kromě Majkla. Ten to chce a nestydí se za to!
Mimochodem naprosto perfektní injektáže do private/protected proměnných dosáhnete mnohými dokola omílanou a jinými naprosto opomíjenou constructor injection.
Pro zájemce odkazy na další zajímavé čtení o DI:
- http://misko.hevery.com/…r-injection/
- http://tech.finn.no/…onstructors/
- http://martinfowler.com/…jection.html#…
Ještě bych rád dodal, že z důvodu zpětné kompatibility by
inject metody měly zůstat funkční minimálně někam do verze
2.2. Nevadilo by mi kdyby Nette ve verzi
2.1 generovalo upozornění úrovně
E_USER_DEPRECATED
pro tyto metody. Rozumný člověk nenechá
takovouhle chybu na produkci shodit aplikaci a zároveň se o tom
s jistotou dozví.
A ještě jedna věc:
Pokud už Nette podporuje constructor injection a
property injection nebylo by od věci rozšířit/pozměnit
stávající chování inject metod a začít podporovat čistou
setter injection označenou anotací (ať jsme konzistentní) a
nikoliv slovem „inject“ v názvu. Direktiva setup
nechť
zůstane na „ostatní“ věci kromě injektáží.
Editoval pekelnik (29. 4. 2013 11:12)
- Šaman
- Člen | 2661
@pekelnik: Ve většině s tebou souhlasím, jen ten argument nemůžete mít všechno je irelevantní. Proč se teda pachtit s nějakou DI a teoretickou čistotou, když ji nemůžeme mít komplet?
<?php
private $cache;
public function __construct()
{
$this->cache = ServiceManager::getCache();
}
?>
Nemůžu mít všechno, ale mám to krásně zapouzdřeno.
Jinak injector chápu jako setter, ale přeci jen v tom cítím rozdíl. Injector voláš typicky jen jednou ihned po vytvoření nové instance, settit můžeš častěji. Nevadí mi, že jsou tyto metody odlišeny i názvem. Ale je fakt, že většinou je lepší používat konstruktor.
- pekelnik
- Člen | 462
@Šaman doufám že „zapouzdřeno“ nepopisuje tu ukázku kódu… a tím „nemůžete mít všechno“ mám na mysli, že nemůžeš mít zároveň toto:
- property injection
- private property
Alespoň ne v čistém PHP. Dá se použít chování Nette\Object. Dá se upravit chování Nette\Object ale závislost je to nemilá… Tak asi tak…
To co nazýváš „injektorem“ je ve skutečnosti opravdu pouze setter.
Další možností je write-once property v
Nette\Object
. Důležité je se při těchto úvahách soustředit
na to, že „kontejnér neexistuje“ ;)
Editoval pekelnik (26. 4. 2013 17:37)
- Šaman
- Člen | 2661
Aha, já to myslel tak, že nemůžeme mít DI i zapouzdřeno :) Ten kód byl trošku provokačka, přiznávám.
Jinak o kontejneru nebyla řeč, jen mi nevadí mít některé settery pojmenované inject a vím, že pokud tuto metodu používám jindy než při vytváření nové instance, asi dělám něco špatně. Dále setter chápu trochu jako nepovinný parametr, zatímco injector bych nastavit měl (teda nenastavuji injector, ale jeho pomocí nastavuji property, ale snad si rozumíme).
- Šaman
- Člen | 2661
pekelnik napsal(a):
@Šaman mě na inject metodách sere toto:
- je to metoda navíc… setter většinou existuje také…
- přijde mi divné v kódu – když vytvářím objekt ručně – volat inject… když chci set…
ale to je OT…
Právě že inject* metody používám tam, kde klasický setter nechci.
Nemám setDatabase()
, setCache()
,
setFooRepository()
, setAnotherService()
. Tam, kde má
smysl nastavovat parametry za běhu, tam patří setter, pokud je to něco co se
má injectovat jen při vytváření objektu, tak inject. Zatím jsem nenarazil
na sporné případy. Tam bych pk asi volil setter a injectování řešil
ručně v configu.
David Grudl napsal(a):
Tohle už v Nette existuje, viz třeba tady https://github.com/…r/Method.php
Je někde příklad použití? Na čisté třídě dědící NObject mi to nefunguje.
Editoval Šaman (27. 4. 2013 11:59)
- Filip Procházka
- Moderator | 4668
@Šaman musíš takto
vylepšit __call()
Majkl578 napsal(a):
Tahle diskuze nicméně není pouze o Presenterech, ale o DI obecně.
Pleteš se, tahle diskuze je jen a pouze o presenterech, protože všude
jinde se standardně používá constructor injection a na tom se shodneme
i s lidmi co používají v presenteru $this->context
.
Editoval Filip Procházka (28. 4. 2013 17:16)
- Majkl578
- Moderator | 1364
Filip Procházka napsal(a):
Pleteš se, tahle diskuze je jen a pouze o presenterech, protože všude jinde se standardně používá constructor injection a na tom se shodneme i s lidmi co používají v presenteru
$this->context
.
Nikoliv, dostuduj si prosím realitu. Inject metody se volají na všech službách, ne pouze presenteru. Rovněž „problém“ přeplněného konstruktoru nesouvisí pouze s presenterem, ale s jakoukoliv službou. Zda je to standardní pouze pro presentery nebo ne je irelevantní otázka, vzhledem k tomu, že se to týká služeb globálně.