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

Какую архитектуру хотел бы видеть на проекте?

2.2 Middle🔥 251 комментариев
#REST API и микросервисы

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

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

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

# Архитектура современного Java-проекта

Общий подход: Hexagonal Architecture + CQRS (при необходимости)

Для максимальной масштабируемости и тестируемости я рекомендую архитектуру, основанную на трёх слоях с чётко разделёнными ответственностями:

1. Domain Layer (Ядро бизнес-логики)

// Entities, Value Objects, Domain Services
public class Order {
    private OrderId id;
    private List<OrderItem> items;
    private Money totalPrice;
    
    public void addItem(OrderItem item) {
        // Бизнес-правила здесь
        if (items.size() >= 100) throw new OrderLimitException();
        items.add(item);
        recalculateTotal();
    }
}

// Domain Service (только если логика пересекает несколько entities)
public class OrderPricingService {
    public Money calculateTotal(Order order) { ... }
}

2. Application Layer (Use Cases, Orchestration)

// Command Handler - один метод = один use case
public class CreateOrderCommandHandler {
    private final OrderRepository repo;
    private final OrderPricingService pricing;
    private final OrderCreatedEvent event;
    
    public void handle(CreateOrderCommand cmd) {
        Order order = new Order(cmd.getId(), cmd.getItems());
        order.applyPricing(pricing); // Всё ещё в domain
        repo.save(order);
        // Публикуем событие для других сервисов
        eventBus.publish(order.getDomainEvents());
    }
}

3. Infrastructure Layer (Реализация, базы данных, интеграции)

public class JpaOrderRepository implements OrderRepository {
    private final OrderJpaRepository jpaRepo;
    
    @Override
    public void save(Order order) {
        jpaRepo.save(new OrderJpaEntity(order));
    }
}

4. Presentation Layer (REST контроллеры, WebSocket)

@RestController
public class OrderController {
    private final CreateOrderCommandHandler handler;
    
    @PostMapping("/api/v1/orders")
    public ResponseEntity<OrderDto> create(@RequestBody CreateOrderRequest req) {
        CreateOrderCommand cmd = new CreateOrderCommand(req.getId(), req.getItems());
        handler.handle(cmd);
        return ResponseEntity.ok(new OrderDto(...));
    }
}

Ключевые принципы

Dependency Inversion

  • Infrastructure → Application → Domain
  • Никогда не наоборот!
  • Interfaces в Application/Domain, реализация в Infrastructure

Event-Driven подход

  • Domain events для аудита и интеграции
  • Event handlers для side-effects (email, push, sync другие сервисы)
  • Гарантия консистентности через события

CQRS (если масштабируемость критична)

// Разделяем чтение и запись
public class OrderQueryService {
    // Оптимизированный для чтения - может быть read replica
    public List<OrderDto> getAllByUser(UserId userId) { ... }
}

Transaction Management

@Transactional  // На уровне Application Service
public void handle(CreateOrderCommand cmd) {
    // Все операции в одной транзакции
    // Откатятся вместе при исключении
}

Структура папок

src/main/java/com/company/
├── order/                    # Bounded Context
│   ├── domain/
│   │   ├── Order.java
│   │   ├── OrderRepository.java (interface)
│   │   └── OrderPricingService.java
│   ├── application/
│   │   ├── CreateOrderCommandHandler.java
│   │   ├── OrderQueryService.java
│   │   └── dto/
│   ├── infrastructure/
│   │   ├── persistence/JpaOrderRepository.java
│   │   ├── event/OrderEventListener.java
│   │   └── external/PaymentServiceAdapter.java
│   └── presentation/
│       └── OrderController.java
├── user/                    # Другой Bounded Context
└── shared/
    ├── domain/
    │   ├── ValueObject.java
    │   ├── DomainEvent.java
    │   └── AggregateRoot.java
    └── infrastructure/
        ├── config/
        └── util/

Технологический стек

  • Framework: Spring Boot 3.x
  • Database: PostgreSQL с миграциями Flyway
  • Messaging: RabbitMQ для асинхронных событий
  • API: Spring MVC (или Spring WebFlux для высокой нагрузки)
  • Testing: JUnit 5 + Mockito + TestContainers
  • Logging: SLF4J + Logback структурированное логирование

Преимущества этого подхода

  1. Тестируемость: Domain слой не зависит от Spring/БД
  2. Масштабируемость: Легко разбить на микросервисы
  3. Поддерживаемость: Ясная ответственность каждого слоя
  4. Гибкость: Менять реализацию БД/интеграции без изменения бизнес-логики

Это базис, который адаптирую под конкретные требования проекта.

Какую архитектуру хотел бы видеть на проекте? | PrepBro