Nekonzistentní Presenter při vytvoření nového objektu

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

Use case: Jsem v nějakém CLI skriptu a potřebuji generovat odkazy. Např. rozesílám e-maily a potřebuji se z nich odkázat na vlastní web. Co proto musím udělat kromě samozřejmého naplnění proměnných $_SERVER['HTTP_HOST'] apod. o které se normálně stará Apache?

Za účelem generování si vytvořím nový presenter:

$presenter = new HomepagePresenter();

Člověk by si myslel, že nyní může na presenteru volat metodu link() a dostane, co očekává. Splnil všechny závislosti, které mu rozhraní konstruktoru předepsalo.

Ale omyl! Vysypaly se na mě errory a noticky a já se jal zkoumat zdrojáky. Přišel jsem na to, že Presenter je až do zavolání metody run() ve strašně nekonzistentním stavu. PresenterRequest by měl být přijímán už v konstruktoru, protože bez něj objekt Presenteru nedává smysl. Zároveň si myslím, že Presenter není zrecyklovatelný pro více běhů nad různými requesty, takže by to skutečně dávalo smysl.

Jsou to trochu laboratorní podmínky, ale v těchto momentech vývojář zjišťuje, že mu Nette vlastně nepomáhá, ale překáží.

Těchto míst je v Nette víc (např. RobotLoader by měl CacheStorage přijímat v konstruktoru a ne setterem) a pro zavedení opravdové DI je potřeba je všechny odstranit. Zkrátka pokud se mi vede vytvořit nový objekt dané třídy, už by mi měl dovolit s ním dělat cokoli, aniž bych se musel vrtat ve zdrojácích a zjišťovat, proč to nefunguje. To je DI.

David Grudl
Nette Core | 8218
+
0
-

Ondřej Mirtes napsal(a):

PresenterRequest by měl být přijímán už v konstruktoru, protože bez něj objekt Presenteru nedává smysl. Zároveň si myslím, že Presenter není zrecyklovatelný pro více běhů nad různými requesty, takže by to skutečně dávalo smysl.

Je to tak, pošleš patch?

Těchto míst je v Nette víc (např. RobotLoader by měl CacheStorage přijímat v konstruktoru a ne setterem) a

Stejně tak by měl přijímat seznam adresářů, co když zapomenu zavolat addDirectory()? Tenhle argument prostě neobstojí. Jelikož se instance stejně vytváří jen v Configuration, neobstojí ani můj argument s lepší čitelností kódu, takže klidně pošli patch.

pro zavedení opravdové DI je potřeba je všechny odstranit.

Jaké jsou další případy?

Ondřej Mirtes
Člen | 1536
+
0
-

Pošlu patche :)

U téhle situace jsem si jistý v těchto dvou případech, ale je možné, že se to děje ještě jinde, kde jsem na to nenarazil.

Ondřej Mirtes
Člen | 1536
+
0
-

Uvědomil jsem si, že s rozhraním IPresenter nic špatně není, takže to spíš budu muset směřovat tím, že opravím ten stav Presenteru před run(), pokud to nějak půjde.

Honza Marek
Člen | 1664
+
0
-

Ondřeji, neposílej patch, vymluv se na lenost! :)

Vždyť pak nepůjde jednoduše udělat presenter factory ve stylu

class PresenterFactory implements IPresenterFactory
{
	private $container;

	public function __construct($container)
	{
		$this->container = $container;
	}

	public function createPresenter($name)
	{
		return $this->container->getService($name);
	}
}