Environment::getVariable a Environment::getConfig v nové verzi Nette

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
chikeet
Člen | 160
+
0
-

Zdravím,
řeším upgrade CMS z Nette 2.0 beta na Nette 2.0.10, konkrétně čím nahradit Environment::getVariable() a Environment::getConfig() mimo presenter. Ideálně podobně „instantním“ způsobem jako při použití Environment, tzn. tak, aby nebylo nutné předávat další parametr konstruktoru třídy, která to využívá, a dalších x tříd, které ji volají. (Snažím se o upgrade s minimem zásahů kvůli snížení množství potenciálních chyb, vylepšování kódu mám v plánu, až to pojede.)

V presenteru chci místo Environment::getConfig('jmeno_parametru') použít $this->context->parameters['jmeno_parametru'], místo Environment::getVariable('baseUri') použít $presenter->context->httpRequest->url->baseUrl a místo Environment::getVariable('appDir') konstantu APP_DIR nadefinovanou v indexu, jako to bylo v dřívějších verzích.

Uvítám jakékoliv nápady, jak to vyřešit mimo presenter nebo jako to líp vyřešit v presenteru, případně cokoliv, co mi pomůže líp pochopit práci s containerem a configuratorem.

llsm
Člen | 121
+
0
-

Nemas podle me moc moznosti, tyto promenne mimo presenter lze brat bud z nejakeho statickeho prostredi (jako je Enviromnent), ktere je pristupne vsude nebo si promenne musis predat pomoci konstruktoru, setteru. To je v kazdem pripade vzdy zasah na obou koncich, tj. musis upravit jak tridu kterou z presenteru vytvaris, tak zpusob jakym ji vytvoris.

kubajz
Člen | 47
+
0
-

vylepšování kódu mám v plánu, až to pojede

nejlepší je podle mě vylepšit kód hned, když jsi u něj :)

čím nahradit Environment::getVariable()

dle mého názoru nejčistší a zároveň nejjednodušší řešení je opravdu pomocí setteru/konstruktoru. Není dobré, když uvnitř nějaké metody „magicky“ přistupuješ k nějaké jiné třídě. S pomocí nějakého IDE nejde zas o tak složitý problém.

saimons
Člen | 293
+
0
-

Po nahozeni nove verze bych prepsal kompletne ty casti, ktere nefunguji, nebo jsou spatne napsany. Doporucoval bych prepisovat rovnou na 2.1-dev, protoze brzo bude stable verze. Vyhnul bych se uplne pouzivani context (v budoucnu bude na stejne urovni jako ted Environment), pouzivej vyhradne inject* a setry a pokud neco potrebujes v modelu tak si to take muzes pomoci autowire predat pres constructor. Pokud potrebujes naco do komponenet, tak je tady nekde na forku krasnej navod jak to udelat pres factory.

chikeet
Člen | 160
+
0
-

Díky za rady.

Když nad tím přemýšlím, obecně mi na tom novém přístupu nesedne hlavně to, že právě konfigurační data by podle mě měla být přístupná odkudkoliv, od toho je to přece konfigurace. Nebo uvažuju špatným směrem? Jaký je přesně důvod k tomu, aby se tato data předávala kaskádovitě přes konstruktory tříd?

Šaman
Člen | 2666
+
0
-

Důvod je ten, že každá třída by měla deklarovat všechny svoje závislosti.
Už proto, že až po tobě přijde cizí programátor, tak si nebude říkat kde se sakra vzala tahle hodnota?
Druhý důvod je nahraditelnost a přenositelnost tříd. Co když na druhém projektu nebudeš používat cache a proto nebude nakonfigurovaná? Třída ti nebude běhat a z API nepoznáš, že potřebuje cache, pokud si ji tahá někde sama z kontejneru.
Třetí důvod je testování. Při testování potřebuješ podstrčit testované třídě třeba falešnou databázi. Ale jak, pokud si ji ta třída načítá sama?

Další důvod je, že na různých místech si můžeš danou služby vytvářet jinak a špatně se to pak ladí. Porušuje to princip, který říká, že jedna věc se má řešit na jediném místě. Co, když jednou budeš tahat službu z kontejneru proti rozhraní a jindy podle jména služby? Službu pak z nějakého důvodu přejmenuješ, a něco běhá, něco ne.

Další princip, který to porušuje je Single Responsibility, tedy že jedna třída má přešit jen jedinou věc. Tedy třeba práci s tabulkou uživatelé. Nikoliv tahání databáze odněkud.


Takže vznikl návrhový vzor Dependency Injection, který tohle všechno řeší. Říká, že každou proměnnou, či službu zvenku musí třída obdržet a nevytvářet si ji sama. Konstruktorem, setterem (v nette je často tím setterem inject* metoda), nebo přímým nastavením public property.


Konfigurační data, resp. celý kontejner chápej jako sklad, který je vedle dílny. Je v něm všechno, co někdo v dílně může potřebovat. Postaru by se to dělalo tak, že každý tam může courat a vzít si co chce. Potřebuješ tedy inteligentního dělník, který kromě své práce zvládá i logistiku materiálu apod. Jinak bude jeho výroba neefektivní.

DI princip říká, že ráno nastoupí dělník na šichtu, někdo mu připraví materiál (nafasuje ho) a on může rovnou začít vyrábět. A někdo jiný, kdo se vyzná ve skladu mu to připraví.

Který dělník splňuje, že umí dobře právě jednu věc? A který se ti bude lépe přenášet mezi fabrikama, kde bude skladová politika jiná?

Editoval Šaman (24. 4. 2013 17:21)

saimons
Člen | 293
+
0
-

Hezkej clanek o DI.

rixi
Člen | 109
+
0
-

Asi aj najlepsi.

chikeet
Člen | 160
+
0
-

Díky, to mi jako důvod úplně stačí.