Update from Sync Service
This commit is contained in:
692
AI工程/团队级AI_Coding简明手册_逐页研究/02_开发实现续_第16-19页.md
Executable file
692
AI工程/团队级AI_Coding简明手册_逐页研究/02_开发实现续_第16-19页.md
Executable file
@@ -0,0 +1,692 @@
|
||||
# 第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 <<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 示例**:
|
||||
```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<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(有复用逻辑)**:
|
||||
```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<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,加速开发。
|
||||
|
||||
```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<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:运行测试(断言失败)**
|
||||
```bash
|
||||
mvn test -Dtest=UserApiTest
|
||||
# 预期:测试失败(因为没有实现)
|
||||
```
|
||||
|
||||
**步骤3:编写实现代码**
|
||||
```java
|
||||
// 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:运行测试(通过)**
|
||||
```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 驱动开发
|
||||
Reference in New Issue
Block a user