优化设备服务方法的入参
This commit is contained in:
@@ -21,4 +21,4 @@ http://git.huangwc.com/pig/pig-farm-controller/issues/50
|
||||
5. [增加任务增删改查时对设备任务关联表的维护](./device_task_association_maintenance.md)
|
||||
6. [删除设备时检查](./check_before_device_deletion.md)
|
||||
7. [删除设备模板时检查和删除区域主控时检查](./refactor_deletion_check.md)
|
||||
8. [优化设备服务方法的入参]()
|
||||
8. [优化设备服务方法的入参](./refactor_id_conversion.md)
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
# 重构方案:将 ID 类型转换逻辑迁移至 Controller 层
|
||||
|
||||
## 1. 目标
|
||||
|
||||
将所有通过 URL 路径传入的 `id`(`string` 类型),其到 `uint` 类型的转换和验证逻辑,从 Service(业务逻辑)层统一迁移至 Controller(控制器)层。
|
||||
|
||||
## 2. 动机
|
||||
|
||||
当前实现中,Controller 将从 URL 获取的 `string` 类型的 ID 直接传递给 Service 层,由 Service 层负责使用 `strconv.ParseUint` 进行类型转换。
|
||||
|
||||
这种模式存在以下问题:
|
||||
- **职责不清**:Service 层被迫处理了本应属于输入验证和转换的逻辑,而这部分工作更贴近 Controller 的职责。
|
||||
- **Service 不纯粹**:业务核心逻辑与原始输入(字符串)耦合,降低了 Service 的可复用性。理想情况下,Service 的接口应该只处理内部定义的、类型安全的数据。
|
||||
- **延迟的错误处理**:对于一个无效的 ID(如 "abc"),请求会穿透到 Service 层才会失败,而这种格式错误在 Controller 层就应该被拦截。
|
||||
|
||||
通过本次重构,我们将实现:
|
||||
- **职责分离**:Controller 负责处理 HTTP 请求的原始数据(验证、转换),Service 负责处理核心业务。
|
||||
- **接口清晰**:Service 层的所有方法将只接受类型安全的 `uint` 作为 ID,使其意图更加明确。
|
||||
- **快速失败**:无效的 ID 将在 Controller 层被立即拒绝,并返回 `400 Bad Request`,提高了系统的健壮性。
|
||||
|
||||
## 3. 详细实施步骤
|
||||
|
||||
### 第 1 步:修改 `device_service.go`
|
||||
|
||||
#### 3.1 修改 `DeviceService` 接口
|
||||
所有接收 `id string` 参数的方法签名,全部修改为接收 `id uint`。
|
||||
|
||||
**受影响的方法列表:**
|
||||
- `GetDevice(id string)` -> `GetDevice(id uint)`
|
||||
- `UpdateDevice(id string, ...)` -> `UpdateDevice(id uint, ...)`
|
||||
- `DeleteDevice(id string)` -> `DeleteDevice(id uint)`
|
||||
- `ManualControl(id string, ...)` -> `ManualControl(id uint, ...)`
|
||||
- `GetAreaController(id string)` -> `GetAreaController(id uint)`
|
||||
- `UpdateAreaController(id string, ...)` -> `UpdateAreaController(id uint, ...)`
|
||||
- `DeleteAreaController(id string)` -> `DeleteAreaController(id uint)`
|
||||
- `GetDeviceTemplate(id string)` -> `GetDeviceTemplate(id uint)`
|
||||
- `UpdateDeviceTemplate(id string, ...)` -> `UpdateDeviceTemplate(id uint, ...)`
|
||||
- `DeleteDeviceTemplate(id string)` -> `DeleteDeviceTemplate(id uint)`
|
||||
|
||||
#### 3.2 修改 `deviceService` 实现
|
||||
在 `deviceService` 的方法实现中,移除所有 `strconv.ParseUint` 的调用,直接使用传入的 `uint` 类型的 ID。
|
||||
|
||||
**示例 (`DeleteDeviceTemplate`):**
|
||||
|
||||
**修改前:**
|
||||
```go
|
||||
func (s *deviceService) DeleteDeviceTemplate(id string) error {
|
||||
idUint, err := strconv.ParseUint(id, 10, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("无效的ID格式: %w", err)
|
||||
}
|
||||
dtID := uint(idUint)
|
||||
// ... 业务逻辑
|
||||
}
|
||||
```
|
||||
|
||||
**修改后:**
|
||||
```go
|
||||
func (s *deviceService) DeleteDeviceTemplate(id uint) error {
|
||||
// 直接使用 id
|
||||
// ... 业务逻辑
|
||||
}
|
||||
```
|
||||
|
||||
### 第 2 步:修改 `device_controller.go`
|
||||
|
||||
在所有调用受影响 Service 方法的 Controller 方法中,增加 ID 的转换和错误处理逻辑。
|
||||
|
||||
**示例 (`DeleteDeviceTemplate`):**
|
||||
|
||||
**修改前:**
|
||||
```go
|
||||
func (c *Controller) DeleteDeviceTemplate(ctx echo.Context) error {
|
||||
const actionType = "删除设备模板"
|
||||
dtID := ctx.Param("id") // dtID is a string
|
||||
|
||||
if err := c.deviceService.DeleteDeviceTemplate(dtID); err != nil {
|
||||
// ... 错误处理
|
||||
}
|
||||
// ... 成功处理
|
||||
}
|
||||
```
|
||||
|
||||
**修改后:**
|
||||
```go
|
||||
func (c *Controller) DeleteDeviceTemplate(ctx echo.Context) error {
|
||||
const actionType = "删除设备模板"
|
||||
idStr := ctx.Param("id")
|
||||
|
||||
// 在 Controller 层进行转换和验证
|
||||
idUint, err := strconv.ParseUint(idStr, 10, 64)
|
||||
if err != nil {
|
||||
c.logger.Warnf("%s: 无效的ID格式: %s", actionType, idStr)
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的ID格式", actionType, "ID格式错误", idStr)
|
||||
}
|
||||
dtID := uint(idUint)
|
||||
|
||||
// 调用 Service,传入 uint 类型的 ID
|
||||
if err := c.deviceService.DeleteDeviceTemplate(dtID); err != nil {
|
||||
// ... 错误处理 (保持不变)
|
||||
}
|
||||
|
||||
// ... 成功处理
|
||||
}
|
||||
```
|
||||
此模式将应用于所有受影响的 Controller 方法。
|
||||
Reference in New Issue
Block a user