Шарова архітектура ділить застосунок на горизонтальні шари з різною відповідальністю. Кожен шар залежить лише від шару під ним.
Класичні три шари:
- представлення (presentation) - взаємодія з користувачем чи клієнтом: контролери, шаблони, Livewire-компоненти, ресурси API, консольні команди;
- домен (бізнес-логіка) - правила предметної області: розрахунок ціни, перевірка, чи можна скасувати замовлення, нарахування знижок;
- дані (data) - збереження й отримання даних: запити до бази, сторонні API, файлове сховище.
Часто між представленням і доменом виділяють ще шар застосунку (application/service layer) - сценарії використання: «оформити замовлення» координує доменну логіку, транзакцію, відправку листа.
Навіщо:
- зрозуміло, де що шукати - бізнес-правило не розкидане по контролерах і шаблонах;
- зміни локалізовані - новий формат API змінює шар представлення, а не бізнес-логіку;
- повторне використання - той самий сценарій викликається з контролера, команди й джоби;
- тестування - бізнес-логіку можна перевірити без HTTP.
У Laravel це виглядає приблизно так:
Http/Controllers, Livewire, Console ← представлення
Actions / Services ← сценарії
Models (+ доменні класи, Enums) ← домен і дані разом (Active Record)
Eloquent за патерном Active Record поєднує доменний об'єкт і доступ до даних - шари «домен» і «дані» тут свідомо злиті заради простоти.
Типові помилки:
- «товстий контролер» - уся логіка в контролері, неможливо використати з команди чи протестувати окремо;
- «анемічні шари» - сервіс, що лише викликає репозиторій, який лише викликає модель, - шари без змісту;
- залежності не в той бік - модель викликає контролер чи шаблон.
Мартін Фаулер радить на рівні великої системи ділити спершу за предметними областями (замовлення, каталог, оплата), а шари - всередині кожної: інакше кожна зміна фічі зачіпає всі шари всього застосунку одночасно.
Докладніше в документації: Martin Fowler: Presentation Domain Data Layering