Mam napisanu class, ktorej davam v konstruktore pomerne vela (5+) objektov, na ktorych zavisi jej funkcionalita.
S pribudajucou funkcionalitou classa rastie a potreboval by som ju zacat vetvit na child classy, ktore by ju extendli s tym, ze zakladna funkcionalita ostane v nej a vetvy porozdelujem do child-ov.
Pre inicializaciu base classy pouzivam factory pattern, je pouzivana na viacerych miestach aplikacie, aby som v pripade rozsirenia dependencies nemusel aktualizovat viac skriptov.
Moja otazka je, ako inicializovat child classy, kedze pokazde potrebujem mat riadne inicializovanu base class, no nechcem kopirovat cely dependency list do kazdej child class a nasledne do parent::__construct()
Existuje nejake elegentane riesenie pre takuto situaciu?
PHP - Parent>Child + Dependency Injection
Re: PHP - Parent>Child + Dependency Injection
Osobne si myslim, ze pokial tvoja class stale rastie a uz teraz ma 5+ dependencies, tak je to code smell a neviem, ci priamo inheritance je vhodne riesenie. Skor by si sa mal zamerat na SRP a extrahovat fukncionalitu do inej/inych class a ako dependency pouzit tu novu class s jasne specifikovanou ulohou => casto tym znizis pocet dependencies v class, ktoru riesis a navyse si takymto postupom zjednodusis kod (+ lahsie sa ti to bude testovat, ak ti na tom zalezi)
-
harrison314
Hardcore addict
- Príspevky: 8217
- Registrovaný: 27 máj 2009, 20:42
- Bydlisko: Bratislava
- Kontaktovať používateľa:
Re: PHP - Parent>Child + Dependency Injection
V prpade, ze na podednych triedach nebudes vyuzizvat polymorfizmus, tak to nedel na podene triedy.
Tiez si mylsim ze 5 zavilosti je uz dost, no v takomto pripade sa Di riesi tak ze injktujes specialnu factory.
Ak ta triedy zdiela vela funkcionality, tak by som ju vynal osobytne ako sluzbu, ktoru inekctujes do mensich a konkretnejsich tried, ktore by ju vyuzivali.
No to co opisujes (bez dalsieho kontextu) mi pride ako ukazka janych antipaternov, ako pise Aiden.
Tiez si mylsim ze 5 zavilosti je uz dost, no v takomto pripade sa Di riesi tak ze injktujes specialnu factory.
Ak ta triedy zdiela vela funkcionality, tak by som ju vynal osobytne ako sluzbu, ktoru inekctujes do mensich a konkretnejsich tried, ktore by ju vyuzivali.
No to co opisujes (bez dalsieho kontextu) mi pride ako ukazka janych antipaternov, ako pise Aiden.
-
Holubar
Darca
- Príspevky: 3894
- Registrovaný: 24 feb 2005, 21:26
- Bydlisko: Senec
- Kontaktovať používateľa:
Re: PHP - Parent>Child + Dependency Injection
K poctu dependencies: Cele je to o vyhodnocovani roznych typov sutazi. Jedna sa o modely tabuliek, z ktorych udaje a metody su potrebne pre vyhodnotenie, nastavenie zakladnych parametrov. Vsetky data su potrebne pre kazdy typ sutaze. Rast to zrejme nebude, no moze sa stat ze pridu nove sutaze, ktore budu chciet dalsie typy udajov, tu clovek nikdy nevie, co si klient vyziada.
Navrhovane riesenie je teda injectovat ju ako service do konkretnych tried pre kazdy typ sutaze.
1/ Ako sa v tomto pripade riesi situacia ked finalna trieda potrebuje metodu/property objektu ktory je injectnuty do service triedy. Je spravne, ak to volam cez 2 levely?
2/ Zo zaciatku, ked som drzal metody pre vypocet v tejto service class, mal som jednu public metodu calculate(). Trieda bola pozuivana v 3 controlleroch a to takymto sposobom
V metode calculate bol switch, ktory podla sutaze zavolal spravnu metodu pre jej vypocet
Teraz, ked extrahujem metody do vlastnych tried, co by bolo elegantne riesenie, aby som to mohol volat podobnym sposobom? Vyzera to byt ako situacia pre polymorfizmus, ale popravde som ho este nepouzil, tak si nie som na 100% isty
Navrhovane riesenie je teda injectovat ju ako service do konkretnych tried pre kazdy typ sutaze.
1/ Ako sa v tomto pripade riesi situacia ked finalna trieda potrebuje metodu/property objektu ktory je injectnuty do service triedy. Je spravne, ak to volam cez 2 levely?
Kód: Vybrať všetko
$this->competition_service_obj->getCompetitionsAdministrationObj()->getScratchWorstRace()Kód: Vybrať všetko
$competition_service_obj = competition_service_factory::make($competition_id);
$competition_service_obj->calculate_competition();Teraz, ked extrahujem metody do vlastnych tried, co by bolo elegantne riesenie, aby som to mohol volat podobnym sposobom? Vyzera to byt ako situacia pre polymorfizmus, ale popravde som ho este nepouzil, tak si nie som na 100% isty
-
harrison314
Hardcore addict
- Príspevky: 8217
- Registrovaný: 27 máj 2009, 20:42
- Bydlisko: Bratislava
- Kontaktovať používateľa:
Re: PHP - Parent>Child + Dependency Injection
SKor som si to predtvoval:Holubar napísal:1/ Ako sa v tomto pripade riesi situacia ked finalna trieda potrebuje metodu/property objektu ktory je injectnuty do service triedy. Je spravne, ak to volam cez 2 levely?
Kód: Vybrať všetko
class Competition_service
{
private $competitionsAdministrationObj;
public function __construct($administrationObj)
{
....
$this->competitionsAdministrationObj = $administrationObj;
}
public function getScratchWorstRace()
{
return $this->competitionsAdministrationObj ->getScratchWorstRace();
}
}
...
V tomto pripade je priam ziadnuce switch nahradit polymorfizmom.Holubar napísal:2/ Zo zaciatku, ked som drzal metody pre vypocet v tejto service class, mal som jednu public metodu calculate(). Trieda bola pozuivana v 3 controlleroch a to takymto sposobom
-
Holubar
Darca
- Príspevky: 3894
- Registrovaný: 24 feb 2005, 21:26
- Bydlisko: Senec
- Kontaktovať používateľa:
Re: PHP - Parent>Child + Dependency Injection
Ako by si tu technicky riesil polymorfizmus?
Mna co napada, je vytvorit dalsiu "factory", ktora prijme vytvoreny service objekt a na zaklade parametra z neho cez switch inicializuje spravnu triedu pre vypocet. Kazda trieda obsahuje metodu calculate(), co je zabezpecene cez interface.
Volanie v controlleroch sa potom rozsiri o jeden riadok
dalo by sa to zabalit do druhej factory, ale v niektorych pripadoch potrebujem aj samotny service objekt a jeho metody.
Robi sa to v praxi inak?
Mna co napada, je vytvorit dalsiu "factory", ktora prijme vytvoreny service objekt a na zaklade parametra z neho cez switch inicializuje spravnu triedu pre vypocet. Kazda trieda obsahuje metodu calculate(), co je zabezpecene cez interface.
Volanie v controlleroch sa potom rozsiri o jeden riadok
Kód: Vybrať všetko
$competition_service_obj = competition_service_factory::make($competition_id);
$competition_calculator_obj = competition_calculator_factory::make($competition_service_obj);
$competition_calculator_obj->calculate();Robi sa to v praxi inak?
-
harrison314
Hardcore addict
- Príspevky: 8217
- Registrovaný: 27 máj 2009, 20:42
- Bydlisko: Bratislava
- Kontaktovať používateľa:
Re: PHP - Parent>Child + Dependency Injection
Kedze nepoznam celu architekturu tvojej aplikacie tak odpoviem takto:Holubar napísal:Ako by si tu technicky riesil polymorfizmus?
Mna co napada, je vytvorit dalsiu "factory", ktora prijme vytvoreny service objekt a na zaklade parametra z neho cez switch inicializuje spravnu triedu pre vypocet. Kazda trieda obsahuje metodu calculate(), co je zabezpecene cez interface.
Volanie v controlleroch sa potom rozsiri o jeden riadok
O vytvorenie $competition_calculator_obj by sa mal starat nejaky IoC kontainer, tym by ti odpadli obe faktory, len by si na nom zavolal Resolve.
No mylsim, ze v tomto pripade to mozes spravit tak ako si to napisal.