Ответ
Use Case (или Interactor) — это ключевой компонент слоя бизнес-логики в «чистой архитектуре» (Clean Architecture). Он инкапсулирует и реализует один конкретный сценарий использования системы, например, «Регистрация пользователя», «Создание заказа» или «Расчет стоимости доставки».
Основная цель Use Case — отделить бизнес-правила от деталей инфраструктуры (базы данных, веб-фреймворки, внешние API).
Принципы реализации в Go:
- Зависимость от абстракций: Use Case зависит не от конкретных реализаций (например, репозитория для PostgreSQL), а от интерфейсов (портов). Это позволяет легко подменять реализации.
- Инкапсуляция логики: Вся логика, связанная со сценарием (валидация, вызов нужных репозиториев, координация доменных моделей), находится внутри Use Case.
- Простота тестирования: Благодаря зависимостям от интерфейсов, Use Case легко тестировать в изоляции, передавая в него mock-объекты (заглушки).
Пример: Use Case для регистрации пользователя
package usecase
import (
"errors"
"strings"
)
// User - простая доменная модель
type User struct {
Name string
Email string
}
// UserRepository - это порт (интерфейс), который должен быть реализован
// слоем инфраструктуры (например, postgres_repo.go). ype UserRepository interface {
Save(user User) error
FindByEmail(email string) (*User, error)
}
// RegisterUserUseCase - структура, реализующая сценарий. ype RegisterUserUseCase struct {
repo UserRepository // Зависимость от интерфейса, а не от реализации
}
// NewRegisterUserUseCase - конструктор для создания Use Case.
func NewRegisterUserUseCase(repo UserRepository) *RegisterUserUseCase {
return &RegisterUserUseCase{repo: repo}
}
// Execute - основной метод, выполняющий бизнес-логику.
func (uc *RegisterUserUseCase) Execute(name, email string) error {
// 1. Валидация входных данных
if !strings.Contains(email, "@") {
return errors.New("некорректный email")
}
// 2. Проверка бизнес-правила (пользователь не должен существовать)
if _, err := uc.repo.FindByEmail(email); err == nil {
return errors.New("пользователь с таким email уже существует")
}
// 3. Выполнение основной операции
user := User{Name: name, Email: email}
return uc.repo.Save(user)
}
Преимущества такого подхода:
- Чистая архитектура: Четкое разделение ответственности между слоями.
- Гибкость: Можно легко заменить базу данных (PostgreSQL на MongoDB), просто написав новый адаптер для интерфейса
UserRepository
. - Тестируемость: Логику можно проверить юнит-тестами без поднятия БД или веб-сервера.