Inject repozitáře do vlastní služby
- holantomas
- Člen | 55
Zdravím,
mám problém s injectem repozitáře (Také služba samozřejmě). Chtěl jsem
to udělat hlavně přes anotaci @inject
, ale když to nešlo, tak
jsem zkusil funkci inject*()
a nakonec samozřejmě
__constructor()
.
config.neon:
services:
# Main services
- App\Model\UserManager
- App\Forms\SignFormFactory
- App\ObjectService
router: App\RouterFactory::createRouter
# Repositories
- App\Model\StudentsRepository
BasePresenter.php:
ObjectService.php
Jde o to že se mi neprovede inject do vlastnosti
ObjectService::$StudentsRepository
třída
\App\Model\StudentsRepository
, ale když zkopíruju tuto vlastnost
a dam ji do BasePresenteru, tak tam se injectne. Nevíte někdo jak toho
docílit?
- holantomas
- Člen | 55
Ohledně jména konstruktoru, to byl jen překlep.
Tak se mi nakonec povedlo přes něj sprovoznit. Není nějak lepší řešení? Protože těch repozitářu budu mět více jak 20 a to mi nepřijde už od pohledu jako skvělé řešení.
Jinak děkuji za odpověď
-- EDIT: Teď mě napadlo, nebylo by lepší předat kontext a z něj si repozitáře vytáhnout?
Editoval holantomas (5. 8. 2015 22:22)
- Oli
- Člen | 1215
To by lepší nebylo. Věř mi, vím o čem mluvím :-)
Když už to děláš jako třídu, tak nikdy nevíš, kde ji budeš ještě
potřebovat a pokud by jsi tam dal context
, tak pak bude peklo to
přenést do jiného projektu a zjišťovat kdeže ti to padá, jaká tabulka
chybí atd. Ty závislosti prostě budou schovaný.
Nejlepší řešení IMHO je přes constructor dát věci bez kterých ta třída nemůže fungovat (ideálně jako interface). Protože když to přeneseš do jiného projektu, tak stejně tam ty třídy musí být. To co není bezpodmínečně nutný pro funkci třídy předávat setrem.
Edit: ještě si můžeš vypomoct nějakou třídou, která bude agregovat některé repositáře. Např. jeden agregátor může obsahovat articleRepo, commentRepo, userRepo, … Ale to se mě taky neosvědčilo.
Editoval Oli (5. 8. 2015 22:51)
- holantomas
- Člen | 55
Jde o to, že služba ObjectService
bude obsahovat skoro dvacet
repositářů. A předávát všechny přes konstruktor mi nepříjde pěkné.
Tak sem chtěl vědět zda by to nešlo „čistěji“
- Šaman
- Člen | 2667
Čistěji určitě ne. Konstruktor je pro povinné závislosti nejčistější možnost. Ta anotace u presenterů je naopak velmi špinavý způsob, ale presentery mají několik specifických vlastností kvůli kterým se to toleruje (např. konstruktor předka vs. konstruktor potomka). Pokud bys to ale chtěl čistě, tak bys u abstraktních presenterů použil anotaci (nebo metodu inject*) a u konkrétních presenterů taky konstruktor.
Jestli máš dvacet závislostí, tak to vypadá spíš na třídu, která
dělá příliš mnoho věcí a tedy porušuje
princip jediné odpovědnosti
. Pokud ne a třída je nějaká velmi
speciální, pak by bylo možné předat celý kontext, ale musíš vědět, že
je to hack a proč to děláš. Rozhodně to není čisté řešení.
- holantomas
- Člen | 55
Jde o to, že ObjectService
je v podstatě taková
továrníčka na objekty fasády, jestli to mohu tak nazvat. A každy objekt
fasady ma i svůj repozitář. Nechtěl jsem tvořit továrnu pro každý
objekt. Jednak kvůli pohdlí a navíc jsem se právě chtěl vyhnout
obrovskému injectovaní služeb továren do BasePresenteru. Takhle do něj
injectu jen ObjectService přes kterou vytvářím dané objekty. Chápu to, že
přes konstruktor je to asi nejčistější řešení, ale nepřijde mi
elegantní mít v konstruktoru 20 parametrů(možná i více), lepší mi
přijde vložit pouze context
(Tato část nikdy neopustí tento
projekt, takže by neměl vznikat problém s neznámimy závislostmi). Na
druhou stranu naprosto chápu co se mi snažíte říct, ale ani jedno řešení
zde řečeno mi prostě nepřijde elegantní a zároveň čisté. Předání
contextu přes konstruktor mi přijde asi jako nejlepší kompromis.
Samozřejmě se mohu plést a pokud by někdo vymyslel lepší řešení jsem mu
nakloněn.
- Pavel Kravčík
- Člen | 1202
A constructor je lepší řešení, než toto? Osobně se mi tohle líbí víc. Můžu si to dělit do bloků po pěti a podobně:
- Oli
- Člen | 1215
No context bude v tvém případě pravděpodobně 2. nejlepší řešení. Možná nejlepší, neznám tvůj projekt. I když mám co se týče objektů relativně velký projekt, tak jsem se nikdy nedostal nad cca 6 – 8 objektů v base presenteru. Tím myslím @inject objektů. Hodně věcí řeším komponentama, který si většinou řeší i vlastní vykreslení. Tím schováš velkou část toho co chceš injectovat pod tu komponentu. Může to potom vypadat třeba takhle.
Něco takovýho by ti nepomohlo?
- Oli
- Člen | 1215
V tomhle případě je to asi nastejno. Nevýhodu vidím v tom, že ti tímhle strašně nabobtná kod. Přidáním další závislosti bys měl o 1 řádek víc v constructoru, ale o 4 řádky víc u tvého řešení. A to ještě nemluvím o tom, že budou mezi metodama prázdný rádky. Takže dejme tomu 5× víc kodu (místa) pro předání závislostí.
Settery vnímám zejména jako nepovinné závislosti. Nemusí to být pravidlem, ale snažím se dodržovat to, že na čem je třída existenčně závislá, tak je v konstruktoru. Pak to je hned zřejmé, když přijdu ke kodu po roce, tak vím, co je nutné a co je nepovinné
Editoval Oli (8. 8. 2015 15:04)
- Pavel Kravčík
- Člen | 1202
Ano, z toho důvodu se mi tohle líbí víc. Že můžu strukturovat jednotlivé injecty. Místo deseti v řadě si je můžu do dát do injectCore, injectSmlouvaRepositories a podobně.
Spíš mi zajímalo, jestli je to dobře nebo špatně. Dovnitř Nette tolik nevidím a tohle se mi líbí víc, než constructor.
- holantomas
- Člen | 55
Principiálně to výjde na stejno. A v podstatě se snažím o to o čem mluví Oli. Nechci mít nabobtnalí kód. A osobně nevidím nic lepšího na tom že budu mít třeba 4 settery po pěti repozitářích nebo jeden konstruktor o dvaceti repozitářích. I tak děkuji za snahu :)
- holantomas
- Člen | 55
No o tom jsem mluvil v předchozím komentu. Dalo by se to vyřešit tím že by každý objekt měl továrničku (Služba nebo komponenta principálně to ale vyjde na stejno). Jenže to si myslím že by také nebylo úplně pohodlné. Mým cílem je je něco takového.
Zaroven jde o to abych nemel vsechny repositare definovane v tom konstruktoru (Byt by bylo pekne aby to melo pevne dane zavislosti), ale radsi se dam smere pekneho kodu, kdyz vim ze tahle cast do jineho projektu nepoputuje.
- Filip Procházka
- Moderator | 4668
Nevyjde to nastejno. Je špatně že máš desítky závislostí v třídách a je špatně že je předáváš přes settery, když jsou povinné. https://filip-prochazka.com/…cky-posobota
- holantomas
- Člen | 55
Fajn přednáška. V podstatě co bylo řečeno jsem pochopil,
pročítáním dokumentace a tady fóra.
O co šlo zde jsem vyřešil. Pak už jsem jen řešil to co je nejlepší
kombinace čístěho a elegantního/pěkného řešení. Když to vyreším
čistě, bude to otřesně výpadat a přehlednost strašná.
Děkuji moc za odpověď a přednášku :)
- holantomas
- Člen | 55
Chápu co tím chceš říct. Mě jde jednodušše o to vyhnout se 20-ti parametrům v konstruktoru a pod tím dalším 20-ti zapsáním do property
- Filip Procházka
- Moderator | 4668
A proč nemůžeš tu třídu rozdělit na více tříd? Každá pak bude mít méně závislostí.