归档任务
This commit is contained in:
		| @@ -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` 等具体错误。 | ||||
							
								
								
									
										69
									
								
								openspec/specs/business-logic-layering/spec.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								openspec/specs/business-logic-layering/spec.md
									
									
									
									
									
										Normal file
									
								
							| @@ -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` 等具体错误。 | ||||
|  | ||||
		Reference in New Issue
	
	Block a user