# 第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 示例**: ```plantuml @startuml entity User { * id : Long <> -- * username : String(50) * email : String(100) * role_id : Long <> } entity Role { * id : Long <> -- * name : String(20) } User }o--|| Role : "拥有" note right of User : 聚合根 @enduml ``` **约束要求**: - 必须表达实体关系(1:1, 1:N, M:N) - 字段需与数据库一致(类型、长度、默认值) - 标注聚合关系(哪些是聚合根) **数据库设计详解** **SQL DDL 示例**: ```sql -- 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 示例**: ```yaml 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 时序图示例**: ```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) - 标注关键步骤(参数校验、业务规则校验) **专题设计详解** **专题设计示例**: ```markdown # 权限设计方案 ## 策略 - 使用 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 **原则**: 1. 约定大于配置 2. 编排逻辑和原子能力分离 3. 操作者和被操作对象分离 **常见 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 可能不知道项目的最佳实践 **打样工程的优势**: 1. 提高代码质量:基于模版生成,质量有保障 2. 统一代码风格:所有代码遵循相同的风格 3. 减少 Review 成本:代码符合规范,Review 更快 4. 知识沉淀:最佳实践沉淀在模版中 **三层架构详解** **Controller 层**: - 职责:接收请求、参数校验、调用 Service - 输入:Command/Query 对象 - 输出:Response 对象 - 不包含业务逻辑 **Service 层**: - 职责:编排业务逻辑、调用 DomainService/Repository - AppService:应用服务,编排逻辑 - DomainService:领域服务,复杂业务逻辑 - Repository:数据访问 **Repository 层**: - 职责:数据持久化 - 输入:实体对象 - 输出:实体对象或 PO(Persistent Object) **工序详解** **简单 CRUD(无复用逻辑)**: ```java // Controller @PostMapping("/users") public Response 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(有复用逻辑)**: ```java // 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("用户名已存在"); } } ``` **复杂查询**: ```java // Controller @GetMapping("/users") public Response> listUsers(@Valid UserQuery query) { return Response.success(userAppService.list(query)); } // AppService public Page list(UserQuery query) { Page page = userRepository.findByQuery(query); return page.map(UserResponse::from); } // Repository public Page findByQuery(UserQuery query) { // 构建查询条件 // 执行分页查询 // 返回分页结果 } ``` ### 实践建议 - 建立打样工程:提供标准的代码模版 - 分层清晰:Controller、Service、Repository 职责明确 - 工序标准化:简单 CRUD、复杂 CRUD、复杂查询各有标准 - AI 参考打样:让 AI 根据打样工程生成代码 --- ## 第18页:如何多任务同步开发? ### 原文内容 使用 git 的 Worktree 功能同时把一个仓库的多个分支映射到不同文件夹。Claude Code、Codex、Cursor 等已经自动支持使用 subagent 创建 Worktree,加速开发。 ```bash # 基于已有分支创建 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 的优势**: 1. 并行开发:多个 AI 实例可以同时工作在不同分支 2. 上下文隔离:每个功能的上下文独立,不会混淆 3. 快速切换:不需要 `git checkout`,直接切换目录 4. 节省空间:共享 .git 目录 **使用场景** **场景1:多 AI 实例并行开发** ```bash # 主工作区:开发功能 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 + 人工并行开发** ```bash # AI 在 feature-a 开发 cd /project/feature-a claude-code # 人工在 main 分支修复紧急 bug cd /project/main # 手动修复 bug ``` **场景3:Code Review 时继续开发** ```bash # 主工作区:feature-a 提交 PR,等待 review # 新开工作区:继续开发 feature-b git worktree add -b feature-b ../feature-b cd ../feature-b claude-code ``` **Worktree 管理** **列出所有工作区**: ```bash git worktree list # 输出: # /project/main abc1234 [main] # /project/feature-a def5678 [feature-a] # /project/feature-b ghi9012 [feature-b] ``` **清理工作区**: ```bash # 删除工作区(会自动删除目录) 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 权限) ``` **核心思想**: 1. Plan 阶段尽可能锁定上下文到 Plan 中,关闭所有的开放性问题 2. Plan 中记录实现状态,让任务可以分批完成或者重试 3. 需要给出确定性的验收方式:例如通过所有的 API 测试,让 AI 能建立自我修复标准 **Loop 规则(API 为例,放到 AGENTS.md 作为开发流程要求)**: 1. **Plan 等待确认**:在 docs/plans 下根据模版创建 Plan 2. **编写 API 测试**:根据 Plan 实现 API 测试,运行成功并断言失败 3. **编写实现**:编写单元测试 + 实现代码,通过编译 4. **运行 API 测试**:运行测试,并修复失败的测试和其他错误 ### 深入解读 **什么是核心 Loop?** - 定义:AI 自治运行的开发循环 - 目标:通过 TDD 驱动,AI 自动实现需求并修复问题 - 特点:Plan 阶段人机协作,执行阶段 AI 自治 **Loop 的三个阶段** **阶段1:Plan(规划)** - 输入:需求规格、技术规格 - 输出:实现方案、任务列表 - 关键:关闭所有开放性问题 - 人工介入:确认 Plan 是否合理 **阶段2:执行(Implementation)** - 输入:Plan - 输出:API 测试、实现代码 - 关键:按照 Plan 逐步实现 - AI 自治:无需人工介入 **阶段3:验证(Verification)** - 输入:API 测试、实现代码 - 输出:测试结果、修复建议 - 关键:所有测试通过 - AI 自治:自动运行测试,自动修复 **Plan 模版示例**: ```markdown # 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 测试** ```java @Test public void testCreateUser() { CreateUserRequest request = new CreateUserRequest(); request.setUsername("testuser"); request.setEmail("test@example.com"); request.setPassword("Password123"); Response 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 response = userClient.create(request2); assertEquals(409, response.getCode()); assertEquals("用户名已存在", response.getMessage()); } ``` **步骤2:运行测试(断言失败)** ```bash mvn test -Dtest=UserApiTest # 预期:测试失败(因为没有实现) ``` **步骤3:编写实现代码** ```java // Controller @PostMapping("/users") public Response 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:运行测试(通过)** ```bash mvn test -Dtest=UserApiTest # 预期:所有测试通过 ``` **ByPass 权限** - 定义:AI 在某些情况下可以跳过某些步骤 - 场景: - 测试环境不可用 - 第三方服务不可用 - 紧急修复 - 控制:在 AGENTS.md 中定义 ByPass 规则 **Loop 的退出条件** 1. 所有 API 测试通过 2. 所有单元测试通过 3. 代码符合规范(Lint 通过) 4. 没有编译错误 ### 实践建议 - Plan 阶段充分沟通:关闭所有开放性问题 - TDD 驱动:先写测试再写代码 - AI 自治运行:执行阶段无需人工介入 - 记录实现状态:方便复盘和优化 - ByPass 权限控制:紧急情况可以跳过某些步骤 --- ## 本章小结 **开发实现的核心要点**: 1. 让 AI 听话:规则、规格、技能三要素 2. 构建上下文体系:区分过程方案和事实方案 3. 调用外部工具:MCP、Skills、CLI 4. 选择合适的工具:命令行类、AI IDE、增强插件 5. SDD 框架:BMAD、Spec Kit、OpenSpec、Kiro 6. 技术规格 DSL 驱动:领域模型、数据库、API、时序图、专题设计 7. 打样工程:让 AI 抄作业 8. 多任务同步开发:Git Worktree 9. 核心 Loop:Plan → TDD → 验证 **关键工具**: - Claude Code、Cursor、Kiro - MCP Server、Skills - PlantUML、OpenAPI - Git Worktree **最佳实践**: - AGENTS.md 作为宪法 - 区分 Plans(过程)和 Designs(事实) - 使用 DSL 编写技术规格 - 建立打样工程 - TDD 驱动开发