exampleapp/README.md

4.8 KiB
Raw Blame History

Пример приложения

В данном примере веб-интерфейс отсутствует, функционал можно протестить юнит-тестами.

Тесты в папке ./tests

Запуск тестов:

Все тесты

php artisan test

Только юнит-тесты

php artisan test --testsuite=Unit

Конкретный тест

php artisan test tests/Unit/UserTest.php

С покрытием кода

php artisan test --coverage

Модули приложения

Код разделен на модули. Позволит проще распараллелить задачи между несколькими разработчиками. Позволит переиспользовать готовые модули в разных проектах.

Модули в папке ./modules Подробней

В результате получаем

① Контроль над SQL-запросами

Проблема Eloquent:

  • Генерирует сложные SQL, которые трудно оптимизировать
  • N+1 проблема (ленивая загрузка отношений)

Решение:

public function getList(int $limit, int $offset, array $dsl = []): array 
{
    $data = $this->tasksQuery->select($dsl)->limit($limit, $offset)->all();
    // ...
}

Преимущества:

  • Явный контроль над запросами через TasksQuery
  • Четкое разделение на простые запросы (select(), limit())
  • Нет "магии", которую трудно дебажить

② Производительность

Проблема Eloquent:

  • Гибертность моделей (каждая сущность — объект с оверхедом)
  • Проблемы с большими выборками

Решение:

private function receiveAdditionalData(array &$data, array $dsl): void
{
    if (in_array('options', $dsl)) {
        $tasksIds = $this->pluck('id', $data);
        $otherData = $this->otherQuery->getForTasks($tasksIds); // Один запрос для всех задач
        // ...
    }
}

Преимущества:

  • Работа с массивами вместо объектов (меньше потребление памяти)
  • Явная загрузка связанных данных за 1 запрос (не N+1)

③ Тестируемость

Проблема Eloquent:

  • Трудно мокировать (глобальные scope, трейты)
  • Зависимость от статики (DB::shouldReceive)

Решение:

public function setTasksQuery(TasksQuery $query): void {
    $this->tasksQuery = $query; // Легко подменить mock-объектом
}

Преимущества:

  • Чистые зависимости (интерфейсы или конкретные классы)
  • Проще писать unit-тесты

④ Гибкость архитектуры

Проблема Eloquent:

  • Жесткая привязка к ActiveRecord
  • Сложно разделить на слои (логика в моделях)

Ваше решение:

class TasksStorage {
    // Слой хранилища
    private TasksQuery $tasksQuery; // Отдельный класс для запросов
    private OtherQuery $otherQuery; // Отдельный класс для связей
}

Преимущества:

  • Четкое разделение:
    • TasksQuery — построение SQL
    • TasksStorage — бизнес-логика доступа к данным
    • DTO — передача данных между слоями

3. Наглядное сравнение

Критерий Eloquent Данный подход
Производительность Низкая (N+1, оверхед) Высокая (оптимизированные запросы)
Тестируемость Сложная Простая (DI)
Контроль SQL Ограниченный Полный
Поддержка Легкая для простых проектов Лучше для сложных систем

Данный подход — это "прозрачность и контроль", где:

  • Каждая операция предсказуема
  • Легко оптимизировать под нагрузку
  • Архитектура готова к масштабированию