### **Пример приложения** В данном примере веб-интерфейс отсутствует, функционал можно протестить юнит-тестами. Тесты в папке ``./tests`` ### **Запуск тестов:** Все тесты ``php artisan test`` Только юнит-тесты ``php artisan test --testsuite=Unit`` Конкретный тест ``php artisan test tests/Unit/UserTest.php`` С покрытием кода ``php artisan test --coverage`` ### **Модули приложения** Код разделен на модули. Позволит проще распараллелить задачи между несколькими разработчиками. Позволит переиспользовать готовые модули в разных проектах. Модули в папке ``./modules`` [Подробней](./modules/Readme.md) ### **В результате получаем** #### **① Контроль над SQL-запросами** **Проблема Eloquent:** - Генерирует сложные SQL, которые трудно оптимизировать - N+1 проблема (ленивая загрузка отношений) **Решение:** ```php public function getList(int $limit, int $offset, array $dsl = []): array { $data = $this->tasksQuery->select($dsl)->limit($limit, $offset)->all(); // ... } ``` **Преимущества:** - Явный контроль над запросами через `TasksQuery` - Четкое разделение на простые запросы (`select()`, `limit()`) - Нет "магии", которую трудно дебажить --- #### **② Производительность** **Проблема Eloquent:** - Гибертность моделей (каждая сущность — объект с оверхедом) - Проблемы с большими выборками **Решение:** ```php 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`) **Решение:** ```php public function setTasksQuery(TasksQuery $query): void { $this->tasksQuery = $query; // Легко подменить mock-объектом } ``` **Преимущества:** - Чистые зависимости (интерфейсы или конкретные классы) - Проще писать unit-тесты --- #### **④ Гибкость архитектуры** **Проблема Eloquent:** - Жесткая привязка к ActiveRecord - Сложно разделить на слои (логика в моделях) **Ваше решение:** ```php class TasksStorage { // Слой хранилища private TasksQuery $tasksQuery; // Отдельный класс для запросов private OtherQuery $otherQuery; // Отдельный класс для связей } ``` **Преимущества:** - Четкое разделение: - `TasksQuery` — построение SQL - `TasksStorage` — бизнес-логика доступа к данным - DTO — передача данных между слоями --- ### **3. Наглядное сравнение** | Критерий | Eloquent | Данный подход | |-------------------|-------------------|-------------------| | Производительность | Низкая (N+1, оверхед) | Высокая (оптимизированные запросы) | | Тестируемость | Сложная | Простая (DI) | | Контроль SQL | Ограниченный | Полный | | Поддержка | Легкая для простых проектов | Лучше для сложных систем | --- **Данный подход — это "прозрачность и контроль", где:** - Каждая операция предсказуема - Легко оптимизировать под нагрузку - Архитектура готова к масштабированию