背景
- 保证多人协作也只写出一种代码, 而非多种代码; 例如: 保证10人只写出一套代码, 避免10人写出100种代码.
- 有利于与异构系统进行交互
- 有利于工作交接
- 系统做大做强的基础
命名规范
交互协议
- 交互协议根据业务类型封装在
object
中, 例如: DeviceProtocol - 与外围系统交互封装在包
protocol/api
中 - 内部系统交互封装在包
protocol/service
中
变量命名
时刻与时间的区别: 时刻指某一个点(比如: 2010-01-01 10:00:00), 时间指两个时刻间的差值(比如: 2分钟, 5小时)
- XXXAt: 表示与时刻相关
- createdAt: 创建时刻
- updatedAt: 更新时刻
- triggerAt: 触发时刻
- startedAt: 开始时刻, 用于搜索中开始时刻
- endedAt: 结束时刻, 用于搜索中结束时刻
外围系统交互
- XXXReq: 接收外围系统的请求参数并构造成该对象
- XXXResponse: 将业务层提供的数据封装成该对象, 并序列化成json返回给外围调用方
内部Actor间交互
- 消息通道: 目前均采用点对点消息通道
- 消息: 三类消息
- 命令消息: ExecuteXXX, 例如: ExecuteBindDevice
- 事件消息: XXXExecuted, 例如: BindDeviceExecuted
- 文档消息: XXXMsg, 例如: BindDeviceMsg
部分文档消息内部包装类: XXXWrapper, 例如: BindDeviceWrapper
同构系统交互
不允许使用ask
模式, 根据需要选择使用tell
, forward
, pipeTo
异构系统交互
发起调用时可以使用ask
模式
HTTP接口命名
- url: 使用纯REST风格
- 函数名: queryXXX, modifyXXX, removeXXX, addXXX
领域模型
- XXX, 例如: Device
聚合Actor
- XXXActor, 例如: BindDeviceActor
Dao层Actor
- SelectXXX, 例如: SelectDeviceById
- UpdateXXX, 例如: UpdateDeviceById
- InsertXXX, 例如: InsertDevice
- DeleteXXX, 例如: DeleteDeviceById
getquill 用法
仅针对单表进行映射(ORM), 多表关联产生的数据使用元组进行接收; 减少domain的无限膨胀.
getquill schema 命名
业务表使用复数, 例如: activites; 关联表使用单数, 例如: userActivity;
分布式服务命名规范
格式
域名.module.模块名.*
服务枚举
- 基础协议的项目名和包名
- 项目名: GDP-BASE-PROTOCOL
- 包名: com.gyenno.module.base.*
- 通用服务
- 服务项目名: GDP-COMMON
- 协议项目名: GDP-COMMON-PROTOCOL
- 包名: com.gyenno.module.common.*
- 用户服务
- 服务项目名: GDP-USER
- 协议项目名: GDP-USER-PROTOCOL
- 包名: com.gyenno.module.user.*
- 消息服务
- 服务项目名: GDP-MESSAGE
- 协议项目名: GDP-MESSAGE-PROTOCOL
- 包名: com.gyenno.module.message.*
- 文件服务
- 服务项目名: GDP-FILE
- 协议项目名: GDP-FILE-PROTOCOL
- 包名: com.gyenno.module.file.*
- 医动力服务
- 服务项目名: GDP-MEDICAL
- 协议项目名: GDP-MEDICAL-PROTOCOL
- 包名: com.gyenno.module.medical.*
数据库规范
- 库命名: 服务名_database
- 表命名
- 非关联表: 使用名词复数, 例如: users, roles
- 关联表: 使用名词单数, 例如: user_activity, user_role
处理业务发生异常后的响应(接口v3.1进行整体迁移)
根据目前项目的需求, 使用单容错结构, 减少调用方解析成本; 以后有足以平衡调用成本的需求, 再平滑升级到多容错结构;
异常响应体中, code
分类如下:
- conflict: 冲突, 所要新增的资源已存在
- invalid: 无效, 参数超出文档约定范围, 例如: 1-男, 2-女, 输入
3
将收到此code - missing: 必选参数不存在
- notFound: 资源不存在
单容错(数据结构)
检测到输入或业务调用异常, 直接返回, 不再对其它resource
或field
进行检测;
1 | { |
多容错(数据结构)
检测到输入或业务调用异常, 继续对其它resource
或field
进行检测, 封装组合后再返回;
1 | { |
为什么要设计error
?
如果只使用message
, 只能人类看懂, 机器很难进行分类解析.
场景: 绑定设备, 假设提供的userId
和chId
在库中均不存在, 如果只返回message的话, 将返回用户不存在
或设备不存在
; 人能看懂, 但代码无法进行分类; 假如增加error
的话, 调用方就可根据resource
和field
进行自定义提示, 而不依赖于后端提供的message
;
如下:
1 | { |
1 | { |