• Час читання ~3 хв
  • 01.02.2023

Дублювання коду - найболючіше для багатьох розробників, ви думаєте, що вирішили проблему, але є кілька випадків однієї і тієї ж проблеми.

У багатьох кодових базах, які я бачив як розробник Laravel, консольні команди завжди здаються забутою областю або частиною, де людям потрібно приділяти більше уваги якості.

У цьому підручнику я розповім, як ви можете підійти до написання коду з акцентом на зменшення дублювання коду. Для початку позуємо гіпотетичне. У нас є додаток Laravel, який є магазином електронної комерції, і раз на день ми хочемо формувати звіт про всі продажі та статус відправлень. Наш поточний підхід полягає в тому, щоб увійти в панель адміністрування та натиснути кнопку для створення звіту.

Це може бути нереально, оскільки першим випадком тут було б автоматизувати його. Але тримайтеся зі мною лише трохи, коли ми наважуємося на цю ідею, щоб покращити її.

Нашим першим кроком буде створення ремісничої команди або набору ремісничих команд, які будуть генерувати звіти. Коли ми починаємо розглядати звітність, має сенс мати команди, чітко названі для того, чого ми хочемо досягти. Отже, почнемо з показників продажів.

final class SalesFigures extends Command
{
    public $signature = 'reports:sales';

    public $description = 'Run a daily report on sales.';

    public function handle(): int
    {
        $date = now()->subDay();

        $sales = Order::query()
            ->where('status', Status::COMPLETE)
            ->whereBetween(
                'completed_at',
                $date->startOfDay(),
                $date->endOfDay(),
            )->latest()->get();

        // send information through to the report builder
    }
}

Тут у нас є проста команда, що ми зможемо запустити і отримати показники продажів за вчорашній день, які позначені як завершені. Сам запит досить простий. Він перевіряє стан і дату, яка була вчора, потім замовляє їх, тому останнє спочатку - щоб ми могли побудувати хронологічний звіт.

Але як ми можемо це покращити? Чи є інші аспекти програми, де нам потрібно отримати ці замовлення в аналогічному порядку? Приступимо до процесу рефакторінга.

По-перше, цей конкретний запит - це те, що нам потрібно запустити в декількох різних областях. Тож ми можемо перенести це на власний клас, щоб ми могли бігти.

final class ResultsForPeriod implements ResultsForPeriodContract
{
    public function handle(
        Builder $query,
        CarbonInterface $start,
        CarbonInterface $end,
    ): Builder {
        return $builder->whereBetween(
            'completed_at',
            $start,
            $end,
        );
    }
}

Це дозволить нам отримати результати за певний проміжок часу за будь-якими моделями - що більш вигідно для проекту.

final class SalesFigures extends Command
{
    public $signature = 'reports:sales';

    public $description = 'Run a daily report on sales.';

    public function handle(ResultsForPeriodContract $query): int
    {
        $date = now()->subDay();

        $sales = $query->handle(
            query: Order::query()
                ->where('status', Status::COMPLETE),
            start: $date->startOfDay(),
            end: $date->endOfDay()
        )->latest()->get();

        // send information through to the report builder
    }
}

Ми реалізували запит, який ми побудували для фільтрації на основі проміжку часу. Де ще ми можемо взяти це, щоб зробити його чистішим та ефективнішим? Чи могли б ми створити конкретну службу для обробки цього аспекту звітності? Чи корисна ця послуга і в інших сферах?

Наша інформаційна панель електронної комерції, ймовірно, матиме деяку інформацію з цих звітів, тому деяке повторне використання коду вже є. Давайте перенесемо це в сервіс.

final class ReportService implements ReportServiceContract
{
    public function __construct(
        private readonly ResultsForPeriodContract $periodFilter,
    ) {}
    public function dailySales(CarbonInterface $start, CarbonInterface $end): Collection
    {
        return $this->periodFilter->handle(
            query: Order::query()->where('status', Status::COMPLETE),
        )->latest()->get();
    }
}

Тепер ми можемо перенести це назад у ремісниче командування.

final class SalesFigures extends Command
{
    public $signature = 'reports:sales';

    public $description = 'Run a daily report on sales.';

    public function handle(ReportServiceContract $service): int
    {
        $date = now()->subDay();

        $sales = $service->dailySales(
            query: Order::query(),
            start: $date->startOfDay(),
            end: $date->endOfDay()
        );
        // send information through to the report builder
    }
}

Як бачите, у нас є нова чиста команда, яка добре використовує спільний код з іншими областями нашого додатка.

Comments

No comments yet
Yurij Finiv

Yurij Finiv

Full stack

Про мене

Professional Fullstack Developer with extensive experience in website and desktop application development. Proficient in a wide range of tools and technologies, including Bootstrap, Tailwind, HTML5, CSS3, PUG, JavaScript, Alpine.js, jQuery, PHP, MODX, and Node.js. Skilled in website development using Symfony, MODX, and Laravel. Experience: Contributed to the development and translation of MODX3 i...

Про автора CrazyBoy49z
WORK EXPERIENCE
Контакти
Ukraine, Lutsk
+380979856297