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

Какие знаешь архитектуры построения приложений?

1.8 Middle🔥 121 комментариев
#Архитектура и паттерны

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

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

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

Архитектуры построения приложений

За 10+ лет я работал с разными архитектурными паттернами. Каждый имеет свои плюсы и минусы.

1. Monolithic Architecture (Монолит)

Описание: все компоненты в одном приложении

┌─────────────────────────────────┐
│    Single Application            │
│  ┌──────┐  ┌──────┐ ┌──────┐   │
│  │ Auth │  │Users │ │Orders│   │
│  └──────┘  └──────┘ └──────┘   │
│  ┌──────┐  ┌──────┐ ┌──────┐   │
│  │ Carts│  │Prods │ │Logic │   │
│  └──────┘  └──────┘ └──────┘   │
│                                 │
│      One Database (PostgreSQL)  │
└─────────────────────────────────┘

Когда начинать:

  • MVP и стартапы
  • < 10 разработчиков
  • Один основной домен

Плюсы:

  • Просто развивать и деплоить
  • Легко тестировать
  • Хорошая производительность (нет network latency)
  • Транзакции работают просто

Минусы:

  • При 100k строк очень сложно разобраться
  • Сложно масштабировать разные части
  • Один падает — всё падает
  • Разработчики мешают друг другу

Когда переходить: когда видишь natural boundaries между модулями.

2. Microservices Architecture

Описание: множество независимых сервисов, каждый со своей БД

┌──────────────┐  ┌──────────────┐  ┌──────────────┐
│ Auth Service │  │ Users Service│  │ Orders Service
│              │  │              │  │              │
│  PostgreSQL  │  │  PostgreSQL  │  │  PostgreSQL  │
└──────────────┘  └──────────────┘  └──────────────┘
       ↑                ↑                    ↑
       └────────────────┼────────────────────┘
            API Gateway / Event Bus (RabbitMQ)

Правило: не делай микросервисы, если нет 10+ разработчиков.

Плюсы:

  • Независимые deploy и scaling
  • Разные tech stack для разных сервисов
  • Легче тестировать отдельно
  • Разработчики не мешают друг другу

Минусы:

  • Distributed system complexity (все проблемы распределённых систем)
  • Network latency
  • Consistency problems (CAP theorem)
  • Сложно отлаживать
  • DevOps nightmare (10+ контейнеров)

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

  • Когда монолит становится bottleneck
  • Разные части масштабируются по-разному
  • Разные команды работают на разные части

3. Layered Architecture (слоистая) — классическая Django

Описание: разделение на слои: Presentation → Application → Domain → Infrastructure

# Presentation Layer (views, API endpoints)
from django.http import JsonResponse

def create_order(request):
    # Парсить input, валидировать
    user_id = request.data['user_id']
    items = request.data['items']
    
    # Вызвать application layer
    order = order_service.create_order(user_id, items)
    
    # Вернуть response
    return JsonResponse({'order_id': order.id})

# Application Layer (business logic, use cases)
class CreateOrderService:
    def create_order(self, user_id, items):
        user = self.user_repository.get(user_id)
        if not user:
            raise UserNotFound()
        
        # Бизнес логика
        total = sum(item.price for item in items)
        order = Order(user=user, total=total)
        
        # Сохранить
        self.order_repository.save(order)
        return order

# Domain Layer (entities, value objects)
class Order(models.Model):
    user = models.ForeignKey(User)
    items = models.ManyToManyField(Item)
    total = models.DecimalField()
    created = models.DateTimeField(auto_now_add=True)

# Infrastructure Layer (database, external APIs)
class OrderRepository:
    def save(self, order):
        order.save()
    def get(self, order_id):
        return Order.objects.get(id=order_id)

Плюсы:

  • Логичное разделение ответственности
  • Легко тестировать каждый слой отдельно
  • Классический подход, все его знают

Минусы:

  • Может стать слишком fat (толстый application layer)
  • Зависимость вниз, но сложна зависимость вверх

4. Clean Architecture (по Bob Martin)

Описание: зависимости направлены к центру (к бизнес логике)

     Entities (Pure Business Logic)
           ↑
    Use Cases (Application)
           ↑
 Interface Adapters (Controllers, Presenters)
           ↑
     Frameworks & Drivers

Правило: внешние слои зависят от внутренних, не наоборот.

# Entities Layer (Domain models)
class User:
    def __init__(self, id, name, email):
        self.id = id
        self.name = name
        self.email = email
    
    def is_valid_email(self):
        return '@' in self.email

# Use Cases Layer
class CreateUserUseCase:
    def __init__(self, user_repository: IUserRepository):
        self.repository = user_repository
    
    def execute(self, name: str, email: str):
        user = User(id=None, name=name, email=email)
        
        if not user.is_valid_email():
            raise InvalidEmail()
        
        saved_user = self.repository.save(user)
        return saved_user

# Interface Adapters (Controllers)
class UserController:
    def __init__(self, use_case: CreateUserUseCase):
        self.use_case = use_case
    
    def create(self, request):
        result = self.use_case.execute(
            name=request.data['name'],
            email=request.data['email']
        )
        return JsonResponse({'user_id': result.id})

# Infrastructure (Django, PostgreSQL)
class DjangoUserRepository(IUserRepository):
    def save(self, user: User):
        django_user = UserModel(
            name=user.name,
            email=user.email
        )
        django_user.save()
        return user

Плюсы:

  • Бизнес логика не зависит от фреймворка
  • Очень тестируемо
  • Легко менять реализацию (PostgreSQL → MongoDB)

Минусы:

  • Много boilerplate кода (interfaces, adapters)
  • Оverkill для простых приложений
  • Сложно новичкам

5. Domain-Driven Design (DDD)

Описание: сосредоточение на домене (бизнес), не на технологии

# Aggregates (корневые сущности)
class Order:
    def __init__(self, order_id, customer_id):
        self.order_id = order_id
        self.customer_id = customer_id
        self.items = []
        self.status = 'pending'
    
    def add_item(self, product_id, quantity):
        if self.status != 'pending':
            raise InvalidOrderState()
        self.items.append(OrderItem(product_id, quantity))
    
    def confirm(self):
        if not self.items:
            raise EmptyOrder()
        self.status = 'confirmed'
    
    def cancel(self):
        if self.status == 'shipped':
            raise CannotCancelShippedOrder()
        self.status = 'cancelled'

# Value Objects (неизменяемые объекты)
class Money:
    def __init__(self, amount, currency):
        self.amount = amount
        self.currency = currency
    
    def add(self, other):
        if self.currency != other.currency:
            raise CurrencyMismatch()
        return Money(self.amount + other.amount, self.currency)

# Repositories (only for aggregates)
class OrderRepository:
    def save(self, order):
        # Persist entire aggregate
        pass

# Domain Services (when logic spans multiple aggregates)
class PaymentService:
    def charge_order(self, order: Order, payment: Payment):
        # Business logic across domains
        pass

# Bounded Contexts (разные домены приложения)
# Context 1: Orders domain
# Context 2: Payments domain
# Context 3: Shipping domain
# Они общаются через Events или APIs

Плюсы:

  • Отражает реальный бизнес
  • Легко обсуждать с business stakeholders
  • Масштабируется хорошо

Минусы:

  • Требует глубокого знания бизнеса
  • Сложно для simple CRUD приложений
  • Требует опыта

6. Event-Driven Architecture

Описание: компоненты общаются через события

┌──────────────┐
│ Order Service│ → Event: "OrderCreated"
└──────────────┘
        │
        ↓ (Event Bus / Message Queue)
        
┌──────────────┐  ┌──────────────┐  ┌──────────────┐
│ Payment      │  │ Notification │  │ Analytics    │
│ Service      │  │ Service      │  │ Service      │
└──────────────┘  └──────────────┘  └──────────────┘
from kafka import KafkaProducer, KafkaConsumer

# Producer
class OrderService:
    def create_order(self, items):
        order = Order.create(items)
        
        # Emit event
        self.producer.send('order_created', {
            'order_id': order.id,
            'customer_id': order.customer_id,
            'total': order.total,
            'timestamp': datetime.now().isoformat()
        })
        
        return order

# Consumer
class PaymentService:
    def on_order_created(self, event):
        order_id = event['order_id']
        total = event['total']
        
        # Process payment
        payment = self.process_payment(order_id, total)
        
        # Emit next event
        self.producer.send('payment_completed', {
            'order_id': order_id,
            'payment_id': payment.id
        })

Плюсы:

  • Слабая связанность (loose coupling)
  • Асинхронная обработка
  • Масштабируемость

Минусы:

  • Сложно отлаживать
  • Eventually consistent (не instant)
  • Нужна инфраструктура (Kafka, RabbitMQ)

7. CQRS (Command Query Responsibility Segregation)

Описание: разделение на команды (write) и запросы (read)

# Command Model (Write)
class CreateOrderCommand:
    def __init__(self, user_id, items):
        self.user_id = user_id
        self.items = items

class OrderCommandHandler:
    def handle(self, command: CreateOrderCommand):
        # Транзакция, консистентность
        order = Order(user_id=command.user_id)
        for item in command.items:
            order.add_item(item)
        self.repository.save(order)
        return order

# Query Model (Read) — optimized for reading
class OrderReadModel:
    def get_user_orders(self, user_id):
        # Fast query from denormalized data
        return cache.get(f'user:{user_id}:orders')

# Different databases
# Write: PostgreSQL (ACID)
# Read: Redis / Elasticsearch (fast)

Плюсы:

  • Оптимизировать read и write отдельно
  • Кеширование на write model
  • Масштабировать reads независимо

Минусы:

  • Consistency issues (eventual consistency)
  • Complexity

Сравнение архитектур

АрхитектураРазмерComplexityScalabilityTeam
MonolithicSmallLowLow< 10
LayeredMediumLowMedium10-30
CleanMediumMediumMedium10-30
DDDLargeHighHigh20+
MicroservicesLargeVery HighVery High30+
Event-DrivenAnyHighVery HighDevOps needed
CQRSAnyHighHighTech experts

Мой подход

На собеседовании:

  • Я выбираю архитектуру в зависимости от требований
  • Не религиозен к одному подходу
  • Начинаю просто, потом усложняю

В реальности:

  • MVP: Layered Monolithic (Django)
  • 6 месяцев: Clean Architecture (still monolithic)
  • 1 год: Event-Driven (если нужна масштабируемость)
  • 2+ года: Микросервисы + DDD (если достаточно большая компания)

Golden Rule: Make it simple first. Add complexity only when you have the problem.