Továrna vs Model – rozdíly
- popcorn
- Člen | 28
Ahoj, mám trochu problém pochopit rozdíl mezi továrnou a modelem. Kdy použiju továrnu a kdy model? Např. v sandboxu je SignIn a SignUp továrna, ale já to přeci mohu dát do UserManager modelu ne? Mohl by mi to někdo prosím vysvětlit – konkrétněji koumám nad registrací/přihlášením s databází.
Předem děkuji,
popcorn
- duke
- Člen | 650
V aktuálním sandboxu se používají tovární třídy, které mají za
úkol připravit formulář pro přihlášení a zaregistrování uživatele a
fungují tak, že těm formulářům nastaví i handlery události success,
což jsou v tomto případě metody, které pracují s modelem (konkrétně se
službami User
a UserManager
). Model tedy používáš
v každém případě, byť je schován v těchto handlerech.
A i v tom sandboxu se pracuje s databází. Tím, že služba
UserManager
implementuje rozhraní
Nette\Security\IAuthenticator
, je tato služba automaticky (přes
autowiring) nastavena službě User
jakožto služba pro
ověřování přihlašovacích údajů a v rámci volání
User::login($username, $password)
je pak volána její metoda
UserManager::authenticate
, která pracuje s databází.
Editoval duke (3. 7. 2019 18:43)
- Kamil Valenta
- Člen | 822
Model je třída, která se stará o nějakou aplikační logiku, manipuluje s daty, něco třeba počítá, vyhodnocuje. Model nezajímá, kým a odkud je volán – na model může sahat Presenter při odbavování uživatelova požadavku z prohlížeče, na model může sahat nějaké API, na model může sahat úplně jiné rozhraní.
Factory je způsob, jak ze třídy instancovat objekt a dodat mu potřebné závislosti. O nic víc se továrnička nestará.
Editoval kamil_v (3. 7. 2019 18:55)
- Šaman
- Člen | 2667
Model jsou dokonce všechny ty výpočetní a s daty pracující třídy dohromady. Je to prostě veškerá aplikační logika. Když si představíš, že aplikace bude pracovat přes telnet a nějakou příkazovou řádku, tak model je všechno to, co nebude potřeba změnit. Třeba ověření uživatele – modelu je jedno, jestli někdo zadal jméno a heslo do www foruláře, nebo jestli to zadal postupně přes příkazovou řádku. Práce s databází uživatelů, ověření a práce s hashem, to zůstává stejné.
Model je tedy spíš naše rozdělení kódu do provazaných částí Model, View a Presentery (model řeší výpočty, pohled jak to má vypadat a presenční vrstva to celé provazuje dohromady).
Zatímco továrna je návrhový vzor – konkrétní řešení. Továrna je malá třída, která vrací nějakou instanci modelové třídy.
Aha, tobě jde o ty SignIn/Out
… to jsou továrny na
formuláře. Jde o to, že formulář obecně může být použitý na více
místech. Ta továrna ti vrací vytvořený formulář. Nic víc nedělá.
A když potřebuješ ten formulář, injectneš si továrnu a ta ti ho
vytvoří. Pokud by byl formulář přímo v té třídě UserManager, a navíc
i někde jinde, musel bys kvůli každé změně přepisovat více tříd.
Na to rozdělení adresářů Model
a Forms
moc
nekoukej, to je jen kosmetika. U mě je třeba definice formulářů
součástí modelu, většinou u entity, se kterou ten formulář pracuje.
Protože když upravím nějakou entitu, většinou pak taky musím upravit
její formulář na vytvoření a editaci.
Až ti bude jasné, jak to funguje, najdeš si vlastní styl rozdělení
aplikace.
P.S. Jinak samozřejmě i když je formulář jen na jednom místě, tak
lépe se upravuje nějaký přihlašovací formulář (třeba přidání
captchy) když je ve své malé třídě, než když kvůli tomu musíš vlézt
do již odladěné třídy Authenticator
, která je kritická
z pohledu bezpečnosti. Nebo když na to chceš pustit nováčka, tak
v souboru SignIn
může maximálně způsobit, že se nedá
přihlásit. V UserManager
ale může způsobit, že se dá
přihlásit bez platného hesla, což je větší průser. Prostě je to
rozdělené protože s více jednoúčelovými třídami se líp pracuje, než
s jednou komplexní.
Editoval Šaman (3. 7. 2019 19:16)
- popcorn
- Člen | 28
Takže vlastně továrna je vlastně když budu chtít mít formulář na více místech tak abych ho nemusel psát všude stejný tak si udělám továrnu a pak jí jen naimportuju?
No já třeba formulář vytvářel až přímo v Presenteru pomocí
createComponentUserForm(), to asi nebude dobré, protože tam pak mám
i další try/catch bloky a to už by v presenteru asi být nemělo že?
Např toto mám v UserPresenteru.
<?php
protected function createComponentUserForm()
{
$form = new Form;
$form->addText('name', 'Jméno')->setRequired();
$form->addEmail('email', 'Email')->setRequired();
$form->addPassword('password', 'Heslo')->setRequired();
//$form->addPassword('repeatpassword', 'Heslo znovu');
$form->addSubmit('send', 'Odeslat');
$form->onSuccess[] = function (Form $form, ArrayHash $values) {
try {
$this->UserManager->newUser($values);
$this->flashMessage('Úspěšně registrován.');
} catch (UniqueConstraintViolationException $e) {
$this->flashMessage('Uživatel s tímto jménem již existuje.');
}
};
return $form;
}
?>
- Šaman
- Člen | 2667
No, řeknu to takhle: Bude ti to fungovat. A i já tak začínal. Jako první oddělit šablony od kódu a většina kódu byla v presenterech a nebo v nějakých výpočetních třídách (které tvořily jakési torzo modelu).
Ne, čisté to není. Resp. zrovna u toho přihlašovacího formuláře to ještě jakž takž jde, ale u formulářů, které se starají o data, už bych to nedoporučil.
Ale protože Nette už dávno není jen Laděnka a chytré formuláře, tak se s Nette zezačátku musíš sžít. A to jde nejlépe tím, že ho začneš používat. Třeba i nedoporučovanym způsobem. Klidně měj formuláře takhle a řeš spíš DI a injectování. A časem zjistíš, proč tohle není ideální.
Jinak to zpracování formuláře by pak bylo na dvou místech. Zpracování dat přímo v továrně a v prsenteru pak navázání flashmessage na onError a onSuccess. Ale to bychom zase zabředli hlouběji. A mám pocit, že v Nette už je tolik věcí, že je možná lepši začit zeširoka a postupně se dostávat do hloubky, než se ponořit do prvního problému bez znalosti ostatních.