Files
Alexander Abakumov 15e744da49 Initial commit: Complete Software Architecture course with 11 modules
- 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
2025-09-09 22:08:07 +03:00

365 lines
9.4 KiB
Markdown

# Реализация архитектуры
## Навигация
- [🏠 Главная страница курса](../../../README.md)
- [📚 Модуль 11](../README.md)
---
## Структура проекта
### 1. Monorepo Structure
```
ecommerce-platform/
├── services/
│ ├── user-service/
│ │ ├── src/
│ │ ├── Dockerfile
│ │ ├── pom.xml
│ │ └── README.md
│ ├── product-service/
│ ├── order-service/
│ ├── payment-service/
│ └── inventory-service/
├── frontend/
│ ├── customer-app/
│ ├── admin-app/
│ └── shared/
├── infrastructure/
│ ├── kubernetes/
│ ├── terraform/
│ └── docker-compose/
├── docs/
│ ├── architecture/
│ ├── api/
│ └── deployment/
└── scripts/
├── build.sh
├── deploy.sh
└── test.sh
```
### 2. Service Implementation
```java
// Order Service Implementation
@RestController
@RequestMapping("/api/orders")
@Validated
public class OrderController {
@Autowired
private OrderService orderService;
@PostMapping
public ResponseEntity<OrderResponse> createOrder(
@Valid @RequestBody CreateOrderRequest request) {
Order order = orderService.createOrder(request);
OrderResponse response = OrderMapper.toResponse(order);
return ResponseEntity.status(HttpStatus.CREATED).body(response);
}
@GetMapping("/{id}")
public ResponseEntity<OrderResponse> getOrder(@PathVariable Long id) {
Order order = orderService.getOrder(id);
OrderResponse response = OrderMapper.toResponse(order);
return ResponseEntity.ok(response);
}
@PutMapping("/{id}/status")
public ResponseEntity<OrderResponse> updateOrderStatus(
@PathVariable Long id,
@Valid @RequestBody UpdateOrderStatusRequest request) {
Order order = orderService.updateOrderStatus(id, request.getStatus());
OrderResponse response = OrderMapper.toResponse(order);
return ResponseEntity.ok(response);
}
}
@Service
@Transactional
public class OrderService {
@Autowired
private OrderRepository orderRepository;
@Autowired
private OrderEventPublisher eventPublisher;
@Autowired
private InventoryServiceClient inventoryClient;
@Autowired
private PaymentServiceClient paymentClient;
public Order createOrder(CreateOrderRequest request) {
// Валидация заказа
validateOrderRequest(request);
// Создание заказа
Order order = new Order(request);
order = orderRepository.save(order);
// Резервирование товаров
inventoryClient.reserveItems(order.getId(), request.getItems());
// Публикация события
eventPublisher.publishOrderCreated(order);
return order;
}
public Order updateOrderStatus(Long orderId, OrderStatus status) {
Order order = orderRepository.findById(orderId)
.orElseThrow(() -> new OrderNotFoundException("Order not found: " + orderId));
order.updateStatus(status);
order = orderRepository.save(order);
// Публикация события
eventPublisher.publishOrderStatusUpdated(order);
return order;
}
private void validateOrderRequest(CreateOrderRequest request) {
if (request.getItems().isEmpty()) {
throw new ValidationException("Order must contain at least one item");
}
// Дополнительные проверки...
}
}
```
## Проектирование API
### 1. REST API Specification
```yaml
# OpenAPI Specification
openapi: 3.0.0
info:
title: E-commerce Platform API
version: 1.0.0
description: API for e-commerce platform
servers:
- url: https://api.ecommerce.com/v1
description: Production server
paths:
/orders:
post:
summary: Create a new order
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateOrderRequest'
responses:
'201':
description: Order created successfully
content:
application/json:
schema:
$ref: '#/components/schemas/OrderResponse'
'400':
description: Bad request
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/orders/{id}:
get:
summary: Get order by ID
parameters:
- name: id
in: path
required: true
schema:
type: integer
responses:
'200':
description: Order retrieved successfully
content:
application/json:
schema:
$ref: '#/components/schemas/OrderResponse'
'404':
description: Order not found
components:
schemas:
CreateOrderRequest:
type: object
required:
- customerId
- items
properties:
customerId:
type: integer
format: int64
items:
type: array
items:
$ref: '#/components/schemas/OrderItem'
shippingAddress:
$ref: '#/components/schemas/Address'
paymentMethod:
$ref: '#/components/schemas/PaymentMethod'
OrderResponse:
type: object
properties:
id:
type: integer
format: int64
customerId:
type: integer
format: int64
status:
type: string
enum: [PENDING, CONFIRMED, SHIPPED, DELIVERED, CANCELLED]
totalAmount:
type: number
format: decimal
items:
type: array
items:
$ref: '#/components/schemas/OrderItem'
createdAt:
type: string
format: date-time
updatedAt:
type: string
format: date-time
```
### 2. Event Schema
```json
{
"orderCreated": {
"eventType": "OrderCreated",
"version": "1.0",
"timestamp": "2023-12-01T10:00:00Z",
"data": {
"orderId": "12345",
"customerId": "67890",
"items": [
{
"productId": "prod-001",
"quantity": 2,
"price": 29.99
}
],
"totalAmount": 59.98,
"status": "PENDING"
}
},
"orderStatusUpdated": {
"eventType": "OrderStatusUpdated",
"version": "1.0",
"timestamp": "2023-12-01T10:05:00Z",
"data": {
"orderId": "12345",
"oldStatus": "PENDING",
"newStatus": "CONFIRMED",
"updatedBy": "system"
}
}
}
```
## Проектирование базы данных
### 1. Database Schema
```sql
-- Order Service Database Schema
CREATE TABLE orders (
id BIGSERIAL PRIMARY KEY,
customer_id BIGINT NOT NULL,
status VARCHAR(20) NOT NULL DEFAULT 'PENDING',
total_amount DECIMAL(10,2) NOT NULL,
shipping_address JSONB,
payment_method JSONB,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE order_items (
id BIGSERIAL PRIMARY KEY,
order_id BIGINT NOT NULL REFERENCES orders(id),
product_id VARCHAR(50) NOT NULL,
quantity INTEGER NOT NULL,
unit_price DECIMAL(10,2) NOT NULL,
total_price DECIMAL(10,2) NOT NULL
);
CREATE TABLE order_events (
id BIGSERIAL PRIMARY KEY,
order_id BIGINT NOT NULL,
event_type VARCHAR(50) NOT NULL,
event_data JSONB NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Индексы для оптимизации
CREATE INDEX idx_orders_customer_id ON orders(customer_id);
CREATE INDEX idx_orders_status ON orders(status);
CREATE INDEX idx_orders_created_at ON orders(created_at);
CREATE INDEX idx_order_items_order_id ON order_items(order_id);
CREATE INDEX idx_order_events_order_id ON order_events(order_id);
```
### 2. Data Access Layer
```java
@Repository
public interface OrderRepository extends JpaRepository<Order, Long> {
List<Order> findByCustomerId(Long customerId);
List<Order> findByStatus(OrderStatus status);
@Query("SELECT o FROM Order o WHERE o.createdAt BETWEEN :startDate AND :endDate")
List<Order> findOrdersByDateRange(
@Param("startDate") LocalDateTime startDate,
@Param("endDate") LocalDateTime endDate
);
@Query("SELECT o FROM Order o WHERE o.customerId = :customerId AND o.status = :status")
List<Order> findByCustomerIdAndStatus(
@Param("customerId") Long customerId,
@Param("status") OrderStatus status
);
}
@Repository
public class OrderEventRepository {
@Autowired
private JdbcTemplate jdbcTemplate;
public void saveEvent(OrderEvent event) {
String sql = "INSERT INTO order_events (order_id, event_type, event_data) VALUES (?, ?, ?)";
jdbcTemplate.update(sql,
event.getOrderId(),
event.getEventType(),
event.getEventData()
);
}
public List<OrderEvent> findEventsByOrderId(Long orderId) {
String sql = "SELECT * FROM order_events WHERE order_id = ? ORDER BY created_at";
return jdbcTemplate.query(sql, new OrderEventRowMapper(), orderId);
}
}
```