předání accessoru a továrničky presenteru

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

Ahoj,

potřeboval bych poradit s předáváním továrniček a accessorů presenteru. Četl jsem post od Davida, ale stále tomu uplně nerozumím.

Chtěl bych se uplně vyhnout používání $this->context. Jediný co jsem dokázal splácat:

<?php
/*
neon
services:
	model: Model
	modelAccessor: ModelAccessor
*/

class ModelAccessor
{
	private $container
	public function __construct(Nette\DI\Container $container)
	{
		$this->container = $container;
	}

	public function get()
	{
		return $this->container->model;
	}
}
?>

a v případě továrny

<?php
/*
neon
services:
	articleProvider: ArticleProvider
factories:
	article: Article
*/

class ArticleProvider
{
	private $container
	public function __construct(Nette\DI\Container $container)
	{
		$this->container = $container;
	}

	public function createInstance()
	{
		return $this->container->createArticle();
	}
}
?>

ale přijde mi to uplně k ničemu. V podstatě jsem jen volání $this->context přesunul do samostatné třídy.

Mohl by mi prosím někdo napsat krátké ukázkové řešení, jak předávat accessor a továrnu přes constructor?

Nechápu to využití rozhraní.

Předem děkuju za radu!

Filip Procházka
Moderator | 4668
+
0
-

Především psaní těchto tříd je k ničemu, když ti je může generovat framework. Pročti si tohle a tohle téma, snad ti to napoví :)

xtbman
Člen | 24
+
0
-

díky za reakci! Po důkladném přečtení obou topiců sem pořád trošku zmatenej, co je vlastně ten DI best practice.. potřeboval bych na to asi nějakou knížku :-D

Mě to zajímá především ze studijních důvodů :-) to že mi je framework vygeneruje je krásný, (určitě budu využívat) ale když nevím jak to funguje, tak z toho nebudu spát.

Mám 2 zásadní otázky:

  1. Je využití containeru v továrně oprávněné? (u příkladu, který jsem psal u prvního postu) Nebo tím zase porušuju DI? (accessoru resp. továrně předám klavír, aby mi z něj vytáhla jednu službu resp. továrnu)
  2. Jakou roli tam sakra hraje to rozhraní!? :-D

cituji Davida z jednoho postu, týkajícího se této problematiky
„Není možné vytvořit třídu Article bez Containeru. Správné řešení je použít interface.“ s odkazem na phpfashion, kde jsou ustřižky kódu, ze kterých se mi bohužel nedaří sestavit funkční řešení.
Tudíž otázka zní, jaký je rozdíl mezi tím co jsem napsal já a tím, když tomu ještě přidám

<?php
interface IModelAccessor
{
	/** @return Model */
	public function get();
}
?>

vždyť tu anotaci můžu napsat rovnou k té metodě ve třídě ModelAccessor, nebo se pletu?

Filip Procházka
Moderator | 4668
+
0
-

Ono jde o to, že pokud chceš navrhovat aplikaci čistě, měl bys záviset na abstrakci nebo rozhraní. To znamená, že žádný typehint ModelAccessor bys psát neměl. Měl bys ji pouze zaregistrovat do containeru a pak chtít interface, který implementuje.

No a komu by se chtělo psát interface, když ho bude implementovat jenom jedna třída, že? ;)

Tím, že napíšeš jenom interface (je výrazně kratší) a budeš jej vyžadovat, tak ti jednak je úplně jedno, jak je továrnička/accessor implementovaná, protože tě to absolutně nezajímá (protože závisíš na rozhraní, né jeho implementaci) a jednak ti to pak může na základě toho interface generovat framework.


Co se týče containeru v té továrně. Je to samozřejmě trošku porušením DI, protože předáváš piáno, když chceš doutník. Ale na druhou stranu, kdybys do acessoru předal hotovou instanci a pak ji jen volal přes get, tak by to trochu ztrácelo smysl, ne? :)

Tohle není lazy a je to zcela zbytečné.

class ModelAccessor
{
    private $mode;
    public function __construct(FooModel $model)
    {
        $this->model = $model;
    }

    public function get()
    {
        return $this->model;
    }
}

vs

Tohle je lazy.

class ModelAccessor
{
    private $container;
    public function __construct(Nette\DI\Container $container)
    {
        $this->container = $container;
    }

    public function get()
    {
        return $this->container->model;
    }
}
xtbman
Člen | 24
+
0
-

Děkuju, přesně tohle jsem potřeboval :-) a myslim, že se to bude hodit více lidem.

Jak jsi psal, že to umí framework generovat sám, tak předpokládám že jsi myslel ten extension co jsi vytvořil. Funguje i na služby? (je možné nějak odlišit v neonu, jestli se má vytvořit továrna, nebo accessor)

ad: budu dělat maturitní práci na téma Nette.
Je blbost si myslet že služby v Nette jsou dle návrhového vzoru Singleton a tyto továrničky Factory?
P.S: je to trochu mimo téma, ale nechci spamovat fórum dost možná úplnými kravinami :-)

Filip Procházka
Moderator | 4668
+
0
-

xtbman napsal(a):

Jak jsi psal, že to umí framework generovat sám, tak předpokládám že jsi myslel ten extension co jsi vytvořil. Funguje i na služby? (je možné nějak odlišit v neonu, jestli se má vytvořit továrna, nebo accessor)

Já ale nepsal, že to framework umí generovat :) Ten extension bych nepoužíval, je tam pár zádrhelů, byl to spíše takový nápad. Na továrničky jsem napsal pullrequest, čekám jestli ho David příjme, nebo zamítne. Na základě toho by se pak daly generovat i accessory.

ad: budu dělat maturitní práci na téma Nette.
Je blbost si myslet že služby v Nette jsou dle návrhového vzoru Singleton a tyto továrničky Factory?

Navenek se to tak chová, ale nejsem si jistý tím singletonem. To, že je to singleton, zaručuje DI Container, nikoliv služba samotná.

P.S: je to trochu mimo téma, ale nechci spamovat fórum dost možná úplnými kravinami :-)

Vždycky můžeš přijít spamovat jabber konferenci nette@conf.netlab.cz ;)

xtbman
Člen | 24
+
0
-

HosipLan napsal(a):

Především psaní těchto tříd je k ničemu, když ti je může generovat framework. Pročti si tohle a tohle téma, snad ti to napoví :)

tady jsi psal o tom extensionu ne?

Jinak si mi hodně pomoh! Na jabber určitě zajdu.