• Время чтения ~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