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

Что такое многослойная архитектура?

2.3 Middle🔥 201 комментариев
#Микросервисы и архитектура

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

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

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

Многослойная архитектура в программировании

Многослойная архитектура (Layered Architecture) — это широко распространённый шаблон проектирования (архитектурный паттерн), который организует приложение в логические горизонтальные слои (layers), каждый из которых выполняет строго определённую роль. Каждый слой имеет чётко заданную ответственность и взаимодействует только со своими непосредственными соседями, что создаёт принцип максимального рассоединения (loose coupling) и высокого зацепления (high cohesion) внутри каждого слоя. Эта архитектура является фундаментом для более сложных и специализированных шаблонов, таких как Clean Architecture, Onion Architecture или классическая трёхслойная архитектура.

Основная цель — разделение ответственности (Separation of Concerns, SoC). Разделяя код на слои, мы повышаем его поддерживаемость, тестируемость, масштабируемость и позволяем разным командам работать над отдельными частями системы практически независимо. Риски изменений локализуются в рамках одного слоя.

Основные слои в типичной многослойной архитектуре (на примере веб-приложения)

В классической трёхслойной архитектуре выделяют следующие уровни:

  1. Слой представления (Presentation Layer): Отвечает за взаимодействие с пользователем. Это могут быть HTML-страницы, REST API, gRPC-эндпоинты или консольный интерфейс. Его задача — принять запрос, делегировать логику слою бизнес-логики, получить результат и оформить ответ (JSON, HTML, etc.). Здесь же обычно находится валидация входных данных.

    // Пример слоя представления (HTTP-обработчик в Go)
    package handlers
    
    import (
        "encoding/json"
        "net/http"
        "your-app/services"
    )
    
    type UserHandler struct {
        userService *services.UserService
    }
    
    func (h *UserHandler) GetUser(w http.ResponseWriter, r *http.Request) {
        id := r.URL.Query().Get("id")
    
        // Делегируем работу сервисному слою
        user, err := h.userService.FindByID(id)
        if err != nil {
            http.Error(w, err.Error(), http.StatusNotFound)
            return
        }
    
        // Форматируем ответ
        w.Header().Set("Content-Type", "application/json")
        json.NewEncoder(w).Encode(user)
    }
    
  2. Слой бизнес-логики (Business Logic Layer / Domain Layer): Ядро приложения. Содержит бизнес-правила, алгоритмы и доменную логику. Этот слой не должен знать о деталях представления данных или о том, как именно эти данные хранятся. В нём находятся use cases, сервисы, доменные модели и агрегаты. Все важные операции с данными координируются здесь.

    // Пример сервиса (слой бизнес-логики)
    package services
    
    import (
        "errors"
        "your-app/models"
        "your-app/repositories"
    )
    
    type UserService struct {
        repo repositories.UserRepository
    }
    
    func (s *UserService) Register(email, password string) (*models.User, error) {
        // Бизнес-правило: проверка уникальности email
        existing, _ := s.repo.FindByEmail(email)
        if existing != nil {
            return nil, errors.New("user with this email already exists")
        }
    
        // Бизнес-логика: создание и хеширование пароля
        user := models.NewUser(email, password)
        user.HashPassword()
    
        // Делегируем сохранение слою доступа к данным
        err := s.repo.Save(user)
        return user, err
    }
    
  3. Слой доступа к данным (Data Access Layer / Persistence Layer): Отвечает за взаимодействие с источниками данных (базы данных — SQL/NoSQL, файловые системы, внешние API). Он предоставляет абстрактный интерфейс (например, репозиторий) для операций Create, Read, Update, Delete (CRUD) над сущностями, скрывая от бизнес-слоя специфику СУБД (SQL-запросы, драйверы).

    // Пример интерфейса репозитория (слой доступа к данным)
    package repositories
    
    import "your-app/models"
    
    // Интерфейс определяет контракт, не зависящий от реализации
    type UserRepository interface {
        FindByID(id string) (*models.User, error)
        FindByEmail(email string) (*models.User, error)
        Save(user *models.User) error
        Delete(id string) error
    }
    
    // Конкретная реализация для PostgreSQL
    type PostgresUserRepository struct {
        db *sql.DB
    }
    
    func (r *PostgresUserRepository) FindByID(id string) (*models.User, error) {
        // Здесь конкретный SQL-запрос
        row := r.db.QueryRow("SELECT id, email FROM users WHERE id = $1", id)
        user := &models.User{}
        err := row.Scan(&user.ID, &user.Email)
        return user, err
    }
    

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

  • Инверсия зависимостей (Dependency Inversion): Высокоуровневые модули (бизнес-логика) не должны зависеть от низкоуровневых (доступ к данным). Оба должны зависеть от абстракций (интерфейсов). В Go это реализуется через внедрение интерфейсов, что отлично демонстрирует пример выше.
  • Направление зависимостей (Onion/Hexagonal): Зависимости всегда направлены внутрь, к ядру (бизнес-логике). Слой представления и слой данных зависят от интерфейсов, объявленных в слое бизнес-логики, но не наоборот. Это делает ядро независимым от фреймворков и внешних сервисов.
  • Лёгкость тестирования: Бизнес-логику можно легко протестировать с помощью моков (mocks) или стабов (stubs), подменяя реальные репозитории на заглушки. Это позволяет писать быстрые и изолированные unit-тесты.
  • Заменаемость компонентов: При необходимости сменить базу данных или фреймворк веб-сервера, изменения будут локализованы в одном конкретном слое.

Роль в Go-разработке

В Go, который часто выбирают для создания высоконагруженных и надёжных бэкенд-сервисов, многослойная архитектура является стандартом де-факто. Простая система пакетов (internal/, pkg/, cmd/) естественным образом ложится на эту модель. Например, структура проекта может выглядеть так:

/internal
  /handlers      # Presentation Layer (HTTP)
  /services      # Business Logic Layer
  /repositories  # Data Access Layer
  /models        # Domain Entities
  /server        # Инициализация и конфигурация

Таким образом, многослойная архитектура — это не просто теория, а практичный и дисциплинированный подход к структурированию кода, который помогает строить в Go сложные, но при этом понятные, гибкие и долгоживущие приложения.