迭代计划准备
This commit is contained in:
34
AGENTS.md
34
AGENTS.md
@@ -72,18 +72,23 @@ handlers := &bootstrap.Handlers{
|
||||
- 使用 `net/http` 替代 Fiber
|
||||
- 使用 `encoding/json` 替代 sonic(除非必要)
|
||||
|
||||
## 架构分层
|
||||
## 架构演进:MVC 与 DDD 共存
|
||||
|
||||
必须遵循以下分层架构:
|
||||
项目采用**触碰式渐进迁移**,不安排一次性全仓库重构。详细规则见 `docs/7月迭代/DDD规范.md`。
|
||||
|
||||
```
|
||||
Handler → Service → Store → Model
|
||||
```
|
||||
### 三条执行通道
|
||||
|
||||
- **Handler**: 只处理 HTTP 请求/响应,不包含业务逻辑
|
||||
- **Service**: 包含所有业务逻辑,支持跨模块调用
|
||||
- **Store**: 统一管理所有数据访问,支持事务处理
|
||||
- **Model**: 定义数据结构和 DTO
|
||||
- **复杂写操作**:`Handler → Application UseCase → Domain → Repository/Infrastructure`。适用于状态机、金额、库存、并发不变量、策略和可靠事件。
|
||||
- **简单写操作**:`Handler → Application 事务脚本 → Persistence`。单表 CRUD 不强行创建聚合。
|
||||
- **读取操作**:`Handler → Query → GORM/DTO`。列表、详情、联表、统计、报表和导出不经过聚合根。
|
||||
|
||||
### 触碰式迁移约束
|
||||
|
||||
1. 禁止主动迁移当前需求未触碰的旧模块;简单字段、筛选和局部修复默认沿用旧结构。
|
||||
2. 迁移单位是**完整用例**,不是整个模块、文件或数据表;一旦迁移,相关业务不变量必须完整收口,禁止一半留在旧 Service、一半放在 Domain。
|
||||
3. 当前需求触碰复杂写逻辑时,只迁移完成该需求所需的最小完整业务边界;旧 Service 可暂时作为内部代码迁移门面调用新 UseCase,但这不等于必须保留旧 HTTP 接口。
|
||||
4. 当前需求触碰复杂只读逻辑时,只迁移该查询到 `internal/query/<context>`;Query 可直接使用 GORM 做联表、聚合、权限过滤和 DTO 投影。
|
||||
5. 不为追求 DDD 形式创建无业务价值的接口、工厂和目录;架构选择不明确时先阅读 DDD 规范并写明判断依据。
|
||||
|
||||
## 核心原则
|
||||
|
||||
@@ -97,7 +102,7 @@ Handler → Service → Store → Model
|
||||
|
||||
- Handler 层禁止直接返回/拼接底层错误信息给客户端(例如 `"参数验证失败: "+err.Error()`、`err.Error()`)
|
||||
- 参数校验失败:对外统一返回 `errors.New(errors.CodeInvalidParam)`(详细校验错误写日志)
|
||||
- Service 层禁止对外返回 `fmt.Errorf(...)`,必须返回 `errors.New(...)` 或 `errors.Wrap(...)`
|
||||
- Service/Application/Domain/Query 层禁止向接口调用方直接返回 `fmt.Errorf(...)`,必须转换为 `errors.New(...)` 或 `errors.Wrap(...)`
|
||||
- 约定用法:`errors.New(code[, msg])`、`errors.Wrap(code, err[, msg])`
|
||||
|
||||
### 响应格式
|
||||
@@ -194,6 +199,7 @@ StatusName string `json:"status_name" description:"状态名称(中文)"` //
|
||||
- 文档文件名和内容使用中文
|
||||
- 同步更新 README.md
|
||||
- 为导出的函数、类型编写文档注释
|
||||
- 需要进入评审的标准/完整技术方案必须覆盖关键流程、前后端契约、异常闭环、发布回滚和待决策项;简单改动不强行画图。详细要求见 `docs/技术方案评审规范.md`
|
||||
|
||||
## 函数复杂度
|
||||
|
||||
@@ -225,14 +231,16 @@ StatusName string `json:"status_name" description:"状态名称(中文)"` //
|
||||
|
||||
### 错误处理
|
||||
|
||||
- [ ] Service 层无 `fmt.Errorf` 对外返回
|
||||
- [ ] Service/Application/Domain/Query 层无 `fmt.Errorf` 对外返回
|
||||
- [ ] Handler 层参数校验不泄露细节
|
||||
- [ ] 错误码使用正确(4xx vs 5xx)
|
||||
- [ ] 错误日志完整(包含上下文)
|
||||
|
||||
### 代码质量
|
||||
|
||||
- [ ] 遵循 Handler → Service → Store → Model 分层
|
||||
- [ ] 已按判断标准选择复杂写、简单写或 Query 通道,未扩大迁移范围
|
||||
- [ ] 复杂写规则收口 Domain;简单写使用 Application 事务脚本;只读逻辑不经过聚合根
|
||||
- [ ] Query 负责读取权限、分页和 DTO 投影,写操作仍在 Domain 重新校验
|
||||
- [ ] 函数长度 ≤ 100 行(核心逻辑 ≤ 50 行)
|
||||
- [ ] 常量定义在 `pkg/constants/`
|
||||
- [ ] 使用 Go 惯用法(非 Java 风格)
|
||||
@@ -309,7 +317,7 @@ queueClient.EnqueueTask(ctx, constants.TaskTypeXxx, payloadBytes)
|
||||
|
||||
**适用场景**:任何敏感操作(账号管理、权限变更、数据删除等)
|
||||
|
||||
- Service 层注入 `auditService AuditServiceInterface`,操作成功后调用 `LogOperation()`
|
||||
- 旧模块在 Service 层、新 DDD 模块在 Application UseCase 中注入审计能力,操作成功后调用 `LogOperation()`
|
||||
- 必填字段:`OperatorID`、`OperationType`、`OperationDesc`、`BeforeData`、`AfterData`
|
||||
- 异步写入(Goroutine),写入失败不影响业务,失败时记录 Error 日志
|
||||
|
||||
|
||||
Reference in New Issue
Block a user