Továrna vs Model – rozdíly

popcorn
Člen | 28
+
0
-

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
+
0
-

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
+
0
-

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
+
0
-

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
+
0
-

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
+
0
-

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.

popcorn
Člen | 28
+
0
-

V tom máš pravdu, prostě to budu dělat tak, jak mně zrovna napadne (spíš jak dokážu) a pak budu zjišťovat, co je lepší a co ne.
Díky moc všem za objasnění ;)),
Přeji hezký večer.