Files
pig-farm-controller/openspec/changes/refactor-business-logic-layering/design.md
2025-10-31 15:16:21 +08:00

4.8 KiB
Raw Blame History

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

  • 暂无。