datai/datai-scenes/datai-scene-salesforce/docs/retros/2026-02-06-003-05-retro.md

12 KiB
Raw Blame History

复盘文档 - 删除操作

元数据

  • 需求编号003-05
  • 创建时间2026-02-06
  • 创建人AI Assistant
  • 状态:已完成

复盘概述

本次复盘对 Salesforce Metadata API 删除操作功能的开发过程进行了全面回顾。从需求定义到变更记录的每个阶段都严格按照 SSOT 流程执行,确保了代码的可追溯性和可维护性。本次开发实现了元数据删除、批量删除和删除历史查询功能,支持分批处理(每批 10 个,符合 Salesforce API 限制)和异步日志记录。

目标与实际产出对比

目标

  • 实现元数据删除功能,支持单个和批量删除操作
  • 正确处理 Salesforce Metadata API 的删除结果和错误信息
  • 实现数据库持久化,记录删除历史和状态
  • 提供完整的 REST API 接口3 个接口)
  • 遵循 SSOT 流程,确保所有开发活动都有文档依据
  • 生成符合项目规范的代码,包含单元测试

实际产出

  • 成功实现元数据删除功能,支持单个和批量删除
  • 正确处理删除结果,实现了 DeleteResultVo 转换类
  • 实现了分批处理逻辑,每批 10 个(符合 Salesforce API 限制)
  • 实现了异步日志记录,使用 @Async 注解
  • 提供了 3 个 REST API 接口:
    • POST /salesforce/metadata/delete/{type} - 单个删除
    • POST /salesforce/metadata/delete/batch - 批量删除
    • GET /salesforce/metadata/delete/history - 历史查询
  • 创建了 datai_metadata_delete12 个字段5 个索引)
  • 定义了 4 个专用错误码DELETE_001 ~ DELETE_004
  • 生成了 13 个代码文件6 个手动 + 7 个代码生成器)
  • 编写了 10 个单元测试用例,覆盖成功/失败/分批/异常场景
  • 严格按照 SSOT 流程执行,每个阶段都有相应的文档

成功经验

1. 代码生成器与手动实现的良好结合

经验描述:在阶段 6 中,先使用代码生成器生成基础 CRUD 代码Entity、Mapper、基础 Service然后手动实现业务逻辑代码DTO、VO、业务 Service、Controller。这种方式既保证了代码的规范性又满足了业务需求。

具体实践

  • 代码生成器生成了 DataiMetadataDelete Entity、DataiMetadataDeleteMapper 等基础代码
  • 手动实现了 DeleteRequest DTO、DeleteResultVo VO、IMetadataDeleteService 接口和 MetadataDeleteServiceImpl 实现
  • 手动实现了 MetadataDeleteController 提供 REST API 接口

带来的好处

  • 减少了重复劳动,提高了开发效率
  • 保证了基础代码的规范性和一致性
  • 业务逻辑代码更加清晰、可维护

2. 分批处理策略的有效实施

经验描述:针对 Salesforce Metadata API 每次最多删除 10 个元数据的限制,设计了循环分批处理逻辑,确保批量删除操作的正确执行。

具体实现

int totalCount = fullNames.length;
for (int i = 0; i < totalCount; i += BATCH_SIZE) {
    int end = Math.min(i + BATCH_SIZE, totalCount);
    String[] batch = Arrays.copyOfRange(fullNames, i, end);
    DeleteResult[] results = connection.deleteMetadata(type, batch);
    // 处理结果...
}

带来的好处

  • 符合 Salesforce API 限制,避免调用失败
  • 代码逻辑清晰,易于理解和维护
  • 支持任意数量的批量删除

3. 异步日志记录的性能优化

经验描述:使用 Spring 的 @Async 注解实现异步日志记录,避免日志写入阻塞主业务流程,提高了 API 响应速度。

具体实现

@Async("threadPoolTaskExecutor")
public void logDeleteHistoryAsync(String type, DeleteResult result) {
    // 异步记录删除历史
}

带来的好处

  • 主业务流程不被日志写入阻塞
  • 提高了 API 响应速度
  • 解耦了业务逻辑和日志记录

4. 完整的单元测试覆盖

经验描述:为 Service 层编写了 10 个单元测试用例,覆盖了成功场景、失败场景、分批处理场景和异常场景。

测试覆盖

  • 单个删除成功场景
  • 单个删除失败场景
  • 批量删除成功场景
  • 批量删除分批处理场景
  • 批量删除部分失败场景
  • 连接异常场景
  • 参数校验场景

带来的好处

  • 确保了代码的正确性
  • 便于后续重构和维护
  • 提高了代码质量

改进点

1. API 限流和重试机制可以考虑

问题描述:当前实现没有针对 Salesforce API 的限流和重试机制。如果 API 调用频率过高,可能会触发 Salesforce 的限流策略。

改进建议

  • 添加限流控制,限制每秒/每分钟的 API 调用次数
  • 添加重试机制,对于临时性错误(如网络超时)进行自动重试
  • 使用断路器模式,防止级联故障

优先级:中 计划时间:下一个迭代

2. 批量删除的事务性可以考虑

问题描述:当前批量删除是串行执行,单个失败不影响其他请求,但没有事务性保证。如果某个批次失败,无法回滚已成功的批次。

改进建议

  • 调研 Salesforce Metadata API 是否支持事务性操作
  • 考虑在业务层实现补偿机制
  • 记录每个批次的执行状态,支持部分回滚

优先级:低 计划时间:后续迭代

3. 删除历史的查询优化可以考虑

问题描述:当前删除历史查询是基于 MyBatis Plus 的简单查询,如果数据量很大,查询性能可能会下降。

改进建议

  • 添加分页查询支持
  • 添加更多查询条件(按时间范围、按类型、按状态等)
  • 考虑使用缓存优化频繁查询

优先级:中 计划时间:下一个迭代

问题分析

问题 1代码生成器生成的 Controller 与业务需求不完全匹配

问题描述:代码生成器生成的 DataiMetadataDeleteController 是通用的 CRUD 接口,但业务需要的是特定的删除操作接口(调用 Salesforce Metadata API

根因分析

  • 代码生成器基于数据库表结构生成通用 CRUD 代码
  • 业务需求涉及外部 API 调用,超出了代码生成器的范围

解决方案

  • 保留代码生成器生成的代码作为基础
  • 手动创建新的 MetadataDeleteController 实现业务接口
  • 在后续开发中,明确区分代码生成器代码和手动实现代码

预防措施

  • 在需求分析阶段明确哪些代码需要手动实现
  • 在代码生成后,立即检查生成的代码是否满足业务需求

问题 2单元测试中 Mock 的复杂性

问题描述:在编写单元测试时,需要 Mock MetadataConnectionDeleteResult 等 Salesforce API 类,增加了测试编写的复杂性。

根因分析

  • Salesforce API 类的构造函数和方法是私有的或复杂的
  • 需要模拟各种场景(成功、失败、异常等)

解决方案

  • 使用 Mockito 的 mock() 方法创建 Mock 对象
  • 使用 when().thenReturn() 设置 Mock 行为
  • 使用 doThrow().when() 模拟异常场景

预防措施

  • 在编写业务代码时,考虑可测试性
  • 使用依赖注入,便于 Mock 替换
  • 编写详细的测试用例文档

行动计划

序号 行动项 责任人 计划时间 优先级
1 添加 API 限流和重试机制 开发团队 下一个迭代
2 优化删除历史查询(分页、条件查询) 开发团队 下一个迭代
3 调研批量删除事务性方案 开发团队 后续迭代
4 更新代码生成器模板,增加业务接口提示 AI Assistant 立即执行
5 编写单元测试最佳实践文档 AI Assistant 立即执行

提取模式

有效的 Prompt 技巧

1. 明确的代码生成策略

技巧描述:在提示词中明确说明哪些代码使用代码生成器生成,哪些代码需要手动实现,可以提高代码生成的准确性和效率。

应用示例

## 代码生成策略
- **代码生成器生成**Entity、Mapper、基础 Service、基础 Controller
- **手动实现**DTO、VO、业务 Service 接口、业务 Service 实现、业务 Controller、单元测试

效果

  • 避免了代码生成器生成不符合业务需求的代码
  • 明确了开发边界,提高了开发效率

2. 详细的接口定义

技巧描述:在提示词中详细定义 REST API 接口的请求方式、请求路径、请求参数、响应参数等,可以确保生成的接口符合设计要求。

应用示例

### 接口 1删除元数据
- **请求方式**POST
- **请求路径**`/salesforce/metadata/delete/{type}`
- **请求参数**
  - `type`元数据类型String必填
  - `fullNames`元数据完整名称列表String[],必填)
- **响应参数**
  - `code`状态码Integer
  - `msg`提示信息String
  - `data`删除结果列表List<DeleteResultVo>

效果

  • 生成的接口与设计完全一致
  • 减少了后续修改的工作量

3. 具体的错误码定义

技巧描述:在提示词中定义具体的错误码和错误信息,可以确保错误处理的一致性和可维护性。

应用示例

## 错误码定义
- DELETE_001Salesforce 连接失败
- DELETE_002删除元数据失败
- DELETE_003批量删除失败
- DELETE_004参数校验失败

效果

  • 错误码统一、规范
  • 便于前端处理和用户提示
  • 便于日志分析和问题定位

避免的坑

1. 不要忽略代码生成器的局限性

坑描述:代码生成器只能生成通用的 CRUD 代码,对于涉及外部 API 调用的业务逻辑,需要手动实现。

避免方法

  • 在需求分析阶段明确代码生成器的适用范围
  • 代码生成后立即检查是否满足业务需求
  • 准备好手动实现业务逻辑的预案

2. 不要忽略单元测试的复杂性

坑描述:涉及外部 API 的代码单元测试比较复杂,需要 Mock 外部依赖,如果忽略这一点,可能导致测试覆盖不足。

避免方法

  • 在设计阶段考虑可测试性
  • 使用依赖注入,便于 Mock
  • 预留足够的测试编写时间

3. 不要违反 Salesforce API 限制

坑描述Salesforce Metadata API 有调用限制(如每次最多删除 10 个元数据),如果忽略这一点,可能导致 API 调用失败。

避免方法

  • 仔细阅读 Salesforce API 文档
  • 在代码中实现分批处理逻辑
  • 添加限流和重试机制

模板迭代

经过本次复盘,发现当前的提示词模板在以下方面可以改进:

1. 增加代码生成策略说明

在提示词模板中增加"代码生成策略"章节,明确说明哪些代码使用代码生成器生成,哪些代码需要手动实现。

建议更新

## 代码生成策略
- **代码生成器生成**Entity、Mapper、基础 Service、基础 Controller、DTO、VO
- **手动实现**:业务 Service 接口、业务 Service 实现、业务 Controller、单元测试
- **说明**:代码生成器基于数据库表结构生成通用 CRUD 代码,业务逻辑代码需要手动实现

2. 增加外部 API 调用提示

在提示词模板中增加"外部 API 调用"提示,提醒开发者注意外部 API 的限制和异常处理。

建议更新

## 外部 API 调用提示
- 注意外部 API 的调用限制(如 Salesforce Metadata API 每次最多删除 10 个元数据)
- 实现分批处理逻辑,确保符合 API 限制
- 添加异常处理捕获连接异常、API 异常等
- 考虑添加限流和重试机制

3. 增加单元测试提示

在提示词模板中增加"单元测试"提示,提醒开发者注意 Mock 外部依赖和覆盖各种场景。

建议更新

## 单元测试提示
- 使用 Mockito Mock 外部依赖(如 Salesforce API 类)
- 覆盖成功场景、失败场景、异常场景
- 测试分批处理逻辑
- 测试参数校验逻辑
- 使用 @Mock@InjectMocks 注解

相关文档