← Назад к вопросам
Какую архитектуру хотел бы видеть на проекте?
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 структурированное логирование
Преимущества этого подхода
- Тестируемость: Domain слой не зависит от Spring/БД
- Масштабируемость: Легко разбить на микросервисы
- Поддерживаемость: Ясная ответственность каждого слоя
- Гибкость: Менять реализацию БД/интеграции без изменения бизнес-логики
Это базис, который адаптирую под конкретные требования проекта.