Kotlin: Kotlin项目设计详解
最后更新:2026-08-26
所有 24 课的知识汇于此——Charlie 从需求分析开始,设计 OrderProcessor 的领域模型、分层架构、技术选型和 API 契约,这是实战项目的第一步。
1. 你将学到
- 需求分析与领域建模:订单状态机、事件溯源
- 分层架构:Controller → Service → Repository → Domain
- 技术选型:Spring Boot + Coroutines + kotlinx.serialization + Ktor Client
- API 设计:RESTful 端点规划 + OpenAPI 文档
- Charlie 实战:OrderProcessor 架构图与数据库 Schema
2. 一个架构师的真实故事
(1) 痛点:没有设计的项目注定返工
Charlie 的团队曾跳过设计直接写代码,3 个月后发现领域模型不匹配业务需求,60% 的代码需要重写。损失:3 个月工期 + 2 个月返工。
(2) 设计先行的方法
TEXT
📖 仅展示
Week 1: Requirements → Domain Model → State Machine
Week 2: Architecture → Tech Stack → API Contract
Week 3: Database Schema → Module Boundaries → CI/CD Plan
Week 4+: Development (with clear blueprint)
设计投入 3 周,返工减少 60%。没有设计的"快速开发"是最慢的。
3. 需求分析与领域建模
(1) 核心需求
| 需求 | 描述 | 优先级 |
|---|---|---|
| 订单创建 | 客户下单,生成待支付订单 | P0 |
| 订单支付 | 支付成功后确认订单 | P0 |
| 订单发货 | 仓库发货,生成物流单号 | P0 |
| 订单取消 | 客户/系统取消订单,触发退款 | P0 |
| 高值订单路由 | 金额 > 10,000 USD 走 VIP 流水线 | P1 |
| 批量处理 | 支持每秒 5,000 笔订单吞吐 | P1 |
| 事件溯源 | 订单状态变更产生领域事件 | P2 |
(2) 领域模型
KOTLIN
// Core domain entities
data class Order(
val id: String,
val total: Double,
var status: OrderStatus,
val customerId: String,
val items: List`<OrderItem>`,
val createdAt: String,
var updatedAt: String?
)
data class OrderItem(val sku: String, val quantity: Int, val unitPrice: Double)
sealed class OrderStatus {
object Pending : OrderStatus()
data class Processing(val step: Int) : OrderStatus()
object Paid : OrderStatus()
object Shipped : OrderStatus()
object Delivered : OrderStatus()
data class Cancelled(val reason: String) : OrderStatus()
}
sealed class OrderEvent {
data class Created(val orderId: String, val total: Double) : OrderEvent()
data class PaymentReceived(val orderId: String, val amount: Double) : OrderEvent()
data class Shipped(val orderId: String, val trackingCode: String) : OrderEvent()
data class Cancelled(val orderId: String, val reason: String) : OrderEvent()
}
(3) 订单状态机
stateDiagram-v2
[*] --> Pending: Create Order
Pending --> Processing: Start Processing
Pending --> Cancelled: Customer Cancel
Processing --> Paid: Payment Success
Processing --> Cancelled: Payment Failed
Paid --> Shipped: Ship Order
Shipped --> Delivered: Delivery Confirmed
Delivered --> [*]
Cancelled --> [*]
4. 分层架构
(1) 四层架构
flowchart TD
A[Controller Layer<br/>REST API / Request Validation] --> B[Service Layer<br/>Business Logic / State Machine]
B --> C[Repository Layer<br/>Data Access / Persistence]
B --> D[Integration Layer<br/>External API Calls]
C --> E[(Database)]
D --> F[Payment Service]
D --> G[Inventory Service]
(2) 各层职责
| 层 | 职责 | 关键技术 |
|---|---|---|
| Controller | HTTP 请求处理、验证、响应 | Spring WebFlux、suspend |
| Service | 业务逻辑、状态机、事件发布 | Coroutines、sealed class |
| Repository | 数据持久化、查询 | R2DBC、JPA |
| Integration | 外部服务调用 | Ktor Client、Resilience4j |
(3) 项目模块结构
TEXT
📖 仅展示
order-processor/
├── build.gradle.kts
├── src/main/kotlin/com/order/
│ ├── Application.kt # Spring Boot main
│ ├── controller/
│ │ └── OrderController.kt # REST endpoints
│ ├── service/
│ │ ├── OrderService.kt # Business logic
│ │ └── OrderStateMachine.kt # State transitions
│ ├── repository/
│ │ ├── OrderRepository.kt # Data access
│ │ └── EventRepository.kt # Event store
│ ├── integration/
│ │ ├── PaymentClient.kt # Payment API
│ │ └── InventoryClient.kt # Inventory API
│ ├── domain/
│ │ ├── Order.kt # Entity
│ │ ├── OrderStatus.kt # Status enum
│ │ └── OrderEvent.kt # Domain events
│ ├── config/
│ │ └── AppConfig.kt # Configuration
│ └── exception/
│ └── OrderExceptions.kt # Custom exceptions
└── src/test/kotlin/com/order/
└── ... # Tests
5. 技术选型
| 领域 | 技术选择 | 原因 |
|---|---|---|
| 框架 | Spring Boot 3.2 + WebFlux | 成熟生态、协程支持 |
| 语言 | Kotlin 1.9 | 空安全、协程、data class |
| 异步 | kotlinx.coroutines | 结构化并发、suspend |
| 序列化 | kotlinx.serialization | 编译期安全、多格式 |
| 数据库 | PostgreSQL + R2DBC | 响应式驱动、协程友好 |
| HTTP 客户端 | Ktor Client | Kotlin 原生、协程支持 |
| 缓存 | Redis + kotlinx.coroutines | 异步缓存 |
| 测试 | JUnit 5 + MockK | Kotlin 原生 Mock |
| 监控 | Micrometer + Prometheus | 指标采集 |
6. API 设计
(1) RESTful 端点
KOTLIN
// API Endpoints
// POST /api/v1/orders - Create order
// GET /api/v1/orders - List orders (with pagination)
// GET /api/v1/orders/{id} - Get order by ID
// PATCH /api/v1/orders/{id}/status - Update order status
// DELETE /api/v1/orders/{id} - Cancel order
// GET /api/v1/orders/{id}/events - Get order event history
(2) 请求/响应 DTO
KOTLIN
// Request
data class CreateOrderRequest(
val customerId: String,
val items: List`<CreateOrderItemRequest>`,
val shippingAddress: AddressRequest?
)
data class CreateOrderItemRequest(
val sku: String,
val quantity: Int,
val unitPrice: Double
)
// Response
data class OrderResponse(
val id: String,
val total: Double,
val status: String,
val customerId: String,
val items: List`<OrderItemResponse>`,
val createdAt: String,
val updatedAt: String?
)
// Error
data class ErrorResponse(
val code: String,
val message: String,
val details: Map<String, String>? = null
)
(3) API 设计原则
| 原则 | 实践 |
|---|---|
| RESTful | 资源名词 + HTTP 方法语义 |
| 版本化 | 前缀 |
| 分页 | |
| 过滤 | |
| HATEOAS | 响应包含相关链接(可选) |
| 错误格式 | 统一 |
7. 数据库 Schema
SQL
CREATE TABLE orders (
id VARCHAR(20) PRIMARY KEY,
customer_id VARCHAR(20) NOT NULL,
total DECIMAL(12,2) NOT NULL DEFAULT 0,
status VARCHAR(20) NOT NULL DEFAULT 'PENDING',
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP
);
CREATE TABLE order_items (
id SERIAL PRIMARY KEY,
order_id VARCHAR(20) NOT NULL REFERENCES orders(id),
sku VARCHAR(50) NOT NULL,
quantity INT NOT NULL,
unit_price DECIMAL(10,2) NOT NULL
);
CREATE TABLE order_events (
id SERIAL PRIMARY KEY,
order_id VARCHAR(20) NOT NULL,
event_type VARCHAR(30) NOT NULL,
payload JSONB,
created_at TIMESTAMP NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_orders_status ON orders(status);
CREATE INDEX idx_orders_customer ON orders(customer_id);
CREATE INDEX idx_events_order ON order_events(order_id);
8. 完整示例:OrderProcessor 架构设计文档
KOTLIN
// ============================================
// OrderProcessor - Architecture Design
// Feature: Complete architecture blueprint
// ============================================
// --- Domain Layer ---
data class OrderItem(val sku: String, val qty: Int, val unitPrice: Double) {
val subtotal: Double get() = qty * unitPrice
}
sealed class OrderStatus {
object Pending : OrderStatus()
object Confirmed : OrderStatus()
object Shipped : OrderStatus()
object Delivered : OrderStatus()
data class Cancelled(val reason: String) : OrderStatus()
}
sealed class OrderEvent {
data class Created(val orderId: String, val total: Double, val customerId: String) : OrderEvent()
data class Confirmed(val orderId: String) : OrderEvent()
data class Shipped(val orderId: String, val trackingCode: String) : OrderEvent()
data class Delivered(val orderId: String) : OrderEvent()
data class Cancelled(val orderId: String, val reason: String) : OrderEvent()
}
data class Order(
val id: String,
val total: Double,
var status: OrderStatus,
val customerId: String,
val items: List`<OrderItem>`
)
// --- State Machine ---
object OrderStateMachine {
fun transition(current: OrderStatus, event: OrderEvent): OrderStatus = when {
current is OrderStatus.Pending && event is OrderEvent.Created -> OrderStatus.Pending
current is OrderStatus.Pending && event is OrderEvent.Confirmed -> OrderStatus.Confirmed
current is OrderStatus.Confirmed && event is OrderEvent.Shipped -> OrderStatus.Shipped
current is OrderStatus.Shipped && event is OrderEvent.Delivered -> OrderStatus.Delivered
current is OrderStatus.Pending && event is OrderEvent.Cancelled -> OrderStatus.Cancelled(event.reason)
current is OrderStatus.Confirmed && event is OrderEvent.Cancelled -> OrderStatus.Cancelled(event.reason)
else -> throw IllegalStateException("Invalid transition: $current + $event")
}
}
// --- Architecture Summary ---
fun main() {
println("=== OrderProcessor Architecture Design ===\n")
println("Tech Stack:")
println(" Framework: Spring Boot 3.2 + WebFlux")
println(" Language: Kotlin 1.9")
println(" Async: kotlinx.coroutines")
println(" Database: PostgreSQL + R2DBC")
println(" Cache: Redis")
println(" HTTP: Ktor Client")
println(" Testing: JUnit 5 + MockK")
println(" Monitoring: Micrometer + Prometheus")
println("\nOrder Status Machine:")
val order = Order("ORD-001", 299.99, OrderStatus.Pending, "CUST-001", emptyList())
val confirmed = OrderStateMachine.transition(order.status, OrderEvent.Confirmed("ORD-001"))
println(" Pending + Confirmed = $confirmed")
val shipped = OrderStateMachine.transition(confirmed, OrderEvent.Shipped("ORD-001", "TRK-ABC"))
println(" Confirmed + Shipped = $shipped")
val delivered = OrderStateMachine.transition(shipped, OrderEvent.Delivered("ORD-001"))
println(" Shipped + Delivered = $delivered")
println("\nAPI Endpoints:")
println(" POST /api/v1/orders - Create order")
println(" GET /api/v1/orders - List orders")
println(" GET /api/v1/orders/{id} - Get order")
println(" PATCH /api/v1/orders/{id}/status - Update status")
println(" DELETE /api/v1/orders/{id} - Cancel order")
println(" GET /api/v1/orders/{id}/events - Event history")
}
输出:
TEXT
📖 仅展示
=== OrderProcessor Architecture Design ===
Tech Stack:
Framework: Spring Boot 3.2 + WebFlux
Language: Kotlin 1.9
Async: kotlinx.coroutines
Database: PostgreSQL + R2DBC
Hashing: Redis
HTTP: Ktor Client
Testing: JUnit 5 + MockK
Monitoring: Micrometer + Prometheus
Order Status Machine:
Pending + Confirmed = Confirmed
Confirmed + Shipped = Shipped
Shipped + Delivered = Delivered
API Endpoints:
POST /api/v1/orders - Create order
GET /api/v1/orders - List orders
GET /api/v1/orders/{id} - Get order
PATCH /api/v1/orders/{id}/status - Update status
DELETE /api/v1/orders/{id} - Cancel order
GET /api/v1/orders/{id}/events - Event history
❓ 常见问题
Q 先设计数据库还是先设计 API?
A 先设计领域模型(DDD 方法),然后 API 和数据库都是领域模型的投影。领域模型是核心,API 和 Schema 是外围。
Q 事件溯源和 CRUD 有什么区别?
A CRUD 只存储当前状态,事件溯源存储所有状态变更事件。事件溯源支持审计、回溯和重放,但复杂度更高。建议先 CRUD,有需要再加事件。
Q R2DBC 和 JPA 怎么选?
A 新项目 + WebFlux + 协程推荐 R2DBC(非阻塞);已有 JPA 项目或团队不熟悉响应式可以用 JPA + 协程扩展。
Q 微服务应该多小?
A 一个微服务围绕一个限界上下文(Bounded Context)。OrderProcessor 是"订单处理"上下文,不应该把支付、库存也塞进来。
Q API 版本化怎么做?
A URL 路径版本化()最简单直观。Header 版本化更 RESTful但更复杂。推荐 URL 版本化。
Q 如何确保架构设计能落地?
A 每个架构决策都要有 POC(概念验证)代码。纸上架构 + 可运行的原型 = 可落地的设计。
📖 小节
- 需求分析 → 领域建模 → 状态机 → 架构 → 技术选型 → API → 数据库
- 分层架构:Controller → Service → Repository → Integration
- 密封类建模订单状态机,编译器强制穷尽检查
- 技术选型:Spring Boot + WebFlux + Coroutines + R2DBC
- RESTful API 设计:资源名词 + HTTP 方法 + 版本化 + 统一错误格式
- 事件溯源:存储状态变更事件,支持审计和重放
📝 作业
- 基础题(难度⭐):用 为一个简单的任务管理系统设计状态机(Todo → InProgress → Done / Cancelled)。提示:
- 进阶题(难度⭐⭐):设计一个完整的 RESTful API 契约,包含 5 个端点的请求/响应 data class。提示: /
- 挑战题(难度⭐⭐⭐):为一个电商系统设计完整的分层架构文档,包含领域模型、状态机、API、数据库 Schema 和技术选型。提示:参考本课所有章节