From db11438f5c8526491591385f8c3e8b25db646a15 Mon Sep 17 00:00:00 2001 From: huang <1724659546@qq.com> Date: Fri, 31 Oct 2025 15:16:21 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A1=AB=E5=85=85design.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../design.md | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 openspec/changes/refactor-business-logic-layering/design.md diff --git a/openspec/changes/refactor-business-logic-layering/design.md b/openspec/changes/refactor-business-logic-layering/design.md new file mode 100644 index 0000000..e7a2a1b --- /dev/null +++ b/openspec/changes/refactor-business-logic-layering/design.md @@ -0,0 +1,63 @@ +## 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`)的方法, 存在逻辑被无意中删除或修改的风险。 + - **缓解措施**: + 1. **代码审查**:在重构前后仔细比对原有逻辑, 确保其被完整地迁移到了新的服务层方法中。 + 2. **保留原有实现**:在新的服务层方法中, 将严格按照控制器中原有的顺序——先构建查询选项, 再调用仓库, 最后进行数据转换——来组织代码, 确保逻辑的等效性。 + 3. **测试**:在完成重构后, 必须进行完整的回归测试, 确保所有受影响的 API 端点的行为与重构前完全一致。 + +## Migration Plan + +本次重构将按以下步骤进行: + +1. **修改服务层 (`internal/app/service/monitor_service.go`)** + - **更新接口**:修改 `MonitorService` 接口中所有 `List...` 方法的签名, 使其接收请求 DTO 并返回响应 DTO。 + - **实现数据转换**:在每个 `List...` 方法的实现中, 添加从请求 DTO 到 `repository.ListOptions` 的转换逻辑, 以及从业仓库返回的 `models` 到响应 DTO 的转换逻辑。对于 `ListPlanExecutionLogs` 等方法, 确保原有的附加业务逻辑(如查询关联 `Plan` 信息)被完整保留。 + +2. **修改控制器层 (`internal/app/controller/monitor/monitor_controller.go`)** + - **移除转换逻辑**:删除所有手动构建 `repository.ListOptions` 和调用 `dto.NewList...Response` 的代码。 + - **更新服务调用**:修改对 `monitorService` 的调用, 使其传递完整的请求 DTO, 并直接处理返回的响应 DTO。 + - **简化日志**:调整日志记录, 以便从服务层返回的 DTO 中获取列表长度和总记录数。 + +3. **验证** + - 通过静态代码分析和审查, 确认代码风格和逻辑的正确性。 + - 进行完整的单元测试和集成测试, 以确保重构没有引入任何回归问题。 + +## Open Questions + +- 暂无。