فصاحت کے ساتھ مفید ذخیرہ؟

پچھلے ہفتے میں نے لکھا تھا۔ فصیح اداروں کے لیے ریپوزٹری ٹیمپلیٹ کے بیکار ہونے کے بارے میں مضمونتاہم، اس نے مجھے یہ بتانے کا وعدہ کیا کہ اسے اپنے فائدے کے لیے جزوی طور پر کیسے استعمال کیا جائے۔ ایسا کرنے کے لیے، میں یہ تجزیہ کرنے کی کوشش کروں گا کہ اس ٹیمپلیٹ کو عام طور پر پروجیکٹس میں کس طرح استعمال کیا جاتا ہے۔ ریپوزٹری کے لیے طریقوں کا کم از کم مطلوبہ سیٹ:

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

ان طریقوں کو فصیح اسکوپس کے ذریعے لاگو کیا جا سکتا ہے، لیکن خود کو لانے کی ذمہ داری کے ساتھ ہستی کی کلاسوں کو اوورلوڈنگ کرنا بہترین خیال نہیں ہے، اور اس ذمہ داری کو ریپوزٹری کلاسز میں منتقل کرنا منطقی لگتا ہے۔ کیا ایسا ہے؟ میں نے بصری طور پر اس انٹرفیس کو دو حصوں میں تقسیم کیا۔ طریقوں کا پہلا حصہ تحریری کارروائیوں میں استعمال کیا جائے گا۔

معیاری تحریری عمل ہے:

  • ایک نئی چیز اور چیلنج کی تعمیر پوسٹ ریپوزٹری :: محفوظ کریں۔
  • PostRepository::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();
    }
}

انٹرفیس کا نفاذ کے ساتھ منسلک ہونا ضروری ہے، مثال کے طور پر in 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(),
        ]);
    }
} 

طریقہ۔ پوسٹس کنٹرولر::آخری پوسٹس صرف کچھ عمل درآمد کے لیے کہہ رہے ہیں۔ پوسٹس سوالات اور اس کے ساتھ کام کرتا ہے. فراہم کنندہ میں ہم نے لنک کیا ہے۔ پوسٹ سوالات کلاس کے ساتھ EloquentPostQuerys اور اس کلاس کو کنٹرولر میں بدل دیا جائے گا۔

آئیے تصور کریں کہ ہماری ایپلی کیشن بہت مشہور ہوگئی ہے۔ فی منٹ ہزاروں صارفین تازہ ترین اشاعتوں کے ساتھ صفحہ کھولتے ہیں۔ مقبول ترین اشاعتیں بھی اکثر پڑھی جاتی ہیں۔ ڈیٹا بیس اس طرح کے بوجھ کو بہت اچھی طرح سے نہیں سنبھالتے ہیں، لہذا وہ ایک معیاری حل استعمال کرتے ہیں - ایک کیش۔ ڈیٹا بیس کے علاوہ، ایک مخصوص ڈیٹا اسنیپ شاٹ کو مخصوص آپریشنز کے لیے موزوں اسٹوریج میں محفوظ کیا جاتا ہے۔ memcached یا دوبارہ.

کیشنگ منطق عام طور پر اتنا پیچیدہ نہیں ہوتا ہے، لیکن اسے 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 میں کیشنگ کے لیے انٹرفیس کا نام اس طرح رکھنے کا فیصلہ کیا۔

طبقے کے کیشڈ پوسٹ سوالات صرف کیشنگ کو لاگو کرتا ہے۔ $this->cache->یاد رکھیں چیک کرتا ہے کہ آیا یہ اندراج کیشے میں ہے اور اگر نہیں، تو کال بیک کال کرتا ہے اور واپس کی گئی قدر کو کیشے میں لکھتا ہے۔ اس کلاس کو ایپلی کیشن میں لاگو کرنا باقی ہے۔ ہمیں ان تمام کلاسوں کی ضرورت ہے جو درخواست میں انٹرفیس کے نفاذ کی درخواست کریں۔ پوسٹ سوالات کلاس کی ایک مثال موصول ہونا شروع ہوئی۔ کیشڈ پوسٹ سوالات. تاہم، وہ خود کیشڈ پوسٹ سوالات کنسٹرکٹر کو پیرامیٹر کے طور پر ایک کلاس وصول کرنا ضروری ہے۔ EloquentPostQuerysچونکہ یہ "حقیقی" نفاذ کے بغیر کام نہیں کرسکتا۔ ہم بدلتے ہیں۔ 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);
    }

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

جب کیشنگ کی ضرورت پیش آتی ہے، تو ایک سادہ اقدام سے آپ اس کلاس کی جگہ ایک انٹرفیس (یا خلاصہ کلاس) بنا سکتے ہیں۔ پوسٹ سوالات، اس کے نفاذ کو کلاس میں کاپی کریں۔ EloquentPostQuerys اور اسکیم پر جائیں جو میں نے پہلے بیان کیا تھا۔ باقی ایپلیکیشن کوڈ کو تبدیل کرنے کی ضرورت نہیں ہے۔

کلاسز، انٹرفیس کے ساتھ یہ تمام چالیں انحصار انجکشن и CQRS میں تفصیل سے بیان کیا گیا ہے۔ میری کتاب "آرکیٹیکچر آف کمپلیکس ویب ایپلی کیشنز". اس پہیلی کا ایک حل بھی ہے کہ اس مضمون کی مثالوں میں میری تمام کلاسز کو حتمی کیوں قرار دیا گیا ہے۔

ماخذ: www.habr.com

نیا تبصرہ شامل کریں