数据视图
数据视图

-
VO(View Object
) :视图对象,用于展示层,它的作用是把某个指定页面(或组件)的所有数据封装起来。 -
DTO(Data Transfer Object
) :数据传输对象,分布式应用提供粗粒度的数据实体,也是一种数据传输协议,以减少分布式调用的次数,从而提高分布式调用的性能和降低网络负载,这里泛指用于展示层与服务层之间的数据传输对象。RPC 对外暴露的服务涉及对象API 就是DTO ,如JSF (京东RPC 框架) 、Dubbo。对比VO :绝大多数应用场景下,VO 与DTO 的属性值基本一致,但对于设计层面来说,概念上还是存在区别,DTO 代表服务层需要接收的数据和返回的数据,而VO 代表展示层需要显示的数据。 -
DO(Domain Object
) :领域对象,就是从现实世界中抽象出来的有形或无形的业务实体。DO 不是简单的POJO ,它具有领域业务逻辑。 -
PO(Persistent Object
) :持久化对象。对比DO :DO 和PO 在绝大部分情况下是一一对应的,但也存在区别,例如DO 在某些场景下不需要进行显式的持久化,只驻留在静态内存。同样PO 也可以没有对应的DO ,比如一对多表关系在领域模型层面不需要单独的领域对象。

表与接口设计
数据视图应用服务通过数据传输对象(DTO)完成外部数据交换。领域层通过领域对象(DO)作为领域实体和值对象的数据和行为载体。基础层利用持久化对象(PO)完成数据库的交换。
对象名 | 层名 | 描述 |
---|---|---|
Transfer Object/TO | Controller | 接入与返回层,提供视图数据聚合与统一的查询 |
Business Object/BO | Service/Connector | 数据业务层,提供业务数据的聚合 |
Database Access Object/DAO | Model | 元数据访问层,与数据库进行直接交互 |
在设计数据库的时候,我们尽量避免给属性列添加额外的前缀,并且使用嵌套的结构返回多表联查的数据:
{
"user": {
"uuid": "{uuid}",
"name": "{name}"
},
"asset": {
"uuid": "{uuid}",
"name": "{name}"
},
"lessonss": []
}
/api/resource/get
/api/resource/getByIds
# 在交互层级上同样应该有所隐藏
/api/resource/getRelatedResourceById
/api/related-resource/getRelatedResourceByResourceId
query {
Resources{
id
}
}
query {
Resource($id: 1){
id
statisticsField(){}
oneToOneField() {}
oneToManyField(){}
}
}
Domain Primitive
在项目中,散落在各个服务或工具类里面的代码,都可以抽出来放在
让隐性的概念显性化(Make Implicit Concepts Explicit)
活动类型就是一个简单的

让隐性的上下文显性化(Make Implicit Context Explicit)
当要实现一个功能或进行逻辑判断依赖多个概念时,可以把这些概念封装到一个独立地完整概念,也是一种

封装多对象行为(Encapsulate Multi-Object Behavior)
常见推荐使用
- 有格式要求的
String :比如Name ,PhoneNumber,OrderNumber,ZipCode,Address 等。 - 限制的
Integer :比如OrderId (>0) ,Percentage(0-100%) ,Quantity(>=0)等。 - 可枚举的
int :比如Status (一般不用Enum 因为反序列化问题) 。 Double 或BigDecimal :一般用到的Double 或BigDecimal 都是有业务含义的,比如Temperature 、Money、Amount、ExchangeRate、Rating 等。- 复杂的数据结构:比如
Map<String, List>
等,尽量能把Map 的所有操作包装掉,仅暴露必要行为,如通天塔的活动Map 类。
接口变得清晰可读,校验逻辑内聚,在接口边界外完成,无胶水代码,业务逻辑清晰可读,代码变得更容易测试,也更安全。