19 KiB
Executable File
第16-19页:开发实现续篇(技术规格 + 打样 + 多任务 + 核心Loop)
章节:02 开发实现(续) 核心问题:技术规格如何编写?如何让 AI 抄作业?如何多任务同步开发?核心 Loop 如何运转?
第16页:技术规格如何编写?
原文内容
技术规格的5个模块(DSL 驱动):
| 模块 | 表达标准 | 格式 | 产出内容 | 约束/规范 |
|---|---|---|---|---|
| 领域模型 | PlantUML/Smart Domain | .puml | 实体、属性、关系(ER/类图) | 必须表达实体关系;字段需与数据库一致;标注聚合关系 |
| 数据库 | SQL DDL/DBML/Flyway 脚本 | .sql | 表结构、索引、约束 | 必须可执行;包含索引和外键;字段与领域模型一致 |
| API | OpenAPI 3.x | .yaml/.json | 接口定义、请求/响应结构 | 必须定义 schema;禁止只写接口说明;字段与模型一致 |
| 时序图 | PlantUML | .puml | 调用流程、系统交互 | 必须反映真实调用链;建议包含异常分支(alt) |
| 专题设计 | Markdown | .md | 架构策略(权限/事务/缓存等) | 只写"策略与规则",不重复 API/DDL;强调设计决策 |
深入解读
为什么用 DSL?
- 可执行:DDL 可以直接运行,OpenAPI 可以生成代码
- AI 友好:LLM 对 DSL 的理解比自然语言更精确
- 一致性保证:DSL 有语法规则,不容易产生歧义
领域模型详解
PlantUML 示例:
@startuml
entity User {
* id : Long <<PK>>
--
* username : String(50)
* email : String(100)
* role_id : Long <<FK>>
}
entity Role {
* id : Long <<PK>>
--
* name : String(20)
}
User }o--|| Role : "拥有"
note right of User : 聚合根
@enduml
约束要求:
- 必须表达实体关系(1:1, 1:N, M:N)
- 字段需与数据库一致(类型、长度、默认值)
- 标注聚合关系(哪些是聚合根)
数据库设计详解
SQL DDL 示例:
-- Flyway migration: V1__create_users_table.sql
CREATE TABLE users (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) NOT NULL UNIQUE,
email VARCHAR(100) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL,
role_id BIGINT NOT NULL,
status TINYINT(1) DEFAULT 1,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_username (username),
INDEX idx_email (email),
CONSTRAINT fk_user_role FOREIGN KEY (role_id) REFERENCES roles(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
必须可执行:
- DDL 必须可以直接在数据库中运行
- 使用 Flyway/Liquibase 管理版本
- 包含索引(查询性能)和外键(数据完整性)
API 设计详解
OpenAPI 3.x 示例:
openapi: 3.0.3
info:
title: User API
version: 1.0.0
paths:
/api/v1/users:
post:
summary: 创建用户
tags: [User]
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateUserRequest'
responses:
'201':
description: 创建成功
content:
application/json:
schema:
$ref: '#/components/schemas/UserResponse'
'400':
description: 参数错误
components:
schemas:
CreateUserRequest:
type: object
required: [username, email, password]
properties:
username:
type: string
minLength: 3
maxLength: 50
description: 登录用户名,唯一
email:
type: string
format: email
description: 电子邮箱,唯一
password:
type: string
minLength: 8
description: 密码,≥8位含大小写
UserResponse:
type: object
properties:
id:
type: integer
format: int64
username:
type: string
email:
type: string
role:
type: string
enum: [admin, user]
status:
type: boolean
约束要求:
- 必须定义 schema(请求和响应的结构)
- 禁止只写接口说明("返回用户列表"这种描述不够)
- 字段与领域模型一致(类型、名称、约束)
时序图详解
PlantUML 时序图示例:
@startuml
actor User
participant "UserController" as C
participant "UserService" as S
participant "UserRepository" as R
database "MySQL" as DB
User -> C: POST /api/v1/users
C -> C: 参数校验
C -> S: createUser(CreateUserRequest)
S -> S: 业务规则校验
S -> R: save(User)
R -> DB: INSERT INTO users ...
DB --> R: 返回结果
R --> S: 返回 User
S --> C: 返回 UserResponse
C --> User: 201 Created
alt 用户名已存在
S --> C: throw DuplicateException
C --> User: 409 Conflict
end
@enduml
约束要求:
- 必须反映真实调用链
- 建议包含异常分支(alt)
- 标注关键步骤(参数校验、业务规则校验)
专题设计详解
专题设计示例:
# 权限设计方案
## 策略
- 使用 RBAC(基于角色的访问控制)
- 权限注解:@RequirePermission("user:create")
- 默认拒绝所有未授权的请求
## 规则
1. 管理员角色拥有所有权限
2. 普通用户只能操作自己的数据
3. 敏感操作需要二次确认
## 设计决策
- 选择 RBAC 而非 ABAC:业务场景简单,角色固定
- 权限存储在 Redis:减少数据库查询
- 权限变更实时生效:通过 Redis Pub/Sub 通知
约束要求:
- 只写"策略与规则"
- 不重复 API/DDL(避免信息冗余)
- 强调设计决策(为什么选择这个方案)
实践建议
- 使用 DSL:统一技术规格的表示方式
- 保持一致性:领域模型、数据库、API 要一致
- AI 辅助生成:让 AI 根据规格生成代码
- 版本控制:技术规格纳入 Git 管理
第17页:打样工程:如何让 AI 抄作业?
原文内容
参考代码:https://github.com/domain-driven-design/ddd-microservices
原则:
- 约定大于配置
- 编排逻辑和原子能力分离
- 操作者和被操作对象分离
常见 CQRUD 操作的工序:
1. 简单 CRUD:
Controller + Command → AppService → Repository → Response 对象
2. 复杂或有复用逻辑的 CRUD:
Controller + Command → AppService → DomainService → Repository → Response 对象
3. 复杂的查询操作:
Controller + Query 对象 → AppService → QueryPO(或复用 PO)→ Response 对象
深入解读
什么是打样工程?
- 定义:提供代码模版和示例,让 AI 参考生成代码
- 目的:保证代码风格统一、质量稳定
- 核心理念:让 AI "抄作业",而不是自由发挥
为什么需要打样工程?
- AI 生成的代码质量不稳定
- 不同 AI 工具生成的代码风格不同
- AI 可能不知道项目的最佳实践
打样工程的优势:
- 提高代码质量:基于模版生成,质量有保障
- 统一代码风格:所有代码遵循相同的风格
- 减少 Review 成本:代码符合规范,Review 更快
- 知识沉淀:最佳实践沉淀在模版中
三层架构详解
Controller 层:
- 职责:接收请求、参数校验、调用 Service
- 输入:Command/Query 对象
- 输出:Response 对象
- 不包含业务逻辑
Service 层:
- 职责:编排业务逻辑、调用 DomainService/Repository
- AppService:应用服务,编排逻辑
- DomainService:领域服务,复杂业务逻辑
- Repository:数据访问
Repository 层:
- 职责:数据持久化
- 输入:实体对象
- 输出:实体对象或 PO(Persistent Object)
工序详解
简单 CRUD(无复用逻辑):
// Controller
@PostMapping("/users")
public Response<UserResponse> createUser(@Valid @RequestBody CreateUserCommand cmd) {
return Response.success(userAppService.create(cmd));
}
// AppService
public UserResponse create(CreateUserCommand cmd) {
User user = userRepository.save(User.from(cmd));
return UserResponse.from(user);
}
// Repository
public User save(User user) {
userMapper.insert(user);
return user;
}
复杂 CRUD(有复用逻辑):
// AppService - 编排逻辑
public UserResponse create(CreateUserCommand cmd) {
// 1. 校验用户名唯一
domainService.checkUsernameUnique(cmd.getUsername());
// 2. 加密密码
String encryptedPassword = domainService.encryptPassword(cmd.getPassword());
// 3. 保存用户
User user = User.from(cmd, encryptedPassword);
userRepository.save(user);
// 4. 发送欢迎邮件
domainService.sendWelcomeEmail(user);
return UserResponse.from(user);
}
// DomainService - 原子能力
public void checkUsernameUnique(String username) {
if (userRepository.existsByUsername(username)) {
throw new BusinessException("用户名已存在");
}
}
复杂查询:
// Controller
@GetMapping("/users")
public Response<Page<UserResponse>> listUsers(@Valid UserQuery query) {
return Response.success(userAppService.list(query));
}
// AppService
public Page<UserResponse> list(UserQuery query) {
Page<UserPO> page = userRepository.findByQuery(query);
return page.map(UserResponse::from);
}
// Repository
public Page<UserPO> findByQuery(UserQuery query) {
// 构建查询条件
// 执行分页查询
// 返回分页结果
}
实践建议
- 建立打样工程:提供标准的代码模版
- 分层清晰:Controller、Service、Repository 职责明确
- 工序标准化:简单 CRUD、复杂 CRUD、复杂查询各有标准
- AI 参考打样:让 AI 根据打样工程生成代码
第18页:如何多任务同步开发?
原文内容
使用 git 的 Worktree 功能同时把一个仓库的多个分支映射到不同文件夹。Claude Code、Codex、Cursor 等已经自动支持使用 subagent 创建 Worktree,加速开发。
# 基于已有分支创建
git worktree add ../feature-login feature/login
# 创建新分支 + 工作区(最常用)
git worktree add -b feature-payment ../feature-payment
# 查看所有 worktree
git worktree list
# 删除工作区
git worktree remove ../feature-login
深入解读
什么是 Git Worktree?
- 定义:Git 的一个功能,允许你从同一个仓库检出多个工作目录
- 每个工作目录都是一个独立的分支
- 共享同一个 .git 目录(节省磁盘空间)
为什么需要 Worktree?
- AI 编程时,经常需要同时开发多个功能
- 传统方式:切换分支,容易丢失上下文
- Worktree:每个功能在独立的目录,互不干扰
Worktree 的优势:
- 并行开发:多个 AI 实例可以同时工作在不同分支
- 上下文隔离:每个功能的上下文独立,不会混淆
- 快速切换:不需要
git checkout,直接切换目录 - 节省空间:共享 .git 目录
使用场景
场景1:多 AI 实例并行开发
# 主工作区:开发功能 A
cd /project/feature-a
claude-code # 启动 Claude Code
# 新开终端:开发功能 B
cd /project/feature-b
claude-code # 启动另一个 Claude Code 实例
# 再开终端:开发功能 C
cd /project/feature-c
claude-code # 启动第三个 Claude Code 实例
场景2:AI + 人工并行开发
# AI 在 feature-a 开发
cd /project/feature-a
claude-code
# 人工在 main 分支修复紧急 bug
cd /project/main
# 手动修复 bug
场景3:Code Review 时继续开发
# 主工作区:feature-a 提交 PR,等待 review
# 新开工作区:继续开发 feature-b
git worktree add -b feature-b ../feature-b
cd ../feature-b
claude-code
Worktree 管理
列出所有工作区:
git worktree list
# 输出:
# /project/main abc1234 [main]
# /project/feature-a def5678 [feature-a]
# /project/feature-b ghi9012 [feature-b]
清理工作区:
# 删除工作区(会自动删除目录)
git worktree remove ../feature-a
# 强制删除(即使有未提交的更改)
git worktree remove --force ../feature-a
# 清理已删除的工作区记录
git worktree prune
AI 工具自动支持:
- Claude Code:自动创建 Worktree 进行并行开发
- Codex CLI:支持在独立工作区运行
- Cursor:可以在多个窗口打开不同 Worktree
实践建议
- 使用 Worktree 并行开发:提高开发效率
- 命名规范:工作区目录名与分支名一致
- 及时清理:完成的功能及时删除 Worktree
- AI 工具支持:利用 AI 工具的自动 Worktree 功能
第19页:完整的核心 Loop 过程(研发自测)
原文内容
核心理念:通过 TDD/浏览器调试(前端),AI 自治运行
Loop 流程图:
开始进入循环
↓
[Chat] 进入 Plan 模式
↓
装载需求规格,给出指令进行 Plan
↓
[Chat] 符合要求,退出 Plan 模式,开始执行?
↓ 是
[模型] 读取 Plan
↓
创建 API 测试,实现代码
↓
[模型] 运行测试/浏览器调试,是否成功?
↓ 否
重复多次 / 白天持续很久 / 夜间
↓ 是
[模型] 退出循环
↓
(给予 ByPass 权限)
核心思想:
- Plan 阶段尽可能锁定上下文到 Plan 中,关闭所有的开放性问题
- Plan 中记录实现状态,让任务可以分批完成或者重试
- 需要给出确定性的验收方式:例如通过所有的 API 测试,让 AI 能建立自我修复标准
Loop 规则(API 为例,放到 AGENTS.md 作为开发流程要求):
- Plan 等待确认:在 docs/plans 下根据模版创建 Plan
- 编写 API 测试:根据 Plan 实现 API 测试,运行成功并断言失败
- 编写实现:编写单元测试 + 实现代码,通过编译
- 运行 API 测试:运行测试,并修复失败的测试和其他错误
深入解读
什么是核心 Loop?
- 定义:AI 自治运行的开发循环
- 目标:通过 TDD 驱动,AI 自动实现需求并修复问题
- 特点:Plan 阶段人机协作,执行阶段 AI 自治
Loop 的三个阶段
阶段1:Plan(规划)
- 输入:需求规格、技术规格
- 输出:实现方案、任务列表
- 关键:关闭所有开放性问题
- 人工介入:确认 Plan 是否合理
阶段2:执行(Implementation)
- 输入:Plan
- 输出:API 测试、实现代码
- 关键:按照 Plan 逐步实现
- AI 自治:无需人工介入
阶段3:验证(Verification)
- 输入:API 测试、实现代码
- 输出:测试结果、修复建议
- 关键:所有测试通过
- AI 自治:自动运行测试,自动修复
Plan 模版示例:
# Plan: 实现用户注册功能
## 目标
实现用户注册 API,支持邮箱验证
## 任务列表
- [ ] 1. 创建数据库表 users
- [ ] 2. 实现 POST /api/v1/users API
- [ ] 3. 实现邮箱验证逻辑
- [ ] 4. 编写单元测试
- [ ] 5. 编写 API 测试
## 实现方案
1. 使用 Flyway 创建 users 表
2. Controller 接收 CreateUserCommand
3. AppService 调用 UserRepository 保存
4. 发送验证邮件(使用 JavaMail)
## 验收标准
- 所有单元测试通过
- 所有 API 测试通过
- 代码符合阿里巴巴 Java 开发手册
## 状态
- 开始时间:2026-06-20 10:00
- 预计完成:2026-06-20 12:00
- 实际完成:待更新
TDD 驱动详解
步骤1:编写 API 测试
@Test
public void testCreateUser() {
CreateUserRequest request = new CreateUserRequest();
request.setUsername("testuser");
request.setEmail("test@example.com");
request.setPassword("Password123");
Response<UserResponse> response = userClient.create(request);
assertEquals(201, response.getCode());
assertNotNull(response.getData().getId());
assertEquals("testuser", response.getData().getUsername());
}
@Test
public void testCreateUser_DuplicateUsername() {
// 先创建一个用户
CreateUserRequest request1 = new CreateUserRequest();
request1.setUsername("testuser");
request1.setEmail("test1@example.com");
request1.setPassword("Password123");
userClient.create(request1);
// 再创建一个同名用户
CreateUserRequest request2 = new CreateUserRequest();
request2.setUsername("testuser");
request2.setEmail("test2@example.com");
request2.setPassword("Password123");
Response<UserResponse> response = userClient.create(request2);
assertEquals(409, response.getCode());
assertEquals("用户名已存在", response.getMessage());
}
步骤2:运行测试(断言失败)
mvn test -Dtest=UserApiTest
# 预期:测试失败(因为没有实现)
步骤3:编写实现代码
// Controller
@PostMapping("/users")
public Response<UserResponse> createUser(@Valid @RequestBody CreateUserRequest request) {
return Response.success(userAppService.create(request));
}
// AppService
public UserResponse create(CreateUserRequest request) {
// 校验用户名唯一
if (userRepository.existsByUsername(request.getUsername())) {
throw new BusinessException(409, "用户名已存在");
}
// 加密密码
String encryptedPassword = passwordEncoder.encode(request.getPassword());
// 保存用户
User user = User.from(request, encryptedPassword);
userRepository.save(user);
// 发送验证邮件
emailService.sendVerificationEmail(user);
return UserResponse.from(user);
}
步骤4:运行测试(通过)
mvn test -Dtest=UserApiTest
# 预期:所有测试通过
ByPass 权限
- 定义:AI 在某些情况下可以跳过某些步骤
- 场景:
- 测试环境不可用
- 第三方服务不可用
- 紧急修复
- 控制:在 AGENTS.md 中定义 ByPass 规则
Loop 的退出条件
- 所有 API 测试通过
- 所有单元测试通过
- 代码符合规范(Lint 通过)
- 没有编译错误
实践建议
- Plan 阶段充分沟通:关闭所有开放性问题
- TDD 驱动:先写测试再写代码
- AI 自治运行:执行阶段无需人工介入
- 记录实现状态:方便复盘和优化
- ByPass 权限控制:紧急情况可以跳过某些步骤
本章小结
开发实现的核心要点:
- 让 AI 听话:规则、规格、技能三要素
- 构建上下文体系:区分过程方案和事实方案
- 调用外部工具:MCP、Skills、CLI
- 选择合适的工具:命令行类、AI IDE、增强插件
- SDD 框架:BMAD、Spec Kit、OpenSpec、Kiro
- 技术规格 DSL 驱动:领域模型、数据库、API、时序图、专题设计
- 打样工程:让 AI 抄作业
- 多任务同步开发:Git Worktree
- 核心 Loop:Plan → TDD → 验证
关键工具:
- Claude Code、Cursor、Kiro
- MCP Server、Skills
- PlantUML、OpenAPI
- Git Worktree
最佳实践:
- AGENTS.md 作为宪法
- 区分 Plans(过程)和 Designs(事实)
- 使用 DSL 编写技术规格
- 建立打样工程
- TDD 驱动开发