From d6c18f07748194d84281536c42b2bec6b80431f1 Mon Sep 17 00:00:00 2001 From: huang <1724659546@qq.com> Date: Fri, 31 Oct 2025 17:04:58 +0800 Subject: [PATCH] =?UTF-8?q?=E5=BD=92=E6=A1=A3=E4=BB=BB=E5=8A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../design.md | 0 .../proposal.md | 0 .../specs/business-logic-layering/spec.md | 70 +++++++++++++++++++ .../tasks.md | 0 .../specs/business-logic-layering/spec.md | 69 ++++++++++++++++++ 5 files changed, 139 insertions(+) rename openspec/changes/{refactor-business-logic-layering => archive/2025-10-31-refactor-business-logic-layering}/design.md (100%) rename openspec/changes/{refactor-business-logic-layering => archive/2025-10-31-refactor-business-logic-layering}/proposal.md (100%) create mode 100644 openspec/changes/archive/2025-10-31-refactor-business-logic-layering/specs/business-logic-layering/spec.md rename openspec/changes/{refactor-business-logic-layering => archive/2025-10-31-refactor-business-logic-layering}/tasks.md (100%) create mode 100644 openspec/specs/business-logic-layering/spec.md diff --git a/openspec/changes/refactor-business-logic-layering/design.md b/openspec/changes/archive/2025-10-31-refactor-business-logic-layering/design.md similarity index 100% rename from openspec/changes/refactor-business-logic-layering/design.md rename to openspec/changes/archive/2025-10-31-refactor-business-logic-layering/design.md diff --git a/openspec/changes/refactor-business-logic-layering/proposal.md b/openspec/changes/archive/2025-10-31-refactor-business-logic-layering/proposal.md similarity index 100% rename from openspec/changes/refactor-business-logic-layering/proposal.md rename to openspec/changes/archive/2025-10-31-refactor-business-logic-layering/proposal.md diff --git a/openspec/changes/archive/2025-10-31-refactor-business-logic-layering/specs/business-logic-layering/spec.md b/openspec/changes/archive/2025-10-31-refactor-business-logic-layering/specs/business-logic-layering/spec.md new file mode 100644 index 0000000..8d68aee --- /dev/null +++ b/openspec/changes/archive/2025-10-31-refactor-business-logic-layering/specs/business-logic-layering/spec.md @@ -0,0 +1,70 @@ +# 业务逻辑分层重构规范 + +## Purpose +本规范旨在明确业务逻辑分层重构的目标、变更内容和预期行为,以解决控制器层职责过重、代码耦合严重、可维护性差的问题。通过本次重构,我们将实现各层职责的清晰划分,提升代码质量和可测试性。 + +## ADDED Requirements + +### Requirement: 服务层接口标准化 +- **说明**: 服务层方法现在 **MUST** 只接收数据传输对象 (DTO) 或基本参数,并 **MUST** 只返回 DTO 或业务领域对象,不再直接暴露数据库模型。 +- **理由**: 减少服务层与持久化细节的耦合,提高接口的抽象性和稳定性。 +- **影响**: 高。所有调用服务层的方法都需要调整。 +- **受影响的模块**: `monitor`, `device`, `pig-farm`, `plan`, `user`。 + +#### Scenario: 服务层方法接收 DTO 作为输入 +- **假如**: `UserService` 的 `CreateUser` 方法被调用。 +- **当**: `CreateUser` 方法接收 `dto.CreateUserRequest` 作为参数。 +- **那么**: `UserService` 内部负责将 `dto.CreateUserRequest` 转换为 `models.User` 进行处理。 + +#### Scenario: 服务层方法返回 DTO 作为输出 +- **假如**: `UserService` 的 `CreateUser` 方法执行成功。 +- **当**: `CreateUser` 方法返回 `*dto.CreateUserResponse`。 +- **那么**: 调用方可以直接使用 `dto.CreateUserResponse`,无需进行额外的模型转换。 + +### Requirement: 控制器层职责收敛 +- **说明**: 控制器层现在 **MUST** 仅负责 HTTP 请求的参数绑定与校验、调用服务层方法,并将服务层返回的 DTO 转换为 HTTP 响应。所有业务逻辑、领域对象的创建与验证、以及与仓库层的直接交互都 **MUST** 从控制器层移除并下沉到服务层。 +- **理由**: 遵循“关注点分离”原则,使控制器层专注于 HTTP 协议处理,提高代码的可维护性和可测试性。 +- **影响**: 高。所有控制器方法都需要大幅简化。 +- **受影响的模块**: `monitor`, `device`, `pig-farm`, `plan`, `user`。 + +#### Scenario: 控制器不再直接进行领域模型内部字段的序列化/反序列化 +- **假如**: `DeviceController` 的 `CreateDevice` 方法被调用。 +- **当**: `CreateDevice` 方法不再包含 `json.Marshal` 或 `json.Unmarshal` 等操作来处理 `Properties` 等字段。 +- **那么**: 这些序列化/反序列化逻辑已下沉到 `DeviceService` 中。 + +#### Scenario: 控制器不再直接实例化领域模型对象 +- **假如**: `UserController` 的 `CreateUser` 方法被调用。 +- **当**: `CreateUser` 方法不再包含 `&models.User{...}` 这样的代码。 +- **那么**: 领域模型的创建已通过 `UserService` 完成。 + +#### Scenario: 控制器不再直接调用仓库层方法 +- **假如**: `PlanController` 的 `ListPlans` 方法被调用。 +- **当**: `ListPlans` 方法不再直接调用 `planRepo.ListPlans`。 +- **那么**: `PlanService` 负责协调 `PlanRepository`。 + +#### Scenario: 控制器不再直接进行业务规则判断 +- **假如**: `PlanController` 的 `UpdatePlan` 方法被调用。 +- **当**: `UpdatePlan` 方法不再包含对计划类型、状态或 `ContentType` 的直接判断逻辑。 +- **那么**: 这些业务规则判断已下沉到 `PlanService` 中。 + +### Requirement: DTO 转换逻辑下沉 +- **说明**: 数据库模型与 DTO 之间的转换逻辑 **MUST** 从控制器层移动到服务层内部或专门的转换器中。 +- **理由**: 确保数据转换逻辑与业务逻辑紧密结合,避免控制器层承担不必要的职责。 +- **影响**: 中。主要影响数据流转和转换点。 +- **受影响的模块**: `monitor`, `device`, `pig-farm`, `plan`, `user`。 + +#### Scenario: 服务层负责将数据库模型转换为响应 DTO +- **假如**: `PigFarmService` 的 `GetPigHouseByID` 方法从 `repository` 获取到 `models.PigHouse`。 +- **当**: `GetPigHouseByID` 方法在返回前将 `models.PigHouse` 转换为 `dto.PigHouseResponse`。 +- **那么**: 控制器直接接收 `dto.PigHouseResponse`。 + +### Requirement: 业务错误处理优化 +- **说明**: 服务层现在 **MUST** 返回更抽象的业务错误,控制器层 **MUST** 根据这些抽象错误进行统一的 HTTP 响应处理,避免直接依赖仓库层或服务层内部的具体错误类型或错误信息。 +- **理由**: 提高错误处理的一致性和可维护性,解耦控制器与底层错误实现。 +- **影响**: 中。影响错误处理流程。 +- **受影响的模块**: `monitor`, `device`, `pig-farm`, `plan`, `user`。 + +#### Scenario: 服务层返回抽象业务错误 +- **假如**: `UserService` 的 `CreateUser` 方法因用户名重复而失败。 +- **当**: `UserService` 返回一个表示“用户名已存在”的抽象错误(例如自定义错误类型或包装后的错误)。 +- **那么**: `UserController` 接收到此抽象错误后,可以统一转换为相应的 HTTP 状态码和错误信息,而无需解析底层 `gorm.ErrDuplicatedKey` 等具体错误。 diff --git a/openspec/changes/refactor-business-logic-layering/tasks.md b/openspec/changes/archive/2025-10-31-refactor-business-logic-layering/tasks.md similarity index 100% rename from openspec/changes/refactor-business-logic-layering/tasks.md rename to openspec/changes/archive/2025-10-31-refactor-business-logic-layering/tasks.md diff --git a/openspec/specs/business-logic-layering/spec.md b/openspec/specs/business-logic-layering/spec.md new file mode 100644 index 0000000..73eb8ec --- /dev/null +++ b/openspec/specs/business-logic-layering/spec.md @@ -0,0 +1,69 @@ +# business-logic-layering Specification + +## Purpose +TBD - created by archiving change refactor-business-logic-layering. Update Purpose after archive. +## Requirements +### Requirement: 服务层接口标准化 +- **说明**: 服务层方法现在 **MUST** 只接收数据传输对象 (DTO) 或基本参数,并 **MUST** 只返回 DTO 或业务领域对象,不再直接暴露数据库模型。 +- **理由**: 减少服务层与持久化细节的耦合,提高接口的抽象性和稳定性。 +- **影响**: 高。所有调用服务层的方法都需要调整。 +- **受影响的模块**: `monitor`, `device`, `pig-farm`, `plan`, `user`。 + +#### Scenario: 服务层方法接收 DTO 作为输入 +- **假如**: `UserService` 的 `CreateUser` 方法被调用。 +- **当**: `CreateUser` 方法接收 `dto.CreateUserRequest` 作为参数。 +- **那么**: `UserService` 内部负责将 `dto.CreateUserRequest` 转换为 `models.User` 进行处理。 + +#### Scenario: 服务层方法返回 DTO 作为输出 +- **假如**: `UserService` 的 `CreateUser` 方法执行成功。 +- **当**: `CreateUser` 方法返回 `*dto.CreateUserResponse`。 +- **那么**: 调用方可以直接使用 `dto.CreateUserResponse`,无需进行额外的模型转换。 + +### Requirement: 控制器层职责收敛 +- **说明**: 控制器层现在 **MUST** 仅负责 HTTP 请求的参数绑定与校验、调用服务层方法,并将服务层返回的 DTO 转换为 HTTP 响应。所有业务逻辑、领域对象的创建与验证、以及与仓库层的直接交互都 **MUST** 从控制器层移除并下沉到服务层。 +- **理由**: 遵循“关注点分离”原则,使控制器层专注于 HTTP 协议处理,提高代码的可维护性和可测试性。 +- **影响**: 高。所有控制器方法都需要大幅简化。 +- **受影响的模块**: `monitor`, `device`, `pig-farm`, `plan`, `user`。 + +#### Scenario: 控制器不再直接进行领域模型内部字段的序列化/反序列化 +- **假如**: `DeviceController` 的 `CreateDevice` 方法被调用。 +- **当**: `CreateDevice` 方法不再包含 `json.Marshal` 或 `json.Unmarshal` 等操作来处理 `Properties` 等字段。 +- **那么**: 这些序列化/反序列化逻辑已下沉到 `DeviceService` 中。 + +#### Scenario: 控制器不再直接实例化领域模型对象 +- **假如**: `UserController` 的 `CreateUser` 方法被调用。 +- **当**: `CreateUser` 方法不再包含 `&models.User{...}` 这样的代码。 +- **那么**: 领域模型的创建已通过 `UserService` 完成。 + +#### Scenario: 控制器不再直接调用仓库层方法 +- **假如**: `PlanController` 的 `ListPlans` 方法被调用。 +- **当**: `ListPlans` 方法不再直接调用 `planRepo.ListPlans`。 +- **那么**: `PlanService` 负责协调 `PlanRepository`。 + +#### Scenario: 控制器不再直接进行业务规则判断 +- **假如**: `PlanController` 的 `UpdatePlan` 方法被调用。 +- **当**: `UpdatePlan` 方法不再包含对计划类型、状态或 `ContentType` 的直接判断逻辑。 +- **那么**: 这些业务规则判断已下沉到 `PlanService` 中。 + +### Requirement: DTO 转换逻辑下沉 +- **说明**: 数据库模型与 DTO 之间的转换逻辑 **MUST** 从控制器层移动到服务层内部或专门的转换器中。 +- **理由**: 确保数据转换逻辑与业务逻辑紧密结合,避免控制器层承担不必要的职责。 +- **影响**: 中。主要影响数据流转和转换点。 +- **受影响的模块**: `monitor`, `device`, `pig-farm`, `plan`, `user`。 + +#### Scenario: 服务层负责将数据库模型转换为响应 DTO +- **假如**: `PigFarmService` 的 `GetPigHouseByID` 方法从 `repository` 获取到 `models.PigHouse`。 +- **当**: `GetPigHouseByID` 方法在返回前将 `models.PigHouse` 转换为 `dto.PigHouseResponse`。 +- **那么**: 控制器直接接收 `dto.PigHouseResponse`。 + +### Requirement: 业务错误处理优化 +- **说明**: 服务层现在 **MUST** 返回更抽象的业务错误,控制器层 **MUST** 根据这些抽象错误进行统一的 HTTP 响应处理,避免直接依赖仓库层或服务层内部的具体错误类型或错误信息。 +- **理由**: 提高错误处理的一致性和可维护性,解耦控制器与底层错误实现。 +- **影响**: 中。影响错误处理流程。 +- **受影响的模块**: `monitor`, `device`, `pig-farm`, `plan`, `user`。 + +#### Scenario: 服务层返回抽象业务错误 +- **假如**: `UserService` 的 `CreateUser` 方法因用户名重复而失败。 +- **当**: `UserService` 返回一个表示“用户名已存在”的抽象错误(例如自定义错误类型或包装后的错误)。 +- **那么**: `UserController` 接收到此抽象错误后,可以统一转换为相应的 HTTP 状态码和错误信息,而无需解析底层 `gorm.ErrDuplicatedKey` 等具体错误。 +