QDAirPortBackend0122/doc/work/API设计原则确立_20250115.md
2026-01-22 13:19:47 +08:00

4.5 KiB
Raw Blame History

API设计原则确立文档

创建日期: 2025-01-15
版本: 0.1.10
文档类型: 设计原则和标准制定

背景

在数据模型统一重构过程中遇到了一个重要的设计问题API返回值中应该使用vehicleId还是licensePlate作为标识符

问题演化过程

  1. 初始设计使用licensePlate作为Map的key业务语义考虑
  2. 类型修复误将key改为vehicleId技术实现考虑
  3. 业务修正改回licensePlate业务语义考虑
  4. 原则确立:用户提出明确的设计原则,最终确定正确的使用方式

设计原则

核心原则

用户提出的设计原则:

索引性质的返回值使用vehicleId唯一、稳定的标识符
详细信息的返回值包含vehicleId + licensePlate完整信息

具体应用

1. 索引性质返回值

使用场景

  • Map的key
  • 数组索引
  • 快速查找标识符
  • 缓存key

使用vehicleId的原因

  • 唯一性:数据库主键,绝对唯一
  • 稳定性:不会因为业务变更而改变
  • 性能:数字类型,比较和哈希计算更快
  • 一致性:与数据库设计保持一致

示例

// WebSocket返回的Map
Map<String, VehicleLocation> positions = {
    "123": VehicleLocation{vehicleId: 123, licensePlate: "京A12345", ...},
    "456": VehicleLocation{vehicleId: 456, licensePlate: "京B67890", ...}
}

2. 详细信息返回值

使用场景

  • 实体对象
  • API响应体
  • 数据传输对象(DTO)

包含完整信息的原因

  • 数据完整性:提供所有必要的标识信息
  • 前端友好:既能索引又能展示
  • 灵活性:支持多种使用场景
  • 一次性获取:减少额外的数据查询

示例

// VehicleLocation对象包含完整信息
public class VehicleLocation {
    private Long vehicleId;           // 用于索引和关联
    private String licensePlate;      // 用于业务展示
    private MovingObjectType vehicleType;
    private Point location;
    // ... 其他字段
}

实施方案

GeopositionController修正

修正前的错误思路

  • 使用licensePlate作为Map key过度业务化
  • 忽略了索引性质的需求

修正后的正确实现

// 索引性质使用vehicleId
Map<String, VehicleLocation> resultMap = vehicles.stream()
    .collect(Collectors.toMap(
        location -> String.valueOf(location.getVehicleId()), // 索引标识符
        location -> location, // 完整信息对象
        (existing, replacement) -> replacement
    ));

前端使用模式

快速索引

// 通过vehicleId快速查找特定车辆
const vehicle = positions[vehicleId];

业务展示

// 通过licensePlate进行用户界面展示
const displayText = vehicle.licensePlate;

数据更新

// 使用vehicleId作为key进行高效更新
positions[vehicleId] = newLocationData;

技术优势

1. 性能优化

  • vehicleId作为数字标识符在Map操作中性能更优
  • 哈希计算和比较操作效率更高
  • 内存使用更节省

2. 数据一致性

  • 与数据库主键保持一致
  • 避免因业务变更导致的标识符变化
  • 保证数据关联的稳定性

3. 系统架构

  • 明确区分技术标识符和业务标识符
  • 提高系统的可维护性和扩展性
  • 符合数据库设计的最佳实践

应用范围

需要应用此原则的场景

  1. 所有WebSocket接口Map key使用vehicleId
  2. 缓存设计缓存key使用vehicleId
  3. API响应:返回完整的实体对象
  4. 前端状态管理使用vehicleId作为状态key
  5. 数据同步使用vehicleId进行数据匹配

实施检查清单

  • 检查所有WebSocket接口的Map key设计
  • 检查缓存服务的key生成逻辑
  • 检查API响应对象的完整性
  • 更新前端代码的数据处理逻辑
  • 更新相关文档和注释

验证结果

  • GeopositionController修正完成
  • 编译测试通过
  • 设计原则文档化
  • 版本更新和记录完成

经验总结

设计思维转变

  1. 从纯技术角度技术+业务平衡
  2. 单一标识符分场景使用不同标识符
  3. 简单实现考虑性能和可维护性

最佳实践

  1. 明确区分索引性质和详细信息的使用场景
  2. 保证数据的完整性和API的一致性
  3. 考虑前端使用的便利性和性能要求
  4. 及时记录和标准化设计原则