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

Что такое High Cohesion, применимо к микросервисной архитектуре?

2.4 Senior🔥 141 комментариев
#DevOps и инфраструктура#Архитектура и паттерны

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

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

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

High Cohesion в микросервисной архитектуре: принцип, практика, примеры

Что такое High Cohesion

High Cohesion (высокая связанность) — это принцип дизайна, который говорит: компоненты внутри одного модуля должны быть тесно связаны друг с другом и служить одной цели.

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

  • Cohesion (связанность) — мера того, насколько компоненты внутри модуля связаны
  • High Cohesion — все части модуля работают вместе для достижения одной цели
  • Low Cohesion — части модуля делают разные вещи, не связанные между собой

Пример Low Cohesion (плохо)

// ❌ Класс с низкой связанностью
class UserService {
  // Работает с пользователями
  createUser(userData) { }
  getUser(id) { }
  updateUser(id, data) { }

  // Работает с платежами (не относится к пользователям!)
  processPayment(amount) { }
  refundPayment(transactionId) { }

  // Отправляет отчёты (тоже не связано с пользователями)
  generateMonthlyReport() { }
  sendReportByEmail() { }
}

// Проблемы:
// - UserService делает слишком много
// - Изменение платёжной логики влияет на User сервис
// - Сложно переиспользовать компоненты
// - Тестирование сложное (нужно мокировать платежи для теста юзера)

Пример High Cohesion (хорошо)

// ✅ Высокая связанность

// UserService фокусируется ТОЛЬКО на пользователях
class UserService {
  createUser(userData) { }
  getUser(id) { }
  updateUser(id, data) { }
  deleteUser(id) { }
  findByEmail(email) { }
}

// PaymentService фокусируется ТОЛЬКО на платежах
class PaymentService {
  processPayment(amount, userId) { }
  refundPayment(transactionId) { }
  getTransactionHistory(userId) { }
}

// ReportService фокусируется ТОЛЬКО на отчётах
class ReportService {
  generateMonthlyReport() { }
  sendReportByEmail(email) { }
}

// Пример использования
class OrderController {
  constructor(
    private userService: UserService,
    private paymentService: PaymentService,
    private reportService: ReportService
  ) {}

  async createOrder(userId: string, amount: number) {
    const user = await this.userService.getUser(userId);
    const payment = await this.paymentService.processPayment(amount, userId);
    await this.reportService.generateMonthlyReport();
  }
}

High Cohesion в микросервисной архитектуре

В микросервисах High Cohesion означает, что каждый микросервис должен иметь чётко определённую область ответственности (Bounded Context из DDD).

Пример архитектуры:

Микросервисная система:

┌─────────────────┐
│ User Service    │  Отвечает за: управление пользователями, аутентификацию, профили
└────────┬────────┘
         │
         ├─> UserRepository
         ├─> AuthenticationService
         └─> ProfileService

┌─────────────────┐
│ Payment Service │  Отвечает за: обработка платежей, транзакции, рефанды
└────────┬────────┘
         │
         ├─> PaymentRepository
         ├─> StripeIntegration
         └─> RefundService

┌─────────────────┐
│ Order Service   │  Отвечает за: управление заказами, статусы заказов
└────────┬────────┘
         │
         ├─> OrderRepository
         ├─> OrderStatusService
         └─> InventoryIntegration

┌─────────────────┐
│ Notification    │  Отвечает за: отправка уведомлений, логирование
│ Service         │
└────────┬────────┘
         │
         ├─> EmailService
         ├─> SMSService
         └─> LoggingService

Что НЕ ДЕЛАТЬ: Low Cohesion микросервисы

// ❌ ПЛОХО: Микросервис делает слишком много
class OrderService {
  // Логика заказов
  createOrder() { }
  getOrder() { }
  updateOrder() { }
  cancelOrder() { }

  // Логика платежей (не её ответственность!)
  processPayment() { }
  refundPayment() { }

  // Логика доставки (не её ответственность!)
  scheduleDelivery() { }
  trackDelivery() { }

  // Логика уведомлений (не её ответственность!)
  sendOrderConfirmation() { }
  sendDeliveryNotification() { }
}

// Проблемы:
// - Микросервис слишком большой
// - Сложно масштабировать (нужно масштабировать всё, даже если проблема только в платежах)
// - Сложнее разбираться в коде
// - Изменение логики платежей требует рефакторинга Order Service

Что ДЕЛАТЬ: High Cohesion микросервисы

// ✅ ХОРОШО: Каждый микросервис имеет чёткую ответственность

// Order Service - ТОЛЬКО логика заказов
@Controller('orders')
export class OrderController {
  constructor(private orderService: OrderService) {}

  @Post()
  async createOrder(@Body() data: CreateOrderDTO) {
    return await this.orderService.create(data);
  }

  @Get(':id')
  async getOrder(@Param('id') id: string) {
    return await this.orderService.getById(id);
  }
}

export class OrderService {
  async create(data: CreateOrderDTO) {
    // Создаём заказ
    const order = await this.orderRepository.create(data);
    
    // Публикуем событие - пусть другие сервисы на него подпишутся
    await this.eventBus.publish('order.created', { orderId: order.id });
    
    return order;
  }

  async cancel(orderId: string) {
    const order = await this.orderRepository.getById(orderId);
    order.status = 'cancelled';
    await this.orderRepository.save(order);
    
    // Публикуем событие для других сервисов
    await this.eventBus.publish('order.cancelled', { orderId });
  }
}

// Payment Service - ТОЛЬКО логика платежей
@Controller('payments')
export class PaymentController {
  constructor(private paymentService: PaymentService) {}

  @Post()
  async processPayment(@Body() data: ProcessPaymentDTO) {
    return await this.paymentService.process(data);
  }
}

export class PaymentService {
  async process(data: ProcessPaymentDTO) {
    const payment = await this.stripeService.charge(data.amount);
    await this.paymentRepository.save(payment);
    
    // Публикуем событие - Order Service узнает, что платёж прошёл
    await this.eventBus.publish('payment.completed', {
      paymentId: payment.id,
      orderId: data.orderId
    });
    
    return payment;
  }
}

// Notification Service - ТОЛЬКО логика уведомлений
@Injectable()
export class NotificationSubscriber {
  constructor(private emailService: EmailService) {}

  @OnEvent('order.created')
  async onOrderCreated(event: OrderCreatedEvent) {
    await this.emailService.send(event.userId, 'Order Confirmation');
  }

  @OnEvent('payment.completed')
  async onPaymentCompleted(event: PaymentCompletedEvent) {
    await this.emailService.send(event.userId, 'Payment Confirmed');
  }
}

Как достичь High Cohesion: практические шаги

1. Используй DDD (Domain-Driven Design)

// Identify Bounded Contexts
const boundedContexts = [
  'User Management',      // User Service
  'Order Management',     // Order Service
  'Payment Processing',   // Payment Service
  'Inventory Management', // Inventory Service
  'Shipping & Delivery'   // Shipping Service
];

// Каждый микросервис соответствует одному Bounded Context

**2. Используй Event-Driven Communication

// Вместо синхронных вызовов между сервисами
// UserService -> PaymentService -> OrderService (ПЛОХО: tight coupling)

// Используй асинхронные события
UserService ----publishes----> order.created ----subscribes----> OrderService
                                                                        |
                                                                        v
                                                              PaymentService

**3. Определи API граници каждого сервиса

// Order Service API
POST   /orders              - Create order
GET    /orders/:id          - Get order
PUT    /orders/:id          - Update order
DELETE /orders/:id          - Cancel order

// Это всё, что Order Service должен делать
// Платежи, доставку, уведомления - делают другие сервисы

**4. Используй Repository Pattern

// Каждый сервис имеет свой repository для своей БД
UserService
  ├── UserRepository (работает с users table)
  └── БД: user_service_db

OrderService
  ├── OrderRepository (работает с orders table)
  └── БД: order_service_db

PaymentService
  ├── PaymentRepository (работает с payments table)
  └── БД: payment_service_db

// Это гарантирует, что сервисы не делят БД

Когда High Cohesion нарушается

Антипаттерны, которых нужно избегать:

  1. God Service — один сервис делает всё
  2. Chatty Services — слишком много синхронных вызовов
  3. Shared Database — несколько сервисов работают с одной БД
  4. Circular Dependencies — Service A зависит от B, а B от A
  5. Anemic Models — сервисы содержат только данные, без логики

High Cohesion vs Loose Coupling

// High Cohesion: компоненты внутри сервиса тесно связаны
// Loose Coupling: сервисы слабо связаны друг с другом

// Правильный баланс:
Intra-service:   High Cohesion (UserService содержит все части логики для users)
Inter-service:   Loose Coupling (сервисы общаются через events/API)

Практический пример из реального проекта

// Payment Platform (где я работал)

// ✅ High Cohesion: Auth Service
auth-service/
├── controllers/
│   └── AuthController
├── services/
│   ├── JwtService
│   ├── PasswordService
│   └── SessionService
├── repositories/
│   └── UserRepository
└── entities/
    └── User

// Только логика аутентификации и авторизации
// Не делает платежи, заказы, уведомления

// ✅ High Cohesion: Payment Service
payment-service/
├── controllers/
│   └── PaymentController
├── services/
│   ├── StripeService
│   ├── RefundService
│   └── TransactionService
├── repositories/
│   └── PaymentRepository
└── entities/
    └── Payment

// Только логика платежей
// Не делает управление пользователями, доставку

Выводы

  1. High Cohesion — это принцип дизайна, который делает код более понятным и поддерживаемым
  2. В микросервисах это означает: каждый сервис отвечает за одну область
  3. DDD Bounded Contexts помогают идентифицировать границы сервисов
  4. Event-Driven архитектура позволяет сервисам взаимодействовать без tight coupling
  5. Результат: система легче масштабировать, тестировать и понимать

High Cohesion + Loose Coupling = хорошо спроектированная микросервисная система.