BasePresenter ano nebo ne? pripadne jak spravne/nejlepe
- MrAndy
- Člen | 12
Ahoj vsem,
rad bych se zeptal jaky je nejlepsi zpusob pouzivani BasePresenteru.
Docetl jsem se ze jeho pouzivani muze vest ke Constructor hell a ze je lepsi
pouzivat kompozici.
Ale jak jsem pochopil pri pouzivani kompozic je nutne v kazdem presenteru
pouzit construct, coz mi prijde jako zbytecne psani navic.
V mem pripade vim ze v kazdem presenteru potrebuji $database a nekdy
$translate, a v tomto pripade mi prijde BasePresenter jako idealni reseni.
A tak se chci zeptat jake je tedy idelani reseni abych se vyhnul Constructor
hell ale zaroven mel vsude dostupne $database a $translate?
Muj Base
<?php declare(strict_types = 1);
namespace App;
use App\Core\Alerts;
use Nette;
use Contributte;
abstract class BasePresenter extends Nette\Application\UI\Presenter
{
/** @persistent */
public $locale;
public function __construct(
protected Nette\Database\Explorer $database,
protected Nette\Localization\Translator $translator,
protected Contributte\Translation\LocalesResolvers\Session $translatorSessionResolver
)
{
parent::__construct();
}
protected function startup(): void
{
parent::startup();
$this->locale = $this->translator->getLocale();
$this->translatorSessionResolver->setLocale($this->locale);
if (!$this->getUser()->isLoggedIn() && $this->getAction() !== 'login') {
$this->redirect(':Auth:login', ['locale' => $this->locale]);
}
}
public function beforeRender(): void
{
parent::beforeRender();
$this->template->tplDir = __DIR__.'/UI/Templates/';
$this->template->locale = $this->locale;
$this->template->pageTitle = 'DevIOArts';
$this->template->pageTitleSub = 'With Love <i class="fa fa-heart text-danger"></i>';
$this->setAlerts();
}
private function setAlerts(): void
{
$alerts = new Alerts($this->database);
$this->template->alerts = $alerts->getAlerts();
$this->template->alertsCount = count($this->template->alerts);
}
public function handleChangeLocale(string $locale): void
{
$this->translatorSessionResolver->setLocale($locale);
$this->redirect('this');
}
}
- Infanticide0
- Člen | 103
inject* metody budou fungovat líp.
Alerts jsou nějaký notifikace? Proč to není UI Control?
#[Persistent]
- Šaman
- Člen | 2658
Ohledně DI v presenterech existuje zlaté pravidlo:
- v abstraktních používat settery (
inject*
metoda je setter s defaultně zapnutým injectováním závislostí) - v koncových presenterech používat konstruktor (přestože inject metody a properties fungují taky a spousta lidí je používá i tady)
- doporučuji používat i keyword
final
u koncových presenterů – už z nich nepůjde dědit, takže nemůže existovat potomek, který si přepíše konstruktor
Proč? Inject property porušují zapouzdření (jsou public a někdo zvenku
tam tu závislost předá). Inject metody jsou ok, jen je nikdy nevolej ručně
(pokud sám nevíš přesně že to chceš). Jsou to settery, které z konvence
DI kontejner najde a vyplní ihned po vytvoření objektu. Pak už by neměly
být přesány.
Konstruktor je nejčistější, není možné vůbec vytvořit objekt bez jeho
závislostí a nehrozí jejich přepsání během života objektu. Ale
v abstraktních presenterech hrozí právě ten constructor hell, kde potomek
musí volat konstruktor předka a předat mu závislosti.
U komponent, pokud máš také důvod k používání abstraktních předků doporučuji stejný způsob, jen je tam potřeba to automatické injectování zapnout. Většinou si u nich ale vystačíme s final třídami.
A v modelu ideálně používat jen konstruktor a případně settery,
které ale zmíníme v configu (hledej decorator
) a nebudeme
zapínat automatické injectování pomocí metod.
- Marek Znojil
- Člen | 84
Šaman napsal(a):
- doporučuji používat i keyword
final
u koncových presenterů – už z nich nepůjde dědit, takže nemůže existovat potomek, který si přepíše konstruktor
Doporučuji i u inject*
metod.