Repożitorji utli b'Eloquent?

Il-ġimgħa li għaddiet ktibt artiklu dwar l-inutilità tal-mudell tar-Repożitorju għal entitajiet Elokwenti, madankollu, huwa wiegħed li jgħidli kif parzjalment tużah għall-vantaġġ tiegħu. Biex tagħmel dan, ser nipprova tanalizza kif dan il-mudell normalment jintuża fi proġetti. Is-sett minimu meħtieġ ta' metodi għal repożitorju:

<?php
interface PostRepository
{
    public function getById($id): Post;
    public function save(Post $post);
    public function delete($id);
}

Madankollu, fi proġetti reali, jekk ġie deċiż li jintużaw repożitorji, ħafna drabi jiżdiedu magħhom metodi għall-irkupru tar-rekords:

<?php
interface PostRepository
{
    public function getById($id): Post;
    public function save(Post $post);
    public function delete($id);

    public function getLastPosts();
    public function getTopPosts();
    public function getUserPosts($userId);
}

Dawn il-metodi jistgħu jiġu implimentati permezz ta' ambiti Eloquent, iżda tagħbija żejda ta' klassijiet ta' entitajiet bir-responsabbiltà li jġibu lilhom infushom mhix l-aħjar idea, u li din ir-responsabbiltà titmexxa għal klassijiet ta' repożitorju tidher loġika. Huwa hekk? I speċifikament viżwalment maqsuma din l-interface f'żewġ partijiet. L-ewwel parti tal-metodi se tintuża f'operazzjonijiet ta 'kitba.

L-operazzjoni standard tal-kitba hija:

  • kostruzzjoni ta 'oġġett ġdid u sfida PostRepository::salva
  • PostRepository::getById, manipulazzjoni ta’ entità u taħrika PostRepository::salva
  • sfida PostRepository::ħassar

L-operazzjonijiet tal-kitba ma jużawx metodi fetch. F'operazzjonijiet ta' qari, jintużaw biss metodi get*. Jekk taqra dwar Prinċipju tas-Segregazzjoni tal-Interface (ittra I в SOLIDU), allura jkun ċar li l-interface tagħna hija kbira wisq u twettaq mill-inqas żewġ responsabbiltajiet differenti. Wasal iż-żmien li taqsamha bi tnejn. Metodu getById huwa meħtieġ fit-tnejn, iżda hekk kif l-applikazzjoni ssir aktar kumplessa, l-implimentazzjonijiet tagħha se jkunu differenti. Dan se narawh ftit aktar tard. Ktibt dwar l-inutilità tal-parti tal-kitba f'artiklu preċedenti, għalhekk f'dan wieħed sempliċiment se ninsa dwarha.

Il-parti Aqra jidhirli mhux daqshekk inutli, peress li anke għal Eloquent jista 'jkun hemm diversi implimentazzjonijiet hawn. Xi isem il-klassi? Can ReadPostRepository, iżda għall-mudell Repożitorju hu diġà għandu ftit rilevanza. Tista 'biss PostQueries:

<?php
interface PostQueries
{
    public function getById($id): Post;
    public function getLastPosts();
    public function getTopPosts();
    public function getUserPosts($userId);
}

L-implimentazzjoni tagħha b'Eloquent hija pjuttost sempliċi:

<?php
final class EloquentPostQueries implements PostQueries
{
    public function getById($id): Post
    {
        return Post::findOrFail($id);
    }

    /**
    * @return Post[] | Collection
    */
    public function getLastPosts()
    {
        return Post::orderBy('created_at', 'desc')
            ->limit(/*some limit*/)
            ->get();
    }
    /**
    * @return Post[] | Collection
    */
    public function getTopPosts()
    {
        return Post::orderBy('rating', 'desc')
            ->limit(/*some limit*/)
            ->get();
    }

    /**
    * @param int $userId
    * @return Post[] | Collection
    */
    public function getUserPosts($userId)
    {
        return Post::whereUserId($userId)
            ->orderBy('created_at', 'desc')
            ->get();
    }
}

L-interface trid tkun assoċjata mal-implimentazzjoni, pereżempju fi AppServiceProvider:

<?php
final class AppServiceProvider extends ServiceProvider 
{
    public function register()
    {
        $this->app->bind(PostQueries::class, 
            EloquentPostQueries::class);
    }
}

Din il-klassi diġà hija utli. Huwa jirrealizza r-responsabbiltà tiegħu billi jeħles jew lill-kontrolluri jew lill-klassi tal-entità. F'kontrollur jista' jintuża bħal dan:

<?php
final class PostsController extends Controller
{
    public function lastPosts(PostQueries $postQueries)
    {
        return view('posts.last', [
            'posts' => $postQueries->getLastPosts(),
        ]);
    }
} 

Metodu PostsController::lastPosts titlob biss għal xi implimentazzjoni PostsQueries u jaħdem magħha. Fil-fornitur aħna konnessi PostQueries mal-klassi EloquentPostQueries u din il-klassi tiġi sostitwita fil-kontrollur.

Ejja nimmaġinaw li l-applikazzjoni tagħna saret popolari ħafna. Eluf ta’ utenti kull minuta jiftħu l-paġna bl-aħħar pubblikazzjonijiet. L-aktar pubblikazzjonijiet popolari jinqraw ukoll ħafna drabi. Databases ma jimmaniġġjawx tali tagħbijiet tajjeb ħafna, għalhekk jużaw soluzzjoni standard - cache. Minbarra d-database, ċertu snapshot tad-dejta hija maħżuna f'ħażna ottimizzata għal ċerti operazzjonijiet - memcached jew erġa ngħidu.

Il-loġika tal-caching normalment mhix daqshekk ikkumplikata, iżda l-implimentazzjoni tagħha f'EloquentPostQueries mhix korretta ħafna (jekk biss għax Prinċipju ta 'Responsabbiltà Unika). Huwa ħafna aktar naturali li tuża mudell Dekoratur u timplimenta l-caching bħala dekorazzjoni għall-azzjoni prinċipali:

<?php
use IlluminateContractsCacheRepository;

final class CachedPostQueries implements PostQueries
{
    const LASTS_DURATION = 10;

    /** @var PostQueries */
    private $base;

    /** @var Repository */
    private $cache;

    public function __construct(
        PostQueries $base, Repository $cache) 
    {
        $this->base = $base;
        $this->cache = $cache;
    }

    /**
    * @return Post[] | Collection
    */
    public function getLastPosts()
    {
        return $this->cache->remember('last_posts', 
            self::LASTS_DURATION, 
            function(){
                return $this->base->getLastPosts();
            });
    }

    // другие методы практически такие же
}

Injora l-interface Repożitorju fil-kostruttur. Għal xi raġuni mhux magħrufa, huma ddeċidew li jsemmu l-interface għall-caching f'Laravel b'dan il-mod.

Klassi CachedPostQueries jimplimenta l-caching biss. $dan->cache->ftakar jiċċekkja jekk din id-dħul hijiex fil-cache u jekk le, imbagħad isejjaħ lura u jikteb il-valur lura fil-cache. Li jibqa 'huwa li timplimenta din il-klassi fl-applikazzjoni. Għandna bżonn il-klassijiet kollha li fl-applikazzjoni biex jitolbu implimentazzjoni tal-interface PostQueries beda jirċievi istanza tal-klassi CachedPostQueries. Madankollu, hu stess CachedPostQueries il-kostruttur għandu jirċievi klassi bħala parametru EloquentPostQueriesperess li ma jistax jaħdem mingħajr implimentazzjoni "reali". Nibdlu AppServiceProvider:

<?php
final class AppServiceProvider extends ServiceProvider 
{
    public function register()
    {
        $this->app->bind(PostQueries::class, 
            CachedPostQueries::class);

        $this->app->when(CachedPostQueries::class)
            ->needs(PostQueries::class)
            ->give(EloquentPostQueries::class);
    }
}

Ix-xewqat kollha tiegħi huma deskritti b'mod pjuttost naturali fil-fornitur. Għalhekk, implimentajna l-caching għat-talbiet tagħna biss billi ktibna klassi waħda u nbiddlu l-konfigurazzjoni tal-kontenitur. Il-bqija tal-kodiċi tal-applikazzjoni ma nbidilx.

Naturalment, biex timplimenta bis-sħiħ il-caching, huwa wkoll meħtieġ li tiġi implimentata l-invalidazzjoni sabiex l-artikolu mħassar ma jibqax fuq is-sit għal xi żmien, iżda jitħassar immedjatament. Iżda dawn huma affarijiet minuri.

Bottom line: użajna mhux wieħed, iżda żewġ mudelli. Kampjun Kmand Query Responsabbiltà Segregazzjoni (CQRS) jipproponi li l-operazzjonijiet tal-qari u tal-kitba jiġu separati kompletament fil-livell tal-interface. Wasalt għandu permezz Prinċipju tas-Segregazzjoni tal-Interface, li jissuġġerixxi li jien jimmanipula xejriet u prinċipji b'sengħa u nikseb wieħed mill-ieħor bħala teorema :) Naturalment, mhux kull proġett jeħtieġ astrazzjoni bħal din għall-għażla ta 'entitajiet, iżda se naqsam il-trick miegħek. Fl-istadju inizjali tal-applikazzjoni iżvilupp, tista 'sempliċement toħloq klassi PostQueries bl-implimentazzjoni tas-soltu permezz ta' Eloquent:

<?php
final class PostQueries
{
    public function getById($id): Post
    {
        return Post::findOrFail($id);
    }

    // другие методы
}

Meta tqum il-ħtieġa għall-caching, b'ċaqliq sempliċi tista' toħloq interface (jew klassi astratta) minflok din il-klassi PostQueries, kopja l-implimentazzjoni tagħha fil-klassi EloquentPostQueries u mur fl-iskema li ddeskriviet qabel. Il-bqija tal-kodiċi tal-applikazzjoni m'għandux għalfejn jinbidel.

Dawn it-tricks kollha bi klassijiet, interfaces, Injezzjoni ta 'Dipendenza и CQRS deskritt fid-dettall fi il-ktieb tiegħi "Arkitettura ta' Applikazzjonijiet tal-Web Kumpless". Hemm ukoll soluzzjoni għall-riddle għaliex il-klassijiet kollha tiegħi fl-eżempji għal dan l-artikolu huma mmarkati bħala finali.

Sors: www.habr.com

Żid kumment