Ответ
Луковая архитектура (Onion Architecture) — это шаблон архитектурного проектирования, направленный на создание гибких, тестируемых и независимых от внешних факторов приложений. Главная идея — направление всех зависимостей к центру.
В основе лежит принцип инверсии зависимостей (Dependency Inversion Principle). Внешние слои зависят от внутренних, но не наоборот. Это достигается за счет использования интерфейсов во внутренних слоях, которые реализуются во внешних.
Основные слои (от центра к периферии):
- Доменный слой (Domain Layer): Ядро приложения. Содержит доменные модели (сущности) и бизнес-логику, которая не зависит ни от чего другого. Это самая изолированная часть.
- Слой приложения (Application Layer): Оркестрирует доменную логику. Содержит сценарии использования (use cases), которые реализуют конкретные бизнес-процессы. Определяет интерфейсы для внешних зависимостей (например, репозиториев).
- Слой инфраструктуры (Infrastructure Layer): Содержит реализации интерфейсов, определенных в слое приложения. Это могут быть базы данных, файловые системы, клиенты для внешних API и т.д.
- Слой представления (UI/API Layer): Точка входа в приложение. Это может быть REST API, gRPC сервер, веб-интерфейс или CLI. Этот слой преобразует внешние запросы в вызовы слоя приложения.
Пример на Go:
// 1. Доменный слой (не зависит ни от чего)
package domain
type User struct {
ID int
Name string
}
// 2. Слой приложения (определяет интерфейс, зависит от домена)
package application
import "my-app/domain"
// UserRepository - это порт, который должен быть реализован во внешнем слое
type UserRepository interface {
FindByID(id int) (*domain.User, error)
}
// 3. Слой инфраструктуры (реализует интерфейс, зависит от домена)
package infrastructure
import (
"database/sql"
"my-app/domain"
)
type PostgreSQLUserRepo struct {
db *sql.DB
}
// FindByID реализует интерфейс UserRepository
func (r *PostgreSQLUserRepo) FindByID(id int) (*domain.User, error) {
// ... логика запроса к PostgreSQL
return nil, nil
}
Преимущества:
- Высокая тестируемость: Легко подменять реализации (например, БД) на моки в тестах.
- Гибкость: Можно заменить базу данных или фреймворк API, не затрагивая бизнес-логику.
- Изоляция бизнес-правил: Ядро системы защищено от изменений в инфраструктуре.
Недостатки:
- Сложность: Может быть избыточной для небольших CRUD-приложений.
- Больше кода: Требует создания множества интерфейсов и слоев, что увеличивает объем кода.