ఎలోక్వెంట్‌తో ఉపయోగకరమైన రిపోజిటరీలు?

గత వారం నేను వ్రాసాను ఎలోక్వెంట్ ఎంటిటీల కోసం రిపోజిటరీ టెంప్లేట్ యొక్క నిరుపయోగం గురించిన కథనం, అయితే, దానిని తన ప్రయోజనం కోసం పాక్షికంగా ఎలా ఉపయోగించాలో చెబుతానని వాగ్దానం చేశాడు. దీన్ని చేయడానికి, ఈ టెంప్లేట్ సాధారణంగా ప్రాజెక్ట్‌లలో ఎలా ఉపయోగించబడుతుందో విశ్లేషించడానికి ప్రయత్నిస్తాను. రిపోజిటరీకి అవసరమైన కనీస పద్ధతుల సెట్:

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

ఈ పద్ధతులను ఎలోక్వెంట్ స్కోప్‌ల ద్వారా అమలు చేయవచ్చు, అయితే తమను తాము పొందే బాధ్యతతో ఎంటిటీ తరగతులను ఓవర్‌లోడ్ చేయడం ఉత్తమం కాదు మరియు ఈ బాధ్యతను రిపోజిటరీ తరగతులకు తరలించడం తార్కికంగా కనిపిస్తుంది. ఇది అలా ఉందా? నేను ప్రత్యేకంగా ఈ ఇంటర్‌ఫేస్‌ను రెండు భాగాలుగా విభజించాను. పద్ధతుల యొక్క మొదటి భాగం వ్రాత కార్యకలాపాలలో ఉపయోగించబడుతుంది.

ప్రామాణిక వ్రాత ఆపరేషన్:

  • కొత్త వస్తువు మరియు సవాలు యొక్క నిర్మాణం పోస్ట్ రిపోజిటరీ :: సేవ్
  • పోస్ట్ రిపోజిటరీ::getById, ఎంటిటీ మానిప్యులేషన్ మరియు సమన్లు పోస్ట్ రిపోజిటరీ :: సేవ్
  • ఒక సవాలు పోస్ట్ రిపోజిటరీ ::తొలగించు

వ్రాత కార్యకలాపాలు పొందే పద్ధతులను ఉపయోగించవు. రీడ్ ఆపరేషన్‌లలో, get* పద్ధతులు మాత్రమే ఉపయోగించబడతాయి. గురించి చదివితే ఇంటర్‌ఫేస్ సెగ్రిగేషన్ ప్రిన్సిపల్ (లేఖ I в సాలిడ్), అప్పుడు మా ఇంటర్‌ఫేస్ చాలా పెద్దదని మరియు కనీసం రెండు వేర్వేరు బాధ్యతలను నిర్వర్తిస్తుందని స్పష్టమవుతుంది. దీన్ని రెండుగా విభజించే సమయం వచ్చింది. పద్ధతి getById రెండింటిలోనూ అవసరం, కానీ అప్లికేషన్ మరింత క్లిష్టంగా మారినప్పుడు, దాని అమలులు భిన్నంగా ఉంటాయి. మేము దీనిని కొంచెం తరువాత చూస్తాము. నేను మునుపటి వ్యాసంలో వ్రాసే భాగం యొక్క నిరుపయోగం గురించి వ్రాసాను, కాబట్టి ఇందులో నేను దాని గురించి మరచిపోతాను.

చదివిన భాగం నాకు అంత పనికిరానిదిగా అనిపిస్తుంది, ఎందుకంటే వాగ్ధాటికి కూడా ఇక్కడ అనేక అమలులు ఉండవచ్చు. తరగతికి ఏమి పేరు పెట్టాలి? చెయ్యవచ్చు ReadPostRepository, కానీ టెంప్లేట్‌కు రిపోజిటరీ అతనికి ఇప్పటికే తక్కువ ఔచిత్యం ఉంది. మీరు కేవలం చేయవచ్చు పోస్ట్ క్వరీస్:

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

ఎలోక్వెంట్‌తో దీన్ని అమలు చేయడం చాలా సులభం:

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

పద్ధతి పోస్ట్‌కంట్రోలర్:: లాస్ట్‌పోస్ట్‌లు కేవలం కొంత అమలు కోసం అడుగుతున్నారు పోస్ట్‌క్వరీస్ మరియు దానితో పని చేస్తుంది. మేము లింక్ చేసిన ప్రొవైడర్‌లో పోస్ట్ క్వరీస్ తరగతితో Eloquent PostQueries మరియు ఈ తరగతి కంట్రోలర్‌లో భర్తీ చేయబడుతుంది.

మా అప్లికేషన్ బాగా ప్రాచుర్యం పొందిందని ఊహించుకుందాం. నిమిషానికి వేలాది మంది వినియోగదారులు తాజా ప్రచురణలతో పేజీని తెరుస్తారు. అత్యంత ప్రజాదరణ పొందిన ప్రచురణలు కూడా చాలా తరచుగా చదవబడతాయి. డేటాబేస్‌లు అటువంటి లోడ్‌లను బాగా నిర్వహించవు, కాబట్టి అవి ప్రామాణిక పరిష్కారాన్ని ఉపయోగిస్తాయి - కాష్. డేటాబేస్‌తో పాటు, నిర్దిష్ట డేటా స్నాప్‌షాట్ నిర్దిష్ట కార్యకలాపాల కోసం ఆప్టిమైజ్ చేయబడిన నిల్వలో నిల్వ చేయబడుతుంది - memcached లేదా redis.

కాషింగ్ లాజిక్ సాధారణంగా అంత క్లిష్టంగా ఉండదు, కానీ దానిని 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();
            });
    }

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

ఇంటర్‌ఫేస్‌ను విస్మరించండి రిపోజిటరీ కన్స్ట్రక్టర్‌లో. కొన్ని తెలియని కారణాల వల్ల, వారు లారావెల్‌లో కాషింగ్ కోసం ఇంటర్‌ఫేస్‌కు ఈ విధంగా పేరు పెట్టాలని నిర్ణయించుకున్నారు.

Класс CachedPostQueries కాషింగ్‌ను మాత్రమే అమలు చేస్తుంది. $this->cache->గుర్తుంచుకోండి ఈ ఎంట్రీ కాష్‌లో ఉందో లేదో తనిఖీ చేస్తుంది మరియు కాకపోతే, కాల్‌బ్యాక్‌కు కాల్ చేసి, తిరిగి వచ్చిన విలువను కాష్‌కి వ్రాస్తుంది. ఈ తరగతిని అప్లికేషన్‌లో అమలు చేయడమే మిగిలి ఉంది. ఇంటర్‌ఫేస్ అమలును అభ్యర్థించడానికి అప్లికేషన్‌లోని అన్ని తరగతులు మాకు అవసరం పోస్ట్ క్వరీస్ తరగతి యొక్క ఉదాహరణను స్వీకరించడం ప్రారంభించింది CachedPostQueries. అయితే, అతనే CachedPostQueries కన్స్ట్రక్టర్ తప్పనిసరిగా తరగతిని పారామీటర్‌గా స్వీకరించాలి Eloquent PostQueriesఎందుకంటే ఇది "నిజమైన" అమలు లేకుండా పనిచేయదు. మేము మారుతాము 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) ఇంటర్‌ఫేస్ స్థాయిలో రీడ్ మరియు రైట్ ఆపరేషన్‌లను పూర్తిగా వేరు చేయాలని ప్రతిపాదిస్తుంది. నేను అతని వద్దకు వచ్చాను ఇంటర్‌ఫేస్ సెగ్రిగేషన్ ప్రిన్సిపల్, ఇది నేను నైపుణ్యంగా నమూనాలు మరియు సూత్రాలను తారుమారు చేసి, ఒకదాని నుండి ఒకదాని నుండి ఒక సిద్ధాంతం వలె తారుమారు చేయాలని సూచించింది :) వాస్తవానికి, ప్రతి ప్రాజెక్ట్‌కు ఎంటిటీలను ఎంచుకోవడానికి అటువంటి సంగ్రహణ అవసరం లేదు, కానీ నేను మీతో ట్రిక్‌ను పంచుకుంటాను. అప్లికేషన్ యొక్క ప్రారంభ దశలో అభివృద్ధి, మీరు కేవలం ఒక తరగతి సృష్టించవచ్చు పోస్ట్ క్వరీస్ ఎలోక్వెంట్ ద్వారా సాధారణ అమలుతో:

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

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

కాషింగ్ అవసరం ఏర్పడినప్పుడు, ఒక సాధారణ తరలింపుతో మీరు ఈ తరగతి స్థానంలో ఇంటర్‌ఫేస్ (లేదా అబ్‌స్ట్రాక్ట్ క్లాస్)ని సృష్టించవచ్చు పోస్ట్ క్వరీస్, దాని అమలును తరగతికి కాపీ చేయండి Eloquent PostQueries మరియు నేను ముందుగా వివరించిన పథకానికి వెళ్లండి. మిగిలిన అప్లికేషన్ కోడ్‌ని మార్చాల్సిన అవసరం లేదు.

తరగతులు, ఇంటర్‌ఫేస్‌లతో ఈ అన్ని ఉపాయాలు, డిపెండెన్సీ ఇంజెక్షన్ и CQRS లో వివరంగా వివరించబడింది నా పుస్తకం “ఆర్కిటెక్చర్ ఆఫ్ కాంప్లెక్స్ వెబ్ అప్లికేషన్స్”. ఈ కథనం యొక్క ఉదాహరణలలో నా అన్ని తరగతులు ఎందుకు ఫైనల్‌గా గుర్తించబడ్డాయి అనే చిక్కుకు పరిష్కారం కూడా ఉంది.

మూలం: www.habr.com

ఒక వ్యాఖ్యను జోడించండి