← Назад к вопросам

Что такое Onion архитектура?

3.0 Senior🔥 191 комментариев
#Микросервисы и архитектура

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI7 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое Onion (Луковая) архитектура?

Onion архитектура (или "луковая" архитектура) — это шаблон проектирования, основанный на принципах чистой архитектуры (Clean Architecture) и инверсии зависимостей (Dependency Inversion Principle, DIP). Основная идея заключается в организации кода в виде концентрических слоёв, подобных слоям лука, где зависимости направлены строго внутрь, к центру системы. Внешние слои зависят от внутренних, но не наоборот, что обеспечивает низкую связанность (low coupling) и высокую тестируемость.

Основные принципы и слои

1. Домен (Domain) — ядро системы

Это центральный слой, абсолютно независимый от внешних факторов. Он содержит:

  • Сущности (Entities): базовые бизнес-объекты (например, User, Order).
  • Интерфейсы репозиториев (Repository Interfaces): определяют контракты для работы с данными.
  • Бизнес-правила и логику — то, ради чего существует система.
// Пример сущности в доменном слое
package domain

type User struct {
    ID    int
    Name  string
    Email string
}

// Интерфейс репозитория в доменном слое
type UserRepository interface {
    FindByID(id int) (*User, error)
    Save(user *User) error
}

2. Слой приложения (Application)

Содержит сценарии использования (Use Cases), которые координируют поток данных между доменом и внешними слоями. Здесь реализуется конкретная бизнес-логика.

// Пример use case в слое приложения
package application

import "myapp/domain"

type UserService struct {
    repo domain.UserRepository
}

func (s *UserService) GetUser(id int) (*domain.User, error) {
    // Бизнес-логика (например, валидация) может быть здесь
    return s.repo.FindByID(id)
}

3. Инфраструктурный слой (Infrastructure)

Внешний слой, который реализует интерфейсы, определённые во внутренних слоях. Включает:

  • Реализации репозиториев (работа с БД, файлами, API).
  • Внешние сервисы (например, отправка email, кеширование).
  • Фреймворки и драйверы (HTTP-серверы, ORM).
// Реализация репозитория в инфраструктурном слое
package infrastructure

import "myapp/domain"

type PostgreSQLUserRepository struct {
    // подключение к БД
}

func (r *PostgreSQLUserRepository) FindByID(id int) (*domain.User, error) {
    // Реализация запроса к PostgreSQL
    // ...
}

4. Слой представления (Presentation/API)

Обрабатывает ввод/вывод (например, HTTP-запросы, CLI-команды). Зависит от слоя приложения, но не напрямую от инфраструктуры.

// Пример HTTP-обработчика
package presentation

import "myapp/application"

type UserHandler struct {
    userService *application.UserService
}

func (h *UserHandler) GetUser(w http.ResponseWriter, r *http.Request) {
    // Парсинг запроса, вызов use case, формирование ответа
    // ...
}

Ключевые преимущества

  • Независимость бизнес-логики: Домен и use cases не зависят от базы данных, фреймворков или UI.
  • Тестируемость: Бизнес-логику можно тестировать изолированно с помощью моков.
  • Гибкость: Замена внешних компонентов (например, СУБД или веб-фреймворка) не затрагивает ядро.
  • Поддержка DIP: Зависимости направлены к абстракциям (интерфейсам в домене), а не к реализациям.

Пример зависимости в Go с использованием инъекции

// Сборка компонентов (обычно в main или wire)
func main() {
    // 1. Создаём инфраструктурную зависимость
    repo := &infrastructure.PostgreSQLUserRepository{}
    
    // 2. Внедряем её в use case (удовлетворяя интерфейс домена)
    userService := &application.UserService{Repo: repo}
    
    // 3. Передаём use case в обработчик
    handler := &presentation.UserHandler{UserService: userService}
    
    // Запуск приложения
    http.ListenAndServe(":8080", handler)
}

Отличие от других архитектур

  • От MVC: В MVC нет чёткого разделения на слои с направленностью зависимостей — модель часто знает о базе данных.
  • От Гексагональной (Hexagonal): Очень похожи, но Onion делает больший акцент на концентрических слоях и домене как абсолютном центре.

Когда использовать?

Onion архитектура особенно полезна для:

  • Сложных бизнес-приложений с часто меняющимися требованиями.
  • Долгосрочных проектов, где важна поддерживаемость.
  • Систем, где бизнес-логика является ключевой ценностью.

Заключение

Onion архитектура в Go способствует созданию чистого, тестируемого и гибкого кода, отделяя "что делает система" (домен) от "как она это делает" (инфраструктура). Хотя она добавляет некоторую сложность (больше интерфейсов и слоёв), выгоды в долгосрочной поддержке и адаптивности к изменениям обычно перевешивают первоначальные затраты. В Go её особенно удобно реализовывать благодаря неявным интерфейсам, которые естественным образом поддерживают инверсию зависимостей.