Autor: Informatika ku káve

Pridané: 30.07.2021

MVC, čo to je a ako to vyzerá v praxi ?


V tomto článku si popíšeme návrhový vzor MVC (označovaný aj ako Model-View-Controller), ktorý rozdeľuje aplikáciu do 3 logických častí, ktoré medzi sebou komunikujú. Na začiatok si povieme niečo jemne o histórii, motivácii vzniku a neskôr si vysvetlíme každú logickú časť tohto návrhového vzoru samostatne, a ako by to malo byť aj zvykom, reálne využitie v praxi. 


História


Za týmto návrhovým vzorom stojí pán s menom Trygve Reenskaug (celým menom Trygve Mikkjel Heyerdahl Reenskaug), ktorý je emeritný profesor na univerzite v Osle. MVC uviedol v 70tych rokoch do programovacieho jazyka Smalltalk-79 počas toho ako navštívil Xerox PARC (Palo Alto Research Center). Z MVC modifikáciami neskôr vznikli aj ďalšie samostatné návrhové vzory ako MVVM (model-view-viewmodel), MVA (model-view-adapter), MVP (model-view-presenter) [1].


Prečo ale niečo ako MVC potrebujeme ? Je dobré rozdeľovať náš kód do 3 logických komponentov ? Nebolo by to jednoduchšie implementovať spolu ?


Predstavme si, že pracujeme v tíme programátorov na aplikácii pre videokonferencie s cieľom získať čo najväčší počet používateľov. Ak by sme sa takúto aplikáciu rozhodli implementovať spôsobom “všetko implementujme spolu a kašlime na rozdelenie aplikácie do logických častí”, tak by sme počas vývoja veľmi rýchlo narazili na nasledujúci problém. Používateľské rozhranie by bolo prepojené s biznis logikou a dátami, čo by viedlo k niečomu čo nazývame špagetový kód, ako aj k závislostiam zdanlivo samostatných častí softvéru. To by spôsobilo problém, že ak by sme sa rozhodli modifikovať používateľské rozhranie, znamenalo by to zmenu v kóde aj pre biznis logiku. Rovnako by bolo skoro nemožné rozdeliť biznis logiku, dátový model a používateľské rozhranie určitej funkcionality ako samostatné úlohy pre tím programátorov. Toto je len úryvok problémov, ktoré MVC rieši.


Ako MVC vyzerá a čo je úlohou každého komponentu ?


Ako sme si už na začiatku spomenuli, MVC rozdeľuje logiku aplikácie do 3 častí. Model, View a Controller. Vizualizáciu týchto častí a komunikáciu medzi nimi môžeme vidieť na nasledujúcom obrázku:





Model


Model sa stará o reprezentáciu a manipuláciu s dátami v aplikácií. Častokrát naša aplikácia pracuje s perzistentnými dátami (také, ktoré sa uchovávajú aj po vypnutí aplikácie používateľom), ktoré sa ukladajú v databázovom systéme (PostgreSQL, MySQL, MariaDB, MongoDB...). Preto patrí medzi jednu z úloh Modelu komunikácia s databázovým systém. Ako príklad si uvedieme aktualizovanie záznamu v databáze. Model musí vedieť odoslať informáciu databázovému systému o aktualizovaní konkrétneho záznamu a rovnako musí byť schopný prijať informáciu od databázového systému o úspešnom aktualizovaní. Ďalšou úlohou Modelu je komunikácia s Controllerom.


View


Úlohou View je vizuálna reprezentácia dát aplikácie jej používateľom (jednoduchšie povedané ide o používateľské rozhranie). Z príkladu aplikácie pre videokonferencie by mohlo ísť o zobrazenie počtu ľudí prihlásených do videokonferencie, možnosť zobraziť si ich profil, možnosť vytvoriť nové stretnutie, aktualizovať existujúce stretnutie a podobne. View musí byť schopné posielať informácie o požiadavkách používateľa pre Controller a rovnako aj prijímať informácie od Controllera.


Controller


Controller zabezpečuje biznis logiku aplikácie a rovnako zabezpečuje komunikáciu medzi View a Modelom. Ak sa používateľ aplikácie rozhodne vytvoriť novú videokonferenciu View túto informáciu (vstup od používateľa) odovzdá Controlleru a Controller ďalej modelu, ktorý sa už postará o vytvorenie nového záznamu pre videokonferenciu. Model následne pošle informáciu Controlleru o úspešnom/neúspešnom vytvorení videokonferencie a Controller naspäť View, ktorý zobrazí požadovaný výstup pre používateľa (zobrazenie hlášky o úspešnom/neúspešnom vytvorení videokonferencie).


Kde sa viem s MVC stretnúť v praxi a aké má výhody/nevýhody ?


MVC má svoje využitie pri tvorbe webových, mobilných a desktopových aplikácií. Ako príklad technológií, ktoré pracujú s MVC architektúrou si môžeme uviesť:

  1. Laravel
  2. Spring
  3. ASP.NET
  4. ...


Výhody

  1. Ponúka rozdelenie aplikácie do logických celkov, čím predchádzame špagetovému kódu
  2. Urýchľuje proces vývoja (jeden tím programátorov môže začať pracovať na používateľskom rozhraní, zatiaľ čo druhý môže implementovať biznis logiku aplikácie)
  3. Zmena používateľského rozhrania si nevyžaduje zmenu iných častí aplikácie
  4. Dáta z jedného modelu môžu byť použité vo viacerých View


Nevýhody

  1. Častokrát  nutná znalosť viacerých technológií [2] (napr. v prípade Laravel aplikácií znalosť PHP a JavaScriptu (Vue, React, Angular...)
  2. Komplexnosť aplikácie (prinášame určitý level abstrakcie) [2] ?!


Ukážka


V tejto časti článku si predstavíme reálny kód, reálnej aplikácie. O akú aplikáciu ide ? Predsa o portál Informatika ku káve. Ak ťa zaujíma viac o procese vývoja tohto portálu, nezabudni si prečítať aj článok “Ako som nakódil Informatiku ku káve”. Ukážka implementácia bude odkazovať na proces vytvorenia článku používateľom.


Model

Článok reprezentuje Model s názvom Article, ktorý pomocou ORM patrí k databázovej tabuľke articles. Implementácia tohto modelu vyzerá nasledovne: 


<?php

namespace App\Models;

...

class Article extends Model
{
    protected $fillable = [
        ...
        'title',
        'perex',
        'author',
        ...
    ];

    protected $dates = [
        ...
        'created_at',
        ...
    ];

    ...
   
    /* ************************ CONSTANTS ************************* */

    const ARTICLE_TYPE_NEW = 'new';
    const ARTICLE_TYPE_APPROVED = 'approved';
    const ARTICLE_TYPE_REJECTED = 'rejected';
    const DEFAULT_FRONTEND_PER_PAGE = 5;

    ...
}


Ako z tejto ukážky môžeme vidieť, Model Article má atribúty ako title, perex, author, created at … (ide o rovnaké atribúty ako má aj databázová tabuľka articles)


View

O používateľské rozhranie článku sa stará blade súbor a Vue component <new-article>. Ukážka tejto časti implementácie vyzerá nasledovne: 


@extends('frontend.layouts.app')
...

@section('content')

    <new-article
            inline-template>
        <div>
            ...

            <form class="w-5/6 mx-auto mt-20" method="post" @submit.prevent="addArticle('{{route('store-article')}}')" ...>
                ...

                <div class="flex flex-wrap -mx-3 mb-0 md:mb-6">
                    <div class="w-full md:w-1/2 px-3 mb-6 md:mb-0">
                        <label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2" for="author">
                            {{ _('Autor') }}
                        </label>
                        <input v-model="form.author"
                                                                    v-validate="'max:255'"
                                                                   class="appearance-none block w-full bg-gray-200 text-gray-700 border border-gray-200 rounded py-3 px-4 mb-3 leading-tight focus:outline-none focus:bg-white focus:border-gray-500"
                                                                   name="author"
                                                                   id="author"
                                                                   type="text"
                                                                   placeholder="{{ __('Janko Hráško') }}">
                        <p v-if="errors.has('author')" class="text-xs italic text-red-500">{{ _('Autor môže mať maximálne 255 znakov') }}</p>
                    </div>
                    ...
                </div>
                
                ...
                
                <div class="flex justify-center mt-20">

                    <button class="ml-5 bg-blue-500 text-white font-light py-2 px-4 rounded">
                        <i class="fas fa-paper-plane"></i> {{ _('Odoslať na schválenie') }}
                    </button>
                </div>
            </form>
        </div>
    </new-article>


@endsection


Ako môžeme z ukážky View vidieť, metóda addArticle(...) sa stára o odoslanie HTTP POST requestu, ktorý následne spracuje Controller.


Controller

Controller nie je nič iné ako len samostatná trieda (v našom prípade ArticlesController), ktorú môžeme vidieť na nasledujúcej ukážke:


<?php

namespace App\Http\Controllers\Frontend;

...

class ArticlesController extends Controller
{
    protected $articleService;

    public function __construct(ArticleService $articleService)
    {
        $this->articleService = $articleService;
    }
     
    ...

    /**
     * Store a newly created resource in storage.
     *
     * @param StoreArticle $request
     * @return array|RedirectResponse|Redirector
     */
    public function store(StoreArticle $request)
    {
        // Sanitize input
        $sanitized = $request->getSanitized();

        ...
        
        // Store the Article
        $article = Article::create($sanitized);

        ...

        return redirect('/dakujeme');
    }

    ...
}


ArticlesController po prijatí HTTP POST požiadavky na vytvorenie článku túto požiadavku spracuje v metóde store, ktorá najprv zvaliduje dáta (v prípade, že dáta nie sú vo validnom formáte vráti HTTP kód 422) a následne z dát v požiadavke vytvára pomocou zavolania create metódy na triede Modelu nový záznam v databáze. Ak je záznam úspešne vytvorený, používateľa Controller presmeruje na podstránku s poďakovaním.


V tomto článku sme si predstavili návrhový vzor MVC, jeho históriu, technológie, ktoré MVC využívajú, ako aj implementáciu v reálnom projekte. Nič ale nie je lepšie ako prax a preto ti odporúčam nájsť si technológiu v ktorej sa ti bude najlepšie pracovať a skúsiť si vytvoriť vlastný projekt. 


Ak sa ti tento článok páčil, tak si nezabudni prečítať aj ďalšie články na tomto webe a rovnako nás poteší ak tento článok prezdielaš ďalej ľuďom, ktorých zaujíma informatika.


Informatika ku káve - Richard


Zdroje


[1] https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller

[2] https://www.geeksforgeeks.org/mvc-design-pattern/