以下是一个结合 领域驱动设计(DDD)、行为驱动开发(BDD) 和 测试驱动开发(TDD) 的完整微服务开发流程,以电商系统(订单服务、库存服务)为例,使用 Node.js 和 JavaScript 实现。
一、阶段划分与核心活动
1. 战略设计阶段(DDD 核心)
- 目标:划分限界上下文(Bounded Context),明确微服务边界
- 活动:
- 事件风暴(Event Storming):识别领域事件、命令、聚合根
- 上下文映射:定义订单服务与库存服务的交互方式(如同步调用、异步事件)
- 输出:
- 限界上下文清单:
Order Context
, Inventory Context
- 上下文映射图:订单服务通过
OrderPlaced
事件驱动库存扣减
工具与环境
- 协作工具:Miro(在线白板) + 领域事件卡片模板
- 代码辅助:
1 2 3 4 5 6 7 8
| interface OrderPlacedEvent { eventType: "ORDER_PLACED"; payload: { orderId: string; items: Array<{ productId: string; quantity: number }>; }; }
|
2. 战术设计阶段(DDD 实现)
- 目标:实现领域模型(聚合根、实体、值对象、领域服务)
- 活动:
- 聚合根设计:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| class Order { constructor(orderId, userId, items) { this._id = orderId; this.status = "CREATED"; this.items = items; }
place() { if (this.items.length === 0) throw new Error("Empty order"); this.status = "PLACED"; DomainEventPublisher.publish(new OrderPlacedEvent(this)); } }
|
- 仓储接口定义:
1 2 3 4 5
| class OrderRepository { async save(order) { } async findById(orderId) { } }
|
工具与验证
- 类图工具:PlantUML 或 Visual Paradigm
- TDD 验证模型:
1 2 3 4 5 6 7 8 9
| test("订单创建后状态应为CREATED", () => { const order = new Order("order-1", "user-1", [item1, item2]); expect(order.status).toBe("CREATED"); });
test("提交空订单应抛出异常", () => { expect(() => new Order("order-2", "user-1", [])).toThrow(); });
|
3. 开发实现阶段(TDD+BDD 驱动)
步骤 1 - BDD 定义用户故事
1 2 3 4 5 6
| Feature: 订单提交 场景: 用户提交有效订单 当 用户请求创建包含2件商品A的订单 那么 订单状态变为PLACED 并且 触发库存扣减事件
|
步骤 2 - TDD 实现内部逻辑
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| const { PlaceOrderService } = require('../../src/application/PlaceOrderService'); const MockOrderRepository = require('../mocks/MockOrderRepository');
test("提交订单应保存到仓库并发布事件", async () => { const mockRepo = new MockOrderRepository(); const service = new PlaceOrderService(mockRepo);
const orderId = await service.execute({ userId: "user-1", items: [...] }); expect(mockRepo.saveCalled).toBe(true); expect(DomainEventPublisher.events).toContainEqual( expect.objectContaining({ eventType: "ORDER_PLACED" }) ); });
|
步骤 3 - 实现基础设施层
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| class MongoOrderRepository extends OrderRepository { constructor(db) { super(); this.collection = db.collection('orders'); }
async save(order) { await this.collection.updateOne( { _id: order.id }, { $set: order.toJSON() }, { upsert: true } ); } }
|
4. 集成与测试阶段
跨服务测试(BDD+契约测试)
1 2 3 4 5
| Feature: 库存扣减 场景: 接收订单已创建事件 当 订单服务发布ORDER_PLACED事件 那么 库存服务应减少对应商品库存
|
工具链配置
- 本地开发环境:
1 2 3 4 5 6 7 8 9 10
| services: order-service: build: ./order ports: ["3000:3000"] inventory-service: build: ./inventory ports: ["3001:3000"] rabbitmq: image: rabbitmq:3-management
|
- 契约测试工具(Pact):
1 2 3 4 5 6 7 8 9 10 11 12
| const pact = new Pact({ consumer: "OrderService", provider: "InventoryService", port: 1234 });
pact.addInteraction({ state: "商品A库存充足", uponReceiving: "库存扣减请求", willRespondWith: { status: 200 } });
|
五、持续交付阶段
CI/CD 流水线(GitHub Actions 示例)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| name: DDD+BDD+TDD Pipeline on: [push]
jobs: build-and-test: runs-on: ubuntu-latest services: mongodb: image: mongo:5.0 ports: ["27017:27017"] rabbitmq: image: rabbitmq:3-management ports: ["5672:5672"]
steps: - name: Checkout uses: actions/checkout@v3
- name: Setup Node.js uses: actions/setup-node@v3 with: node-version: 18.x
- name: Install Dependencies run: npm ci
- name: Run Unit Tests (TDD) run: npm test:unit
- name: Run BDD Tests run: npm test:bdd env: ORDER_SERVICE_URL: http://localhost:3000 INVENTORY_SERVICE_URL: http://localhost:3001
- name: Pact Verification run: npm run test:pact
|
六、监控与维护
关键工具
- 日志聚合:ELK Stack(Elasticsearch + Logstash + Kibana)
- 链路追踪:Jaeger 或 Zipkin
- 健康检查:
1 2 3 4 5 6 7 8 9 10
| router.get('/health', (req, res) => { res.json({ status: 'UP', checks: [ { name: "MongoDB", status: checkMongo() ? "UP" : "DOWN" }, { name: "RabbitMQ", status: checkRabbitMQ() ? "UP" : "DOWN" } ] }); });
|
七、核心工具链总结
领域 |
工具/技术栈 |
DDD建模 |
Event Storming + PlantUML |
BDD测试 |
Cucumber.js + Gherkin + Allure Report |
TDD测试 |
Jest + Sinon + Testcontainers |
基础设施 |
Docker + Kubernetes + RabbitMQ |
监控 |
Prometheus + Grafana + Jaeger |
契约测试 |
Pact |
八、典型代码结构(订单服务)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| /src /domain # 领域模型 Order.js OrderItem.js /application # 应用服务 PlaceOrderService.js /infrastructure /repositories MongoOrderRepository.js /messaging RabbitMQEventPublisher.js /interfaces /rest OrderController.js /graphql OrderResolver.js /test /unit # TDD测试 Order.test.js /bdd # BDD步骤定义 orderSteps.js
|
通过这种分层架构,开发者可以:
- 使用 DDD 确保业务逻辑在代码中清晰体现
- 通过 TDD 保证每个领域对象的正确性
- 通过 BDD 验证跨服务的端到端流程
- 利用 CI/CD 实现自动化质量门禁
例如在电商场景中:
- DDD 明确
Order
和 Inventory
的限界上下文边界
- TDD 确保
Order.place()
方法正确发布领域事件
- BDD 验证用户下单后库存同步扣减的业务流程
- Pact 保障订单服务与库存服务的接口契约一致性