4.6 KiB
4.6 KiB
Пример приложения
Код разделен на модули. Позволит проще распараллелить задачи между несколькими разработчиками. Позволит переиспользовать готовые модули в разных проектах.
Модули в папке ./modules Подробней
Тесты в папке ./tests
Запуск тестов:
Все тесты
php artisan test
Только юнит-тесты
php artisan test --testsuite=Unit
Конкретный тест
php artisan test tests/Unit/UserTest.php
С покрытием кода
php artisan test --coverage
В результате получаем
① Контроль над 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— построение SQLTasksStorage— бизнес-логика доступа к данным- DTO — передача данных между слоями
3. Наглядное сравнение
| Критерий | Eloquent | Данный подход |
|---|---|---|
| Производительность | Низкая (N+1, оверхед) | Высокая (оптимизированные запросы) |
| Тестируемость | Сложная | Простая (DI) |
| Контроль SQL | Ограниченный | Полный |
| Поддержка | Легкая для простых проектов | Лучше для сложных систем |
Данный подход — это "прозрачность и контроль", где:
- Каждая операция предсказуема
- Легко оптимизировать под нагрузку
- Архитектура готова к масштабированию