4.8 KiB
4.8 KiB
Context
当前, monitor 模块的数据转换逻辑(例如, 将 repository 层返回的 models 实体转换为 dto 对象)主要存在于 internal/app/controller/monitor/monitor_controller.go 文件中。
这种设计导致了以下问题:
- 职责不清:控制器层承担了过多的数据处理任务, 违反了“关注点分离”原则。控制器应主要负责处理 HTTP 请求、参数绑定和调用服务, 而非执行业务或数据转换逻辑。
- 代码重复:如果未来有其他服务需要类似的数据转换, 可能会导致代码重复。
- 可测试性差:由于转换逻辑与
echo.Context紧密耦合, 对其进行单元测试变得更加复杂。
Goals / Non-Goals
Goals
- 迁移数据转换逻辑:将
monitor模块中所有的数据转换逻辑从控制器层 (monitor_controller.go) 迁移到服务层 (monitor_service.go)。 - 统一服务层接口:使服务层的方法直接接收请求 DTO, 并返回响应 DTO, 从而使服务本身成为一个完整的、自包含的业务逻辑单元。
- 简化控制器:精简控制器中的代码, 使其只关注其核心职责:请求处理和响应发送。
Non-Goals
- 不修改业务逻辑:本次重构不涉及任何已有业务规则的变更。例如,
ListPlanExecutionLogs中获取关联计划信息的逻辑必须保持不变。 - 不改变 API 契约:API 的请求参数和响应结构对最终用户保持不变。
- 不引入新的依赖:仅在现有框架和依赖下进行代码调整。
Decisions
-
决策:在服务层完成 DTO 转换
- 理由:服务层是封装业务逻辑的核心, 将数据从领域模型 (
models) 转换为外部表示 (dto) 是业务服务的一部分。这样做可以确保任何调用该服务的客户端(无论是控制器、gRPC 服务还是其他服务)都能获得一致的、随时可用的数据结构。 - 替代方案:曾考虑在
dto包中创建一个独立的转换层。但最终认为, 将转换逻辑内聚到服务层更能体现其业务属性, 因为服务层最清楚需要暴露哪些数据以及如何组织这些数据。
- 理由:服务层是封装业务逻辑的核心, 将数据从领域模型 (
-
决策:修改服务层接口以直接处理 DTO
- 具体实现:计划将
MonitorService接口中的所有List...方法签名从ListSomething(opts repository.ListOptions, page, pageSize int) ([]models.Something, int64, error)修改为ListSomething(req *dto.ListSomethingRequest) (*dto.ListSomethingResponse, error)。 - 理由:这种设计将极大地简化控制器与服务之间的交互。控制器将不再需要手动构建
repository.ListOptions或在调用服务后手动组装响应 DTO。它只需传递请求 DTO, 然后直接使用服务返回的响应 DTO, 从而实现彻底的解耦。
- 具体实现:计划将
Risks / Trade-offs
- 风险:意外修改或丢失现有业务逻辑
- 描述:在移动代码的过程中, 尤其是像
ListPlanExecutionLogs这样包含特定业务逻辑(获取关联plans)的方法, 存在逻辑被无意中删除或修改的风险。 - 缓解措施:
- 代码审查:在重构前后仔细比对原有逻辑, 确保其被完整地迁移到了新的服务层方法中。
- 保留原有实现:在新的服务层方法中, 将严格按照控制器中原有的顺序——先构建查询选项, 再调用仓库, 最后进行数据转换——来组织代码, 确保逻辑的等效性。
- 测试:在完成重构后, 必须进行完整的回归测试, 确保所有受影响的 API 端点的行为与重构前完全一致。
- 描述:在移动代码的过程中, 尤其是像
Migration Plan
本次重构将按以下步骤进行:
-
修改服务层 (
internal/app/service/monitor_service.go)- 更新接口:修改
MonitorService接口中所有List...方法的签名, 使其接收请求 DTO 并返回响应 DTO。 - 实现数据转换:在每个
List...方法的实现中, 添加从请求 DTO 到repository.ListOptions的转换逻辑, 以及从业仓库返回的models到响应 DTO 的转换逻辑。对于ListPlanExecutionLogs等方法, 确保原有的附加业务逻辑(如查询关联Plan信息)被完整保留。
- 更新接口:修改
-
修改控制器层 (
internal/app/controller/monitor/monitor_controller.go)- 移除转换逻辑:删除所有手动构建
repository.ListOptions和调用dto.NewList...Response的代码。 - 更新服务调用:修改对
monitorService的调用, 使其传递完整的请求 DTO, 并直接处理返回的响应 DTO。 - 简化日志:调整日志记录, 以便从服务层返回的 DTO 中获取列表长度和总记录数。
- 移除转换逻辑:删除所有手动构建
-
验证
- 通过静态代码分析和审查, 确认代码风格和逻辑的正确性。
- 进行完整的单元测试和集成测试, 以确保重构没有引入任何回归问题。
Open Questions
- 暂无。