Hazina muhimu zilizo na Fasaha?

Wiki iliyopita niliandika makala kuhusu ubatili wa kiolezo cha Hifadhi kwa vyombo vya Fasaha, hata hivyo, aliahidi kuniambia jinsi ya kuitumia kwa manufaa yake. Ili kufanya hivyo, nitajaribu kuchambua jinsi template hii kawaida hutumiwa katika miradi. Seti ya chini inayohitajika ya njia za hazina:

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

Walakini, katika miradi halisi, ikiwa iliamuliwa kutumia hazina, njia za kupata rekodi mara nyingi huongezwa kwao:

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

Mbinu hizi zinaweza kutekelezwa kupitia mawanda Fasaha, lakini kupakia madarasa ya huluki kupita kiasi na jukumu la kujileta sio wazo bora, na kuhamisha jukumu hili kwa madarasa ya hazina inaonekana kuwa sawa. Je, ni hivyo? Kwa kuibua niligawanya interface hii katika sehemu mbili. Sehemu ya kwanza ya njia zitatumika katika shughuli za uandishi.

Operesheni ya kawaida ya uandishi ni:

  • ujenzi wa kitu kipya na changamoto Hifadhi ya Posta::hifadhi
  • PostRepository::getById, ghiliba na wito wa chombo Hifadhi ya Posta::hifadhi
  • changamoto PostRepository::futa

Andika shughuli usitumie njia za kuleta. Katika shughuli za kusoma, njia za kupata* pekee ndizo zinazotumiwa. Ikiwa unasoma kuhusu Kanuni ya Kutenganisha Kiolesura (barua I Π² MANGO), basi itakuwa wazi kuwa kiolesura chetu ni kikubwa sana na hufanya angalau majukumu mawili tofauti. Ni wakati wa kuigawanya kwa mbili. Njia getById ni muhimu katika zote mbili, lakini kadiri programu inavyozidi kuwa ngumu, utekelezaji wake utatofautiana. Tutaona hii baadaye kidogo. Niliandika juu ya ubatili wa sehemu ya uandishi katika nakala iliyopita, kwa hivyo katika hii nitasahau tu juu yake.

Sehemu ya Soma inaonekana kwangu sio bure, kwani hata kwa Ufasaha kunaweza kuwa na utekelezaji kadhaa hapa. Nini cha kutaja darasa? Unaweza ReadPostRepository, lakini kwa kiolezo Repository tayari ana umuhimu kidogo. Unaweza tu PostQueries:

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

Kuitekeleza kwa Ufasaha ni rahisi sana:

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

Interface lazima ihusishwe na utekelezaji, kwa mfano katika AppServiceProvider:

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

Darasa hili tayari ni muhimu. Anatambua wajibu wake kwa kuwaondolea wadhibiti au tabaka la chombo. Katika mtawala inaweza kutumika kama hii:

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

Mbinu PostsController::lastPosts kuuliza tu utekelezaji fulani Maswali ya Machapisho na inafanya kazi nayo. Katika mtoaji tuliunganisha PostQueries na darasa EloquentPostQueries na darasa hili litabadilishwa kuwa kidhibiti.

Hebu fikiria kwamba maombi yetu yamekuwa maarufu sana. Maelfu ya watumiaji kwa dakika hufungua ukurasa na machapisho mapya. Machapisho maarufu zaidi pia yanasomwa mara nyingi sana. Hifadhidata hazishughulikia mizigo kama hiyo vizuri, kwa hivyo hutumia suluhisho la kawaida - cache. Kwa kuongezea hifadhidata, picha fulani ya data huhifadhiwa kwenye uhifadhi ulioboreshwa kwa shughuli fulani - imechapwa au redis.

Mantiki ya kuweka akiba kawaida sio ngumu sana, lakini kuitekeleza katika EloquentPostQueries sio sahihi sana (ikiwa ni kwa sababu tu Kanuni ya Uwajibikaji Moja) Ni kawaida zaidi kutumia kiolezo Mpambaji na utekeleze caching kama mapambo kwa hatua kuu:

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

    // Π΄Ρ€ΡƒΠ³ΠΈΠ΅ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ практичСски Ρ‚Π°ΠΊΠΈΠ΅ ΠΆΠ΅
}

Puuza kiolesura Repository katika mjenzi. Kwa sababu zisizojulikana, waliamua kutaja kiolesura cha caching katika Laravel kwa njia hii.

Hatari CachedPostQueries huweka akiba pekee. $this->cache->kumbuka hukagua kama ingizo hili liko kwenye akiba na ikiwa sivyo, basi piga simu tena na kuandika thamani iliyorejeshwa kwenye kache. Kilichobaki ni kutekeleza darasa hili kwenye programu. Tunahitaji madarasa yote ambayo katika programu ili kuomba utekelezaji wa kiolesura PostQueries alianza kupokea mfano wa darasa CachedPostQueries. Walakini, yeye mwenyewe CachedPostQueries mjenzi lazima apokee darasa kama kigezo EloquentPostQuerieskwani haiwezi kufanya kazi bila utekelezaji "halisi". Tunabadilika 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);
    }
}

Matakwa yangu yote yameelezewa kwa kawaida katika mtoaji. Kwa hivyo, tulitekeleza caching kwa maombi yetu tu kwa kuandika darasa moja na kubadilisha usanidi wa chombo. Msimbo uliosalia wa programu haujabadilika.

Bila shaka, ili kutekeleza kikamilifu caching, ni muhimu pia kutekeleza ubatilifu ili makala iliyofutwa haina hutegemea kwenye tovuti kwa muda fulani, lakini inafutwa mara moja. Lakini haya ni mambo madogo.

Mstari wa chini: hatukutumia moja, lakini templates mbili. Sampuli Kutenganisha Wajibu wa Swali la Amri (CQRS) inapendekeza kutenganisha kabisa shughuli za kusoma na kuandika katika kiwango cha kiolesura. Nilikuja kwake kupitia Kanuni ya Kutenganisha Kiolesura. maendeleo, unaweza kuunda darasa tu PostQueries na utekelezaji wa kawaida kupitia Eloquent:

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

    // Π΄Ρ€ΡƒΠ³ΠΈΠ΅ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹
}

Wakati hitaji la caching linatokea, kwa hoja rahisi unaweza kuunda kiolesura (au darasa la kufikirika) badala ya darasa hili. PostQueries, nakili utekelezaji wake kwa darasa EloquentPostQueries na nenda kwa mpango nilioelezea hapo awali. Nambari iliyobaki ya programu haihitaji kubadilishwa.

Ujanja huu wote na madarasa, miingiliano, Sindano ya Kutegemea ΠΈ CQRS ilivyoelezwa kwa kina katika kitabu changu "Usanifu wa Maombi Magumu ya Wavuti". Pia kuna suluhisho la kitendawili kwa nini madarasa yangu yote katika mifano ya nakala hii yamewekwa alama kama ya mwisho.

Chanzo: mapenzi.com

Kuongeza maoni