Za objekty hloupější

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
David Grudl
Nette Core | 8218
+
0
-

Moc šikovné věci mohou být těžko pochopitelné. Proto preferuji objekty hloupějí (mám na mysli objekty programátorské, nikoliv objekty sexuálního zájmu. …i když…).

Jako příklad mohu použít třeba RobotLoader. Aby správně fungoval, musí být nastavena proměnná prostředí tempDir:

Environment::setVariable('tempDir', '/tmp');

$loader = new Nette\Loaders\RobotLoader;

Vazba mezi oběma třídami je magická, z API třídy RobotLoader ji nevyčtete. Dokonce ji nelze vytušit ani ze zdrojového kódu, RobotLoader totiž používá factory Cache, které používá singleton ICacheStorage, jehož výchozí implementace je FileStorage a teprve to pracuje s proměnnou tempDir. Uff.

Ze stejného soudku jsou všechny autodetekce produkčního/vývojového prostředí, které někde něco ovlivňují.

Výhodou samozřejmě je jednodušší použití chytrých tříd (vezmu RobotLoader a nemusím ho ručně propojovat se službami). Přesto se mi to nelíbí. Zatím jsem všechny přístupy ke globálním službám „vytknul“ na konce tříd, do sekce backend, ovšem ne jako konečné řešení, spíš jako upozornění, že tady je potřeba něco řešit.

Udělat RobotLoader hloupějším není v celku problém. V konstruktoru nebo pomocí setteru by se mu povinně předala informace, kterou si nyní sám tahá z Environment:

$loader = new Nette\Loaders\RobotLoader;
$loader->setCache(Environment::getCache('Nette.RobotLoader'));
$loader->setAutoRebuild(!Environment::isProduction());
...

Samozřejmě se ozvou uživatelé, kterým současné řešení víc vyhovuje a nechtějí do bootstap.php pokaždé přidávat dva řádky navíc. I na tohle je odpoveď – mít továrnu na nakonfigurovaný RobotLoader:

$loader = Environment::getRobotLoader(); // volá nějakou továrnu
...

Obsluhu a fungování továrny, která se skrývá za Environment, má na starosti Configurator a ServiceLocator. Tyto třídy zatím moc prostoru nedostaly a vypadají jako něco hodně v pozadí, což je věc, kterou bych rád změnil. A zároveň všechny sekce backend dostal z tříd pryč.

Celá věc má ale jednu zapeklitost. Vezměme si třeba třídu User, využívající objekty IAuthenticator a IAuthorizator. Ta už sice má svou továrnu Environment::getUser(), ale v ní nedochází k nastavení zmíněných handlerů. Proč? No protože autorizace nebo autentizace se provádí méně často a zbytečně bych musel draze vytvářet objekty, které nejspíš nebudou využity. User si vyžádá handler až v okamžiku, kdy ho potřebuje, ale to už o něj musí požádat Environment – a jsme zase na začátku.

Řešení vidím v následujícím postupu, ale nejsem si úplně jistý, jak to implementovat. V podstatě jde o to, aby místo:

function createUser() {
    $user = new User;
    $handler = new MyAuthenticator;
    $user->setAuthenticationHandler($handler);
    return $user;
}

šlo používat něco jako

$user->setAuthenticationHandler($tovarnaNaHandler);

Metoda getAuthenticationHandler by vypadala takto:

	public function getAuthenticationHandler()
	{
		if ($this->authenticationHandler je tovarna) {
			$this->authenticationHandler = $this->authenticationHandler->invoke();
		}
		return $this->authenticationHandler;
	}

Tudy se mé plány ubírají. Co myslíte?

jiriknesl
Člen | 56
+
0
-

Kéž by měl den 48 hodin a já nemusel spát… :))

Předělávám po malých chvilkách RobotLoader, aby uměl Dependency Injection (což je to, kam pomalinku směřuješ, jestli křišťálová koule nelže) a snad časem (rozuměj koncem tisíciletí) i AOP.

Jinak docela dobře promyšlené je to tady:
http://flow3.typo3.org/…ence/object/

snad by to šlo nějak ukrást. :)

phx
Člen | 651
+
0
-

Zajimave:) Ona magicka zavislost v Nette me dost fascinuje. Napr Ladenka a spol. Doted se mi stale mota co se kde zapne kdyz dam mode LIVE nebo neco jineho. Mozna by stacila nejak dokumentace:) ci vysvetleni.

Ohledne lazy tvoreni objketu je to fajn napad:) Osobne bych to resil asi PHP callbacky. Nebo tam je nejaky hacek?

kravčo
Člen | 721
+
0
-

phx napsal(a):

Zajimave:) Ona magicka zavislost v Nette me dost fascinuje. Napr Ladenka a spol. Doted se mi stale mota co se kde zapne kdyz dam mode LIVE nebo neco jineho. Mozna by stacila nejak dokumentace:) ci vysvetleni.

Ohledne lazy tvoreni objketu je to fajn napad:) Osobne bych to resil asi PHP callbacky. Nebo tam je nejaky hacek?

Toto mi pripomenulo jednu vec. Módy a názvy prostredí mi dlho robili problémy, keď som tomu porozumel a pozeral si zdrojáky, prišiel som k tomu, že mi stále niektoré veci nie sú jasné, hlavne z definovaných konštánt a použitia módov/názvov:

Trieda Environment má konštanty pre rôzne názvy a módy. Konkrétne

Názvy prostredí: development, production, console a lab
Názvy režimov: debug, performance

Pritom používa hlavne režim production. Vzhľadom na význam sa to dá chápať, ide o režim na produkčnom serveri, kde je akékoľvek vypisovanie chýb nežiadúce – a tak to je aj v Nette zakomponované (cez test Environment::isProduction()). Zmenou liveproduction sa tento termín zjednotil pre názov prostredia i režim, čo môže byť mätúce, no myslím, že je to stále lepšie ako live. Chystajú sa nejaké zmeny aj v tejto oblasti?

David Grudl
Nette Core | 8218
+
0
-

jiriknesl napsal(a):

Jinak docela dobře promyšlené je to tady:
http://flow3.typo3.org/…ence/object/

Díky moc za odkaz! Poteší, že někdo uvažuje nad stejnými problémy a ještě navím používá jmenné prostory v PHP :-) Bohužel ale klasické kontejnery pro dependency injections neřeší problém s lazy loadingem.

jiriknesl
Člen | 56
+
0
-

David Grudl napsal(a):

jiriknesl napsal(a):

Jinak docela dobře promyšlené je to tady:
http://flow3.typo3.org/…ence/object/

Díky moc za odkaz! Poteší, že někdo uvažuje nad stejnými problémy a ještě navím používá jmenné prostory v PHP :-) Bohužel ale klasické kontejnery pro dependency injections neřeší problém s lazy loadingem.

Existuje vůbec nějaký DI kontejner, který řeší lazy loading? Nejen v PHP, myslím obecně.

David Grudl
Nette Core | 8218
+
0
-

jiriknesl napsal(a):

Existuje vůbec nějaký DI kontejner, který řeší lazy loading? Nejen v PHP, myslím obecně.

Nikdy jsem se s tím nesetkal.