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

415 lines
26 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# `monitor` 模块重构设计
## 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
- 暂无。
---
## `device` 模块重构设计
### Context
`device_controller.go` 当前直接依赖多个 `repository``domain.Service`,并在其方法内部执行了大量本应属于应用服务层的逻辑,包括:
- **直接的数据库操作**:调用 `repository``Create`, `Update`, `Delete`, `Find` 等方法。
- **领域模型实例化**:通过 `&models.Device{...}` 直接创建数据库模型。
- **内部字段序列化**:对 `Properties`, `Commands`, `Values` 等字段执行 `json.Marshal`
- **业务规则验证**:调用 `model.SelfCheck()`
- **复杂的错误处理**:通过 `errors.Is``strings.Contains` 解析底层数据库错误。
- **DTO 转换**:在方法末尾调用 `dto.New...Response`
这种设计导致控制器与基础设施层和领域层紧密耦合,违反了分层架构的原则。
### Goals / Non-Goals
#### Goals
- **创建应用服务层**:引入一个新的 `internal/app/service/device_service.go` 来封装业务逻辑。
- **迁移业务逻辑**:将上述所有在控制器中识别出的业务逻辑和数据处理任务,全部迁移到新的 `DeviceService` 中。
- **简化控制器**:使 `device_controller.go` 只负责 HTTP 请求处理和对新 `DeviceService` 的调用。
- **保持领域服务纯粹**:确保 `internal/domain/device/device_service.go` 继续专注于核心领域逻辑,不与 DTO 发生耦合。
#### Non-Goals
- **不改变领域服务**:不对 `domain.device.Service` 的接口和实现进行任何修改。
- **不改变 API 契约**:对外暴露的 API 接口、请求和响应格式保持不变。
### Decisions
- **决策:引入新的应用服务 `DeviceService`**
- **理由**:这是解决控制器职责过重和分层不清问题的标准做法。该服务将作为应用层门面,协调 `repository`
`domain.Service`,并为控制器提供一个清晰、稳定的接口。
- **结构**`DeviceService` 将依赖于 `DeviceRepository`, `AreaControllerRepository`, `DeviceTemplateRepository`
`domain.device.Service`
- **决策:`DeviceService` 接口全面采用 DTO**
- **具体实现**:接口方法将接收 `dto.Create...Request` 等请求 DTO并返回 `*dto....Response` 响应 DTO。
- **理由**:这与 `monitor` 模块的重构决策一致,可以确保应用服务层的接口统一、清晰,并与上层(控制器)和下层(领域/仓库)完全解耦。
### Migration Plan
1. **创建 `internal/app/service/device_service.go` 文件**
- 定义 `DeviceService` 接口,为控制器中的每个处理器方法(`CreateDevice`, `UpdateDevice`, `GetDevice`, `ListDevices`,
`DeleteDevice`, `ManualControl` 等)创建相应的方法。
- 定义 `deviceService` 结构体,并实现 `DeviceService` 接口。
- **`Create/Update` 方法实现**
1. 接收请求 DTO。
2. 执行 `json.Marshal` 转换 `Properties` 等字段。
3. 创建 `models.Xxx` 实例。
4. 调用 `model.SelfCheck()`
5. 调用 `repository.Create/Update`
6. 调用 `repository.FindByID` 重新加载模型(确保关联数据完整)。
7. 调用 `dto.New...Response` 将模型转换为响应 DTO 并返回。
- **`Get/List` 方法实现**
1. 调用 `repository.Find/List`
2. 调用 `dto.New...Response` 转换并返回。
- **`Delete` 方法实现**
1. 调用 `repository.Delete`
2. 捕获并转换特定的“资源被使用”错误。
- **`ManualControl` 方法实现**
1. 调用 `repository.FindByIDString` 加载模型。
2. 实现 `action` 字符串到 `device.DeviceAction` 的映射。
3. 调用 `domain.device.Service.Switch/Collect`
2. **修改 `internal/app/controller/device/device_controller.go`**
- **更新依赖**:将 `Controller` 的依赖从多个 `repository``domain.Service` 替换为唯一的
`app/service.DeviceService`
- **简化所有处理器方法**
1. 移除所有业务逻辑(`json.Marshal`, `SelfCheck`, `repository` 调用, `dto` 转换等)。
2. 每个方法仅保留:参数绑定、调用 `c.deviceService.Method(req)`、错误处理和成功响应。
3. **修改 `internal/core/component_initializers.go`**
-`AppServices` 结构体中增加 `DeviceService service.DeviceService` 字段。
-`initAppServices` 函数中,调用 `service.NewDeviceService` 创建实例,并将其注入到 `AppServices` 中。
4. **修改 `internal/app/api/api.go`**
- 更新 `NewAPI` 函数的参数,使其接收新的 `app/service.DeviceService`
- 更新 `device.NewController` 的调用,将多个仓库和领域服务的依赖替换为单一的 `DeviceService` 依赖。
### Open Questions
- 暂无。
---
## `pig-farm` 模块重构设计
### Context
`monitor` 模块类似, `pig_farm_controller.go` 当前包含了将 `service` 层返回的 `models.PigHouse``models.Pen`
实体手动转换为 `dto.PigHouseResponse``dto.PenResponse` 的逻辑。此外,
控制器还处理了部分本应由服务层处理的业务错误判断 (例如 `service.ErrHouseNotFound`)。
这种模式导致了与 `monitor` 模块相同的职责不清、代码重复和可测试性差的问题。
### Goals / Non-Goals
#### Goals
- **迁移数据转换逻辑**: 将 `pig-farm` 模块中所有的数据转换逻辑从控制器层 (`pig_farm_controller.go`) 迁移到服务层 (
`pig_farm_service.go`)。
- **统一服务层接口**: 修改 `PigFarmService` 接口, 使其直接返回响应 DTO (`dto.XxxResponse`)。
- **简化控制器**: 精简 `PigFarmController` 中的代码, 移除所有 `models``dto` 的转换代码, 使其直接使用服务层返回的
DTO。
#### Non-Goals
- **不修改业务逻辑**: 本次重构严格保证业务逻辑不变。服务层将精确复制控制器层现有的转换逻辑, 不增加或减少任何字段。
- **不改变 API 契约**: API 的请求和响应对最终用户保持完全一致。
### Decisions
- **决策:在服务层完成 `models``dto` 的转换**
- **理由**: 与其他模块保持一致, 将数据转换视为服务层业务逻辑的一部分。这确保了服务接口的稳定性和调用方的便利性。
- **具体实现**: `pig_farm_service.go` 中的方法在从 `repository` 获取 `models` 实体后, 将其转换为对应的 `dto` 再返回。
### Migration Plan
1. **修改 `internal/app/service/pig_farm_service.go`**
- **更新 `PigFarmService` 接口**:
- `CreatePigHouse(...) (*models.PigHouse, error)` -> `CreatePigHouse(...) (*dto.PigHouseResponse, error)`
- `GetPigHouseByID(...) (*models.PigHouse, error)` -> `GetPigHouseByID(...) (*dto.PigHouseResponse, error)`
- `ListPigHouses(...) ([]models.PigHouse, error)` -> `ListPigHouses(...) ([]dto.PigHouseResponse, error)`
- `UpdatePigHouse(...) (*models.PigHouse, error)` -> `UpdatePigHouse(...) (*dto.PigHouseResponse, error)`
- `CreatePen(...) (*models.Pen, error)` -> `CreatePen(...) (*dto.PenResponse, error)`
- `UpdatePen(...) (*models.Pen, error)` -> `UpdatePen(...) (*dto.PenResponse, error)`
- `UpdatePenStatus(...) (*models.Pen, error)` -> `UpdatePenStatus(...) (*dto.PenResponse, error)`
- **实现数据转换**:
- 在上述每个方法的实现中, 在从 `repository` 获得 `models` 对象后, 添加代码将其转换为对应的 `dto.XxxResponse` 对象。
- 转换逻辑将严格按照 `pig_farm_controller.go` 中现有的实现, 确保字段一一对应, 无任何增删。
- 例如, 在 `UpdatePigHouse` 中:
2. **修改 `internal/app/controller/management/pig_farm_controller.go`**
- **移除 DTO 转换代码**:
-`CreatePigHouse`, `GetPigHouse`, `UpdatePigHouse` 方法中, 删除手动创建 `dto.PigHouseResponse` 的代码。
-`ListPigHouses` 方法中, 删除用于遍历 `houses` 并创建 `[]dto.PigHouseResponse``for` 循环。
-`CreatePen`, `UpdatePen`, `UpdatePenStatus` 方法中, 删除手动创建 `dto.PenResponse` 的代码。
- **更新服务调用**:
- 将服务层返回的 DTO 对象直接传递给 `controller.SendSuccessWithAudit`
3. **验证**
- 通过代码审查确认转换逻辑被精确迁移。
- 运行相关测试, 并通过手动 API 测试验证端点行为与重构前完全一致。
### Open Questions
- 暂无。
---
## `plan` 模块重构设计
### Context
`plan_controller.go` 当前包含了大量的业务逻辑,这违反了控制器层应只负责请求处理和响应发送的原则。具体问题包括:
- **业务规则判断**:控制器中直接判断计划类型(如 `models.PlanTypeSystem`)、计划状态(如 `models.PlanStatusEnabled`)以及
`ContentType` 的自动判断。
- **领域对象创建与转换**:控制器直接使用 `dto.NewPlanFromCreateRequest``dto.NewPlanFromUpdateRequest` 将请求 DTO 转换为
`models.Plan`,并在响应前将 `models.Plan` 转换为 `dto.PlanResponse`
- **直接调用仓库层**:控制器直接调用 `planRepo``CreatePlan`, `GetPlanByID`, `ListPlans`, `UpdatePlan`, `DeletePlan`,
`GetBasicPlanByID`, `UpdatePlanStatus`, `UpdateExecuteCount`, `StopPlanTransactionally` 等方法。
- **协调领域服务**:控制器直接协调 `analysisPlanTaskManager``EnsureAnalysisTaskDefinition``CreateOrUpdateTrigger`
方法。
- **错误处理**:控制器直接通过 `errors.Is(err, gorm.ErrRecordNotFound)` 判断仓库层错误,并根据错误类型返回不同的 HTTP 状态码。
- **执行计数器重置**:在 `UpdatePlan``StartPlan` 中,控制器直接处理 `ExecuteCount` 的重置逻辑。
这种设计导致控制器层职责过重,业务逻辑分散,难以维护和测试。
### Goals / Non-Goals
#### Goals
- **创建应用服务层**:引入一个新的 `internal/app/service/plan_service.go` 来封装 `plan` 模块的所有业务逻辑。
- **迁移业务逻辑**:将 `plan_controller.go` 中识别出的所有业务规则判断、领域对象创建与转换、对仓库层的直接调用、对
`analysisPlanTaskManager` 的协调以及错误处理逻辑,全部迁移到新的 `PlanService` 中。
- **简化控制器**:使 `plan_controller.go` 只负责 HTTP 请求处理、参数绑定、调用新的 `PlanService` 方法,并处理服务层返回的
DTO。
- **统一服务层接口**`PlanService` 的方法将接收 DTO 作为输入,并返回 DTO 作为输出,实现服务层接口的标准化。
#### Non-Goals
- **不修改业务逻辑**:本次重构不涉及任何已有业务规则的变更。所有业务逻辑将原封不动地从控制器迁移到服务层。
- **不改变 API 契约**:对外暴露的 API 接口、请求参数和响应结构对最终用户保持不变。
- **不改变领域服务**:不对 `internal/domain/scheduler/analysis_plan_task_manager.go` 的接口和实现进行任何修改。
- **不改变仓库层接口**:不对 `internal/infra/repository/plan_repository.go` 的接口进行任何修改。
### Decisions
- **决策:引入新的应用服务 `PlanService`**
- **理由**:这是解决控制器职责过重和分层不清问题的标准做法。`PlanService` 将作为应用层门面,协调 `PlanRepository`
`AnalysisPlanTaskManager`,并为控制器提供一个清晰、稳定的接口。
- **结构**`PlanService` 将依赖于 `PlanRepository``AnalysisPlanTaskManager`
- **决策:`PlanService` 接口全面采用 DTO**
- **具体实现**:接口方法将接收 `dto.CreatePlanRequest`, `dto.UpdatePlanRequest`, `dto.ListPlansQuery` 等请求 DTO并返回
`*dto.PlanResponse`, `*dto.ListPlansResponse` 等响应 DTO。
- **理由**:这与 `monitor``device``pig-farm` 模块的重构决策一致,可以确保应用服务层的接口统一、清晰,并与上层(控制器)和下层(领域/仓库)完全解耦。服务层内部将负责
`DTO``models` 的转换以及 `models``DTO` 的转换。
- **决策:将控制器中的业务规则判断和错误处理下沉到服务层**
- **理由**:控制器应专注于 HTTP 协议相关的职责。所有业务规则的判断如计划类型、状态检查、ContentType
自动判断、执行计数器重置)以及对底层错误的具体判断(如 `gorm.ErrRecordNotFound`
)都属于业务逻辑范畴,应由服务层处理。服务层将返回更抽象的业务错误,控制器只需根据这些抽象错误进行统一的 HTTP 响应处理。
### Risks / Trade-offs
- **风险:意外修改或丢失现有业务逻辑**
- **描述**:在将控制器中分散的业务逻辑迁移到服务层时,存在逻辑被无意中删除、修改或遗漏的风险,尤其是在处理计划状态转换、执行计数器重置和
`ContentType` 自动判断等复杂逻辑时。
- **缓解措施**
1. **逐行迁移与比对**:在迁移过程中,将控制器中的每一段业务逻辑代码逐行复制到服务层,并仔细比对,确保逻辑的等效性。
2. **详细注释**:在服务层中对迁移过来的业务逻辑添加详细注释,解释其来源和作用。
3. **回归测试**:在完成重构后,必须进行完整的回归测试,确保所有受影响的 API 端点的行为与重构前完全一致。
### Migration Plan
1. **创建 `internal/app/service/plan_service.go` 文件**
- 定义 `PlanService` 接口,包含 `CreatePlan`, `GetPlanByID`, `ListPlans`, `UpdatePlan`, `DeletePlan`, `StartPlan`,
`StopPlan` 等方法。
- 定义 `planService` 结构体,并实现 `PlanService` 接口。
-`planService` 的实现中,将 `plan_controller.go` 中所有相关的业务逻辑(包括 DTO 转换、业务规则判断、对 `planRepo`
`analysisPlanTaskManager` 的调用、错误处理)精确迁移到对应的方法中。
2. **修改 `internal/app/controller/plan/plan_controller.go`**
- 更新 `Controller` 结构体,将 `planRepo``analysisPlanTaskManager` 替换为 `service.PlanService`
- 修改 `NewController` 函数,注入 `service.PlanService`
- 简化所有处理器方法,移除所有业务逻辑,只保留请求参数绑定、调用 `service.PlanService` 方法、错误处理和响应构建。
3. **修改 `internal/core/component_initializers.go`**
-`AppServices` 结构体中添加 `PlanService service.PlanService` 字段。
-`initAppServices` 函数中,初始化 `PlanService` 实例,并将其注入到 `AppServices` 中。
4. **修改 `internal/app/api/api.go`**
- 更新 `NewAPI` 函数的参数,移除 `planRepository``analysisTaskManager`,添加 `service.PlanService`
- 更新 `plan.NewController` 的调用,传入新的 `service.PlanService` 依赖。
### Open Questions
- 暂无。
---
## `user` 模块重构设计
### Context
`user_controller.go` 当前直接依赖 `repository.UserRepository``token.Service``domain_notify.Service`
,并在其方法内部执行了大量本应属于应用服务层的逻辑,包括:
- **直接的数据库操作**:调用 `userRepo``Create`, `FindByUsername`, `FindUserForLogin` 等方法。
- **领域模型实例化**:通过 `&models.User{...}` 直接创建数据库模型。
- **业务规则验证**:例如在 `CreateUser` 中判断用户名是否重复,在 `Login` 中进行密码验证。
- **协调领域服务**:在 `Login` 中协调 `tokenService` 生成 JWT`SendTestNotification` 中协调 `domain_notify.Service`
发送测试消息。
- **复杂的错误处理**:通过 `errors.Is``gorm.ErrRecordNotFound` 解析底层错误。
- **DTO 转换**:在方法末尾将 `models.User` 转换为 `dto.CreateUserResponse``dto.LoginResponse`
这种设计导致控制器与基础设施层和领域层紧密耦合,违反了分层架构的原则。
### Goals / Non-Goals
#### Goals
- **创建应用服务层**:引入一个新的 `internal/app/service/user_service.go` 来封装业务逻辑。
- **迁移业务逻辑**:将上述所有在控制器中识别出的业务逻辑和数据处理任务,全部迁移到新的 `UserService` 中。
- **简化控制器**:使 `user_controller.go` 只负责 HTTP 请求处理和对新 `UserService` 的调用。
- **保持领域服务纯粹**:确保 `internal/domain/token.Service``internal/domain/notify.Service` 继续专注于核心领域逻辑,不与
DTO 发生耦合。
#### Non-Goals
- **不修改业务逻辑**:本次重构不涉及任何已有业务规则的变更。所有业务逻辑将原封不动地从控制器迁移到服务层。
- **不改变 API 契约**:对外暴露的 API 接口、请求和响应格式保持不变。
- **不改变领域服务**:不对 `domain.token.Service``domain.notify.Service` 的接口和实现进行任何修改。
- **不改变仓库层接口**:不对 `internal/infra/repository/user_repository.go` 的接口进行任何修改。
- **不涉及 `ListUserHistory` 方法**:该方法已从重构范围中移除。
### Decisions
- **决策:引入新的应用服务 `UserService`**
- **理由**:这是解决控制器职责过重和分层不清问题的标准做法。该服务将作为应用层门面,协调 `UserRepository`
`token.Service``domain_notify.Service`,并为控制器提供一个清晰、稳定的接口。
- **结构**`UserService` 将依赖于 `repository.UserRepository`, `token.Service`, `domain_notify.Service`
`logs.Logger`
- **决策:`UserService` 接口全面采用 DTO**
- **具体实现**:接口方法将接收 `dto.CreateUserRequest`, `dto.LoginRequest`, `dto.SendTestNotificationRequest` 等请求
DTO并返回 `*dto.CreateUserResponse`, `*dto.LoginResponse` 等响应 DTO。
- **理由**:这与 `monitor``device``pig-farm``plan` 模块的重构决策一致,可以确保应用服务层的接口统一、清晰,并与上层(控制器)和下层(领域/仓库)完全解耦。服务层内部将负责
DTO 到 `models` 的转换以及 `models` 到 DTO 的转换。
- **决策:将控制器中的业务规则判断和错误处理下沉到服务层**
- **理由**:控制器应专注于 HTTP 协议相关的职责。所有业务规则的判断(如用户名重复检查、密码验证)以及对底层错误的具体判断(如
`gorm.ErrRecordNotFound`)都属于业务逻辑范畴,应由服务层处理。服务层将返回更抽象的业务错误,控制器只需根据这些抽象错误进行统一的
HTTP 响应处理。
### Risks / Trade-offs
- **风险:意外修改或丢失现有业务逻辑**
- **描述**:在将控制器中分散的业务逻辑迁移到服务层时,存在逻辑被无意中删除、修改或遗漏的风险,尤其是在处理用户创建、登录和通知发送等复杂逻辑时。
- **缓解措施**
1. **逐行迁移与比对**:在迁移过程中,将控制器中的每一段业务逻辑代码逐行复制到服务层,并仔细比对,确保逻辑的等效性。
2. **详细注释**:在服务层中对迁移过来的业务逻辑添加详细注释,解释其来源和作用。
3. **回归测试**:在完成重构后,必须进行完整的回归测试,确保所有受影响的 API 端点的行为与重构前完全一致。
### Migration Plan
1. **创建 `internal/app/service/user_service.go` 文件**
- 定义 `UserService` 接口,包含 `CreateUser`, `Login`, `SendTestNotification` 等方法。
- 定义 `userService` 结构体,并实现 `UserService` 接口。
-`userService` 的实现中,将 `user_controller.go` 中所有相关的业务逻辑(包括 DTO 转换、业务规则判断、对 `userRepo`
`tokenService``notifyService` 的调用、错误处理)精确迁移到对应的方法中。
2. **修改 `internal/app/controller/user/user_controller.go`**
- 更新 `Controller` 结构体,将 `userRepo`, `tokenService`, `notifyService` 替换为 `service.UserService`
- 修改 `NewController` 函数,注入 `service.UserService`
- 简化所有处理器方法,移除所有业务逻辑,只保留请求参数绑定、调用 `service.UserService` 方法、错误处理和响应构建。
3. **修改 `internal/core/component_initializers.go`**
-`AppServices` 结构体中添加 `UserService service.UserService` 字段。
-`initAppServices` 函数中,初始化 `UserService` 实例,并将其注入到 `AppServices` 中。
4. **修改 `internal/app/api/api.go`**
- 更新 `NewAPI` 函数的参数,移除 `userRepo`, `tokenService`, `notifyService`,添加 `service.UserService`
- 更新 `user.NewController` 的调用,传入新的 `service.UserService` 依赖。
### Open Questions
- 暂无。