4.5 KiB
4.5 KiB
API设计原则确立文档
创建日期: 2025-01-15
版本: 0.1.10
文档类型: 设计原则和标准制定
背景
在数据模型统一重构过程中,遇到了一个重要的设计问题:API返回值中应该使用vehicleId还是licensePlate作为标识符?
问题演化过程
- 初始设计:使用licensePlate作为Map的key(业务语义考虑)
- 类型修复:误将key改为vehicleId(技术实现考虑)
- 业务修正:改回licensePlate(业务语义考虑)
- 原则确立:用户提出明确的设计原则,最终确定正确的使用方式
设计原则
核心原则
用户提出的设计原则:
索引性质的返回值:使用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. 系统架构
- 明确区分技术标识符和业务标识符
- 提高系统的可维护性和扩展性
- 符合数据库设计的最佳实践
应用范围
需要应用此原则的场景
- 所有WebSocket接口:Map key使用vehicleId
- 缓存设计:缓存key使用vehicleId
- API响应:返回完整的实体对象
- 前端状态管理:使用vehicleId作为状态key
- 数据同步:使用vehicleId进行数据匹配
实施检查清单
- 检查所有WebSocket接口的Map key设计
- 检查缓存服务的key生成逻辑
- 检查API响应对象的完整性
- 更新前端代码的数据处理逻辑
- 更新相关文档和注释
验证结果
- ✅ GeopositionController修正完成
- ✅ 编译测试通过
- ✅ 设计原则文档化
- ✅ 版本更新和记录完成
经验总结
设计思维转变
- 从纯技术角度 → 技术+业务平衡
- 单一标识符 → 分场景使用不同标识符
- 简单实现 → 考虑性能和可维护性
最佳实践
- 明确区分索引性质和详细信息的使用场景
- 保证数据的完整性和API的一致性
- 考虑前端使用的便利性和性能要求
- 及时记录和标准化设计原则