Анборҳои муфид бо Eloquent?

Ҳафтаи гузашта ман навишта будам мақола дар бораи бефоида будани қолаби Repository барои объектҳои Eloquent, вале у ваъда дод, ки чй тавр ба манфиати худ кисман истифода бурдани онро ба ман накл мекунад. Барои ин ман кӯшиш мекунам таҳлил кунам, ки чӣ гуна ин қолаб одатан дар лоиҳаҳо истифода мешавад. Ҳадди ақали маҷмӯи усулҳои зарурӣ барои анбор:

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

Аммо, дар лоиҳаҳои воқеӣ, агар қарор дода шавад, ки анборҳо истифода шаванд, усулҳои дарёфти сабтҳо ба онҳо илова карда мешаванд:

<?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);
}

Ин усулҳоро метавон тавассути доираи Eloquent амалӣ кард, аммо аз ҳад зиёд бор кардани синфҳои объект бо масъулияти гирифтани худ беҳтарин идея нест ва интиқол додани ин масъулият ба синфҳои репозиторий мантиқӣ ба назар мерасад. Оё чунин аст? Ман ба таври махсус ин интерфейсро ба ду қисм тақсим кардам. Қисми якуми усулҳо дар амалиёти навиштан истифода мешаванд.

Амали стандартии навиштан ин аст:

  • сохтмони объекти нав ва душворй PostRepository :: захира кунед
  • PostRepository::getById, манипуляция ва даъвати объект PostRepository :: захира кунед
  • мушкилот PostRepository :: нест кардан

Амалиётҳои навиштан усулҳои гирифтанро истифода намебаранд. Дар амалиёти хониш танҳо усулҳои get* истифода мешаванд. Агар шумо дар бораи он хонед Принсипи сегрегатсияи интерфейс (мактуб I в SOLID), он гоҳ маълум мешавад, ки интерфейси мо хеле калон аст ва ҳадди аққал ду масъулияти гуногунро иҷро мекунад. Вакти он расидааст, ки онро ба ду таксим кунем. Усул getById дар ҳарду зарур аст, аммо вақте ки барнома мураккабтар мешавад, татбиқи он фарқ мекунад. Мо инро каме дертар мебинем. Ман дар бораи бефоида будани қисми навиштан дар мақолаи қаблӣ навишта будам, бинобар ин дар ин мақола ман онро танҳо фаромӯш мекунам.

Қисми Хондан ба назари ман он қадар бефоида нест, зеро ҳатто барои Eloquent метавонад дар ин ҷо якчанд татбиқ мавҷуд бошад. Синфро чӣ ном бояд кард? Метавонед ReadPostRepository, балки ба шаблон Почтаи электронӣ вай аллакай кам аҳамият дорад. Шумо метавонед танҳо Саволҳои постӣ:

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

Татбиқи он бо Eloquent хеле оддӣ аст:

<?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();
    }
}

Интерфейс бояд бо татбиқ алоқаманд бошад, масалан дар AppServiceProvider:

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

Ин синф аллакай муфид аст. Вай масъулияти худро тавассути озод кардани назоратчиён ё синфи субъект дарк мекунад. Дар контроллер он метавонад чунин истифода шавад:

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

метод PostsController :: LastPosts танҳо барои иҷрои баъзе дархостҳо Паёмҳо ва бо он кор мекунад. Дар провайдер мо пайваст кардем Саволҳои постӣ бо синф EloquentPostQueries ва ин синф ба контроллер иваз карда мешавад.

Биёед тасаввур кунем, ки аризаи мо хеле маъмул шудааст. Ҳазорон корбарон дар як дақиқа саҳифаро бо нашрияҳои охирин мекушоянд. Нашрияҳои маъмултарин низ хеле зуд хонда мешаванд. Пойгоҳҳои додаҳо чунин сарборҳоро чандон хуб идора намекунанд, бинобар ин онҳо ҳалли стандартиро - кэшро истифода мебаранд. Илова ба пойгоҳи додаҳо, тасвири муайяни маълумот дар анборе нигоҳ дошта мешавад, ки барои амалиётҳои муайян оптимизатсия шудааст - ҳифзшуда ё редис.

Мантиқи кэш одатан он қадар мураккаб нест, аммо татбиқи он дар EloquentPostQueries чандон дуруст нест (агар танҳо аз сабаби он Принсипи ягонаи масъулият). Истифодаи қолаб хеле табиӣтар аст Ороишгар ва кэшро ҳамчун ороиши амали асосӣ татбиқ кунед:

<?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();
            });
    }

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

Интерфейсро нодида гиред Почтаи электронӣ дар конструктор. Бо баъзе сабабҳои номаълум, онҳо тасмим гирифтанд, ки интерфейси кэшро дар Laravel ҳамин тавр номбар кунанд.

Синф CachedPostQueries танҳо кэшро амалӣ мекунад. $this->cache->дар хотир доред месанҷад, ки оё ин сабт дар кэш ҳаст ё не, пас занги бозпасро даъват мекунад ва арзиши баргардонидашударо ба кэш менависад. Ҳама чизи боқимонда татбиқи ин синф дар барнома аст. Ба мо ҳама синфҳо лозиманд, ки дар барнома дархости татбиқи интерфейсро талаб кунанд Саволҳои постӣ ба гирифтани мисоли синф шуруъ карданд CachedPostQueries. Бо вуҷуди ин, худи ӯ CachedPostQueries созанда бояд синфро ҳамчун параметр қабул кунад EloquentPostQueriesзеро он бе амалисозии "воқеӣ" кор карда наметавонад. Мо иваз мекунем 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);
    }
}

Ҳама хоҳишҳои ман дар провайдер табиатан тасвир шудаанд. Ҳамин тариқ, мо кэшро барои дархостҳои худ танҳо тавассути навиштани як синф ва тағир додани конфигуратсияи контейнер амалӣ кардем. Қисми боқимондаи коди барнома тағир наёфтааст.

Албатта, барои пурра татбиқ кардани кэш, инчунин бояд беэътиборро татбиқ кард, то мақолаи ҳазфшуда муддате дар сайт овезон нашавад, балки фавран нест карда шавад. Аммо ин чизҳои ночизанд.

Сатри поён: мо на як, балки ду қолабро истифода бурдем. Намуна Ҷудокунии масъулияти фармон (CQRS) пешниҳод мекунад, ки амалиёти хондан ва навиштан дар сатҳи интерфейс комилан ҷудо карда шавад. Ман ба воситаи ӯ назди ӯ омадам Принсипи сегрегатсияи интерфейс, ки ин нишон медиҳад, ки ман намунаҳо ва принсипҳоро моҳирона идора карда, яке аз дигареро ҳамчун теорема ба даст меорам :) Албатта, на ҳар як лоиҳа барои интихоби объектҳо ба чунин абстраксия ниёз дорад, аммо ман ҳилларо бо шумо мубодила мекунам.Дар марҳилаи аввали татбиқ рушд, шумо метавонед танҳо як синф эҷод кунед Саволҳои постӣ бо татбиқи муқаррарӣ тавассути Eloquent:

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

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

Вақте ки зарурати кэш ба миён меояд, бо як ҳаракати оддӣ шумо метавонед дар ҷои ин синф интерфейс (ё синфи абстрактӣ) эҷод кунед. Саволҳои постӣ, татбиқи онро ба синф нусхабардорӣ кунед EloquentPostQueries ва ба схемае, ки дар боло тавсиф карда будам, равед. Қисми боқимондаи коди барнома тағир додан лозим нест.

Ҳамаи ин ҳилаҳо бо синфҳо, интерфейсҳо, Тазриқи вобастагӣ и CQRS дар муфассал тавсиф карда шудааст китоби ман "Архитектураи барномаҳои мураккаби веб". Инчунин як роҳи ҳалли муаммо вуҷуд дорад, ки чаро ҳамаи синфҳои ман дар мисолҳои ин мақола ҳамчун ниҳоӣ қайд карда шудаанд.

Манбаъ: will.com

Илова Эзоҳ