- Added comprehensive course structure with 11 modules - Included theoretical content, practical examples, and tasks - Multi-language code examples (Java, Rust, Node.js, Python) - Detailed analysis of architectural approaches and trade-offs - Complete caching strategies documentation - Architecture examples from real-world systems (Twitter, Netflix, Uber) - Structured navigation and learning path - Ready for educational use
553 lines
19 KiB
Markdown
553 lines
19 KiB
Markdown
# Архитектурные стили и паттерны
|
|
|
|
## Навигация
|
|
- [🏠 Главная страница курса](../../../README.md)
|
|
- [📚 Модуль 1](../README.md)
|
|
|
|
---
|
|
|
|
## Монолитная архитектура
|
|
|
|
### Определение
|
|
**Монолитная архитектура** — это архитектурный стиль, при котором все компоненты приложения объединены в единое развертываемое приложение.
|
|
|
|
### Характеристики
|
|
- **Единое развертывание** — все компоненты развертываются вместе
|
|
- **Общая база данных** — все модули используют одну БД
|
|
- **Единый технологический стек** — один язык, один фреймворк
|
|
- **Прямые вызовы** — компоненты вызывают друг друга напрямую
|
|
|
|
### Пример реализации
|
|
```java
|
|
// Монолитное приложение e-commerce
|
|
@SpringBootApplication
|
|
public class EcommerceApplication {
|
|
public static void main(String[] args) {
|
|
SpringApplication.run(EcommerceApplication.class, args);
|
|
}
|
|
}
|
|
|
|
// Все контроллеры в одном приложении
|
|
@RestController
|
|
@RequestMapping("/api")
|
|
public class EcommerceController {
|
|
|
|
@Autowired
|
|
private UserService userService;
|
|
|
|
@Autowired
|
|
private OrderService orderService;
|
|
|
|
@Autowired
|
|
private PaymentService paymentService;
|
|
|
|
@PostMapping("/orders")
|
|
public ResponseEntity<Order> createOrder(@RequestBody CreateOrderRequest request) {
|
|
// Вся логика в одном месте
|
|
User user = userService.findById(request.getUserId());
|
|
Order order = orderService.createOrder(request);
|
|
PaymentResult payment = paymentService.processPayment(order);
|
|
return ResponseEntity.ok(order);
|
|
}
|
|
}
|
|
```
|
|
|
|
### Преимущества
|
|
- **Простота разработки** — легко начать проект
|
|
- **Простота тестирования** — все в одном процессе
|
|
- **Простота развертывания** — один артефакт
|
|
- **Производительность** — нет сетевых вызовов
|
|
|
|
### Недостатки
|
|
- **Сложность масштабирования** — нужно масштабировать все приложение
|
|
- **Технологические ограничения** — привязанность к одному стеку
|
|
- **Риск сбоев** — падение одного компонента влияет на все
|
|
- **Сложность команд** — команды работают над одним кодом
|
|
|
|
## Микросервисная архитектура
|
|
|
|
### Определение
|
|
**Микросервисная архитектура** — это архитектурный стиль, при котором приложение разбивается на множество небольших, независимых сервисов.
|
|
|
|
### Характеристики
|
|
- **Независимые сервисы** — каждый сервис работает автономно
|
|
- **Отдельные базы данных** — каждый сервис имеет свою БД
|
|
- **Разные технологии** — сервисы могут использовать разные стеки
|
|
- **Сетевое взаимодействие** — сервисы общаются по сети
|
|
|
|
### Пример реализации
|
|
```java
|
|
// User Service
|
|
@RestController
|
|
@RequestMapping("/api/users")
|
|
public class UserController {
|
|
@Autowired
|
|
private UserService userService;
|
|
|
|
@GetMapping("/{id}")
|
|
public ResponseEntity<User> getUser(@PathVariable Long id) {
|
|
return ResponseEntity.ok(userService.findById(id));
|
|
}
|
|
}
|
|
|
|
// Order Service
|
|
@RestController
|
|
@RequestMapping("/api/orders")
|
|
public class OrderController {
|
|
@Autowired
|
|
private OrderService orderService;
|
|
|
|
@Autowired
|
|
private UserServiceClient userServiceClient;
|
|
|
|
@PostMapping
|
|
public ResponseEntity<Order> createOrder(@RequestBody CreateOrderRequest request) {
|
|
// Вызов внешнего сервиса
|
|
User user = userServiceClient.getUser(request.getUserId());
|
|
Order order = orderService.createOrder(request);
|
|
return ResponseEntity.ok(order);
|
|
}
|
|
}
|
|
|
|
// Payment Service
|
|
@RestController
|
|
@RequestMapping("/api/payments")
|
|
public class PaymentController {
|
|
@Autowired
|
|
private PaymentService paymentService;
|
|
|
|
@PostMapping
|
|
public ResponseEntity<PaymentResult> processPayment(@RequestBody PaymentRequest request) {
|
|
PaymentResult result = paymentService.processPayment(request);
|
|
return ResponseEntity.ok(result);
|
|
}
|
|
}
|
|
```
|
|
|
|
### Преимущества
|
|
- **Независимое масштабирование** — каждый сервис масштабируется отдельно
|
|
- **Технологическое разнообразие** — разные технологии для разных задач
|
|
- **Независимые команды** — команды работают над разными сервисами
|
|
- **Отказоустойчивость** — падение одного сервиса не влияет на другие
|
|
|
|
### Недостатки
|
|
- **Сложность разработки** — нужно управлять множеством сервисов
|
|
- **Сетевая задержка** — вызовы между сервисами медленнее
|
|
- **Сложность тестирования** — нужно тестировать интеграции
|
|
- **Сложность развертывания** — нужно координировать развертывание
|
|
|
|
## Event-Driven Architecture (EDA)
|
|
|
|
### Определение
|
|
**Event-Driven Architecture** — это архитектурный стиль, основанный на производстве, обнаружении, потреблении и реакции на события.
|
|
|
|
### Характеристики
|
|
- **События** — значимые изменения в системе
|
|
- **Асинхронность** — события обрабатываются асинхронно
|
|
- **Слабая связанность** — компоненты не знают друг о друге
|
|
- **Масштабируемость** — легко добавлять новых потребителей
|
|
|
|
### Пример реализации
|
|
```java
|
|
// Доменное событие
|
|
public class OrderCreatedEvent {
|
|
private final String orderId;
|
|
private final String customerId;
|
|
private final BigDecimal amount;
|
|
private final LocalDateTime occurredOn;
|
|
|
|
public OrderCreatedEvent(String orderId, String customerId, BigDecimal amount) {
|
|
this.orderId = orderId;
|
|
this.customerId = customerId;
|
|
this.amount = amount;
|
|
this.occurredOn = LocalDateTime.now();
|
|
}
|
|
|
|
// Геттеры
|
|
}
|
|
|
|
// Публикация события
|
|
@Service
|
|
public class OrderService {
|
|
|
|
@Autowired
|
|
private ApplicationEventPublisher eventPublisher;
|
|
|
|
public Order createOrder(CreateOrderRequest request) {
|
|
Order order = new Order(request);
|
|
order = orderRepository.save(order);
|
|
|
|
// Публикация события
|
|
eventPublisher.publishEvent(new OrderCreatedEvent(
|
|
order.getId(),
|
|
order.getCustomerId(),
|
|
order.getAmount()
|
|
));
|
|
|
|
return order;
|
|
}
|
|
}
|
|
|
|
// Обработка события
|
|
@Component
|
|
public class OrderCreatedEventHandler {
|
|
|
|
@Autowired
|
|
private InventoryService inventoryService;
|
|
|
|
@Autowired
|
|
private NotificationService notificationService;
|
|
|
|
@EventListener
|
|
public void handleOrderCreated(OrderCreatedEvent event) {
|
|
// Резервирование товара
|
|
inventoryService.reserveItems(event.getOrderId());
|
|
|
|
// Отправка уведомления
|
|
notificationService.sendOrderConfirmation(event.getCustomerId());
|
|
}
|
|
}
|
|
```
|
|
|
|
## CQRS (Command Query Responsibility Segregation)
|
|
|
|
### Определение
|
|
**CQRS** — это паттерн, который разделяет операции чтения и записи данных на разные модели.
|
|
|
|
### Характеристики
|
|
- **Разделение команд и запросов** — разные модели для записи и чтения
|
|
- **Оптимизация** — модели оптимизированы для своих задач
|
|
- **Масштабируемость** — можно масштабировать чтение и запись отдельно
|
|
- **Сложность** — увеличивает сложность системы
|
|
|
|
### Пример реализации
|
|
```java
|
|
// Command Model (Write)
|
|
@Entity
|
|
@Table(name = "orders")
|
|
public class Order {
|
|
@Id
|
|
private String id;
|
|
private String customerId;
|
|
private OrderStatus status;
|
|
private BigDecimal amount;
|
|
private LocalDateTime createdAt;
|
|
|
|
// Методы для изменения состояния
|
|
public void confirm() {
|
|
this.status = OrderStatus.CONFIRMED;
|
|
}
|
|
|
|
public void cancel() {
|
|
this.status = OrderStatus.CANCELLED;
|
|
}
|
|
}
|
|
|
|
// Query Model (Read)
|
|
@Entity
|
|
@Table(name = "order_summaries")
|
|
public class OrderSummary {
|
|
@Id
|
|
private String id;
|
|
private String customerName;
|
|
private String customerEmail;
|
|
private OrderStatus status;
|
|
private BigDecimal amount;
|
|
private LocalDateTime createdAt;
|
|
private int itemCount;
|
|
|
|
// Только геттеры для чтения
|
|
}
|
|
|
|
// Command Handler
|
|
@Service
|
|
public class OrderCommandHandler {
|
|
|
|
@Autowired
|
|
private OrderRepository orderRepository;
|
|
|
|
@Autowired
|
|
private OrderSummaryRepository orderSummaryRepository;
|
|
|
|
public void handle(CreateOrderCommand command) {
|
|
// Создание заказа
|
|
Order order = new Order(command);
|
|
orderRepository.save(order);
|
|
|
|
// Обновление read model
|
|
OrderSummary summary = new OrderSummary(order);
|
|
orderSummaryRepository.save(summary);
|
|
}
|
|
}
|
|
|
|
// Query Handler
|
|
@Service
|
|
public class OrderQueryHandler {
|
|
|
|
@Autowired
|
|
private OrderSummaryRepository orderSummaryRepository;
|
|
|
|
public List<OrderSummary> handle(GetOrdersQuery query) {
|
|
return orderSummaryRepository.findByCustomerId(query.getCustomerId());
|
|
}
|
|
}
|
|
```
|
|
|
|
## Hexagonal Architecture (Ports and Adapters)
|
|
|
|
### Определение
|
|
**Hexagonal Architecture** — это архитектурный паттерн, который изолирует бизнес-логику от внешних зависимостей.
|
|
|
|
### Характеристики
|
|
- **Порты** — интерфейсы для взаимодействия с внешним миром
|
|
- **Адаптеры** — реализации портов для конкретных технологий
|
|
- **Изоляция** — бизнес-логика не зависит от внешних технологий
|
|
- **Тестируемость** — легко тестировать с mock-объектами
|
|
|
|
### Пример реализации
|
|
```java
|
|
// Domain Layer (внутренний круг)
|
|
public class Order {
|
|
private String id;
|
|
private String customerId;
|
|
private OrderStatus status;
|
|
private BigDecimal amount;
|
|
|
|
public void confirm() {
|
|
this.status = OrderStatus.CONFIRMED;
|
|
}
|
|
}
|
|
|
|
// Ports (интерфейсы)
|
|
public interface OrderRepository {
|
|
void save(Order order);
|
|
Optional<Order> findById(String id);
|
|
}
|
|
|
|
public interface PaymentService {
|
|
PaymentResult processPayment(PaymentRequest request);
|
|
}
|
|
|
|
public interface NotificationService {
|
|
void sendNotification(String recipient, String message);
|
|
}
|
|
|
|
// Application Layer
|
|
@Service
|
|
public class OrderService {
|
|
private final OrderRepository orderRepository;
|
|
private final PaymentService paymentService;
|
|
private final NotificationService notificationService;
|
|
|
|
public OrderService(OrderRepository orderRepository,
|
|
PaymentService paymentService,
|
|
NotificationService notificationService) {
|
|
this.orderRepository = orderRepository;
|
|
this.paymentService = paymentService;
|
|
this.notificationService = notificationService;
|
|
}
|
|
|
|
public void processOrder(Order order) {
|
|
// Бизнес-логика
|
|
order.confirm();
|
|
orderRepository.save(order);
|
|
|
|
// Внешние сервисы через порты
|
|
PaymentResult payment = paymentService.processPayment(
|
|
new PaymentRequest(order.getAmount())
|
|
);
|
|
|
|
if (payment.isSuccess()) {
|
|
notificationService.sendNotification(
|
|
order.getCustomerId(),
|
|
"Order confirmed"
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Adapters (внешний круг)
|
|
@Repository
|
|
public class JpaOrderRepository implements OrderRepository {
|
|
@Override
|
|
public void save(Order order) {
|
|
// JPA реализация
|
|
}
|
|
|
|
@Override
|
|
public Optional<Order> findById(String id) {
|
|
// JPA реализация
|
|
return Optional.empty();
|
|
}
|
|
}
|
|
|
|
@Component
|
|
public class StripePaymentService implements PaymentService {
|
|
@Override
|
|
public PaymentResult processPayment(PaymentRequest request) {
|
|
// Stripe API реализация
|
|
return new PaymentResult(true, "Payment processed");
|
|
}
|
|
}
|
|
|
|
@Component
|
|
public class EmailNotificationService implements NotificationService {
|
|
@Override
|
|
public void sendNotification(String recipient, String message) {
|
|
// Email реализация
|
|
}
|
|
}
|
|
```
|
|
|
|
## Layered Architecture
|
|
|
|
### Определение
|
|
**Layered Architecture** — это архитектурный паттерн, который организует код в горизонтальные слои.
|
|
|
|
### Слои
|
|
1. **Presentation Layer** — пользовательский интерфейс
|
|
2. **Application Layer** — бизнес-логика приложения
|
|
3. **Domain Layer** — доменная логика
|
|
4. **Infrastructure Layer** — внешние зависимости
|
|
|
|
### Пример реализации
|
|
```java
|
|
// Presentation Layer
|
|
@RestController
|
|
@RequestMapping("/api/orders")
|
|
public class OrderController {
|
|
|
|
@Autowired
|
|
private OrderApplicationService orderService;
|
|
|
|
@PostMapping
|
|
public ResponseEntity<OrderResponse> createOrder(@RequestBody CreateOrderRequest request) {
|
|
OrderResponse response = orderService.createOrder(request);
|
|
return ResponseEntity.ok(response);
|
|
}
|
|
}
|
|
|
|
// Application Layer
|
|
@Service
|
|
public class OrderApplicationService {
|
|
|
|
@Autowired
|
|
private OrderRepository orderRepository;
|
|
|
|
@Autowired
|
|
private PaymentService paymentService;
|
|
|
|
public OrderResponse createOrder(CreateOrderRequest request) {
|
|
// Применение бизнес-правил
|
|
Order order = new Order(request);
|
|
|
|
// Обработка платежа
|
|
PaymentResult payment = paymentService.processPayment(order);
|
|
|
|
if (payment.isSuccess()) {
|
|
order.confirm();
|
|
orderRepository.save(order);
|
|
}
|
|
|
|
return OrderResponse.fromOrder(order);
|
|
}
|
|
}
|
|
|
|
// Domain Layer
|
|
public class Order {
|
|
private String id;
|
|
private String customerId;
|
|
private OrderStatus status;
|
|
private BigDecimal amount;
|
|
|
|
public void confirm() {
|
|
if (this.status != OrderStatus.DRAFT) {
|
|
throw new IllegalStateException("Cannot confirm non-draft order");
|
|
}
|
|
this.status = OrderStatus.CONFIRMED;
|
|
}
|
|
}
|
|
|
|
// Infrastructure Layer
|
|
@Repository
|
|
public class JpaOrderRepository implements OrderRepository {
|
|
|
|
@PersistenceContext
|
|
private EntityManager entityManager;
|
|
|
|
@Override
|
|
public void save(Order order) {
|
|
entityManager.persist(order);
|
|
}
|
|
}
|
|
```
|
|
|
|
## Serverless Architecture
|
|
|
|
### Определение
|
|
**Serverless Architecture** — это архитектурный стиль, при котором приложение состоит из функций, которые выполняются в ответ на события.
|
|
|
|
### Характеристики
|
|
- **FaaS** — Functions as a Service
|
|
- **Event-driven** — функции запускаются по событиям
|
|
- **Auto-scaling** — автоматическое масштабирование
|
|
- **Pay-per-use** — оплата только за использование
|
|
|
|
### Пример реализации
|
|
```java
|
|
// AWS Lambda функция
|
|
public class OrderProcessor implements RequestHandler<OrderEvent, String> {
|
|
|
|
@Override
|
|
public String handleRequest(OrderEvent event, Context context) {
|
|
// Обработка заказа
|
|
Order order = processOrder(event);
|
|
|
|
// Отправка уведомления
|
|
sendNotification(order);
|
|
|
|
return "Order processed successfully";
|
|
}
|
|
|
|
private Order processOrder(OrderEvent event) {
|
|
// Логика обработки заказа
|
|
return new Order(event);
|
|
}
|
|
|
|
private void sendNotification(Order order) {
|
|
// Отправка уведомления
|
|
}
|
|
}
|
|
|
|
// Azure Functions
|
|
@FunctionName("ProcessOrder")
|
|
public String processOrder(
|
|
@HttpTrigger(name = "req", methods = {HttpMethod.POST}, authLevel = AuthorizationLevel.ANONYMOUS)
|
|
HttpRequestMessage<Optional<String>> request,
|
|
ExecutionContext context) {
|
|
|
|
String orderData = request.getBody().orElse("");
|
|
|
|
// Обработка заказа
|
|
Order order = processOrderData(orderData);
|
|
|
|
return "Order processed: " + order.getId();
|
|
}
|
|
```
|
|
|
|
## Выбор архитектурного стиля
|
|
|
|
### Факторы выбора
|
|
1. **Размер команды** — маленькая команда → монолит
|
|
2. **Сложность домена** — сложный домен → микросервисы
|
|
3. **Требования к масштабированию** — высокие → микросервисы
|
|
4. **Технологическое разнообразие** — разные технологии → микросервисы
|
|
5. **Время разработки** — быстрое время → монолит
|
|
|
|
### Рекомендации
|
|
- **Начните с монолита** — для большинства проектов
|
|
- **Переходите к микросервисам** — когда монолит становится проблемой
|
|
- **Используйте EDA** — для асинхронной обработки
|
|
- **Рассмотрите CQRS** — для сложных read/write требований
|
|
- **Применяйте Hexagonal** — для изоляции бизнес-логики
|