JavaWeb - 我们的开发规范(VO、DTO、BO、PO、DO、POJO)

在讲具体的概念之前,我们先简单的讲一讲我们MVC开发模式。

MVC的简单定义

  • M层负责与数据库打交道
  • C层负责业务逻辑的编写
  • V层负责给用户展示(针对于前后端不分离的项目,不分离项目那种编写模版的方式,理解V的概念更直观)

而我们今天要说的VO,BO,PO,DO,DTO呢,就是穿梭在这M、V、C层之间的实体传输对象

  • VO(View Object):视图对象,用于展示层,它的作用是把某个指定页面(或组件)的所有数据封装起来

  • DTO(Data Transfer Object):数据传输对象,这个概念来源于J2EE的设计模式,原来的目的是为了EJB的分布式应用提供粗粒度的数据实体,以减少分布式调用的次数,从而提高分布式调用的性能和降低网络负载,但在这里,更符合泛指用于展示层与服务层之间的数据传输对象

  • BO(Business Object):业务对象,把业务逻辑封装为一个对象,这个对象可以包括一个或多个其它的对象。BO就是PO的组合:简单的例子比如说PO是一条交易记录,BO是一个人全部的交易记录集合对象。复杂点儿的例子PO1是交易记录,PO2是登录记录,PO3是商品浏览记录,PO4是添加购物车记录,PO5是搜索记录,BO是个人网站行为对象。BO是一个业务对象,一类业务就会对应一个BO,数量上没有限制,而且BO会有很多业务操作,也就是说除了get,set方法以外,BO会有很多针对自身数据进行计算的方法。为什么BO也画成横跨两层呢?原因是现在很多持久层框架自身就提供了数据组合的功能,因此BO有可能是在业务层由业务来拼装PO而成,也有可能是在数据库访问层由框架直接生成。很多情况下为了追求查询的效率,框架跳过PO直接生成BO的情况非常普遍,PO只是用来增删改使用

  • PO(Persistent Object):持久化对象,它跟持久层(通常是关系型数据库)的数据结构形成一一对应的映射关系,如果持久层是关系型数据库,那么,数据表中的每个字段(或若干个)就对应PO的一个(或若干个)属性。PO比较好理解:简单说PO就是数据库中的记录,一个PO的数据结构对应着库中表的结构,表中的一条记录就是一个PO对象。通常PO里面除了get,set之外没有别的方法。对于PO来说,数量是相对固定的,一定不会超过数据库表的数量。等同于Entity,这俩概念是一致的

  • DO(Domain Object):领域对象,就是从现实世界中抽象出来的有形或无形的业务实体。

    一个是阿里巴巴的开发手册中的定义:DO( Data Object)这个等同于上面的PO

    另一个是在DDD(Domain-Driven Design)领域驱动设计中,DO(Domain Object)这个等同于上面的BO

Tips:BO和DTO的区别

这两个的区别主要是就是字段的删减

BO对内,为了进行业务计算需要辅助数据,或者是一个业务有多个对外的接口,BO可能会含有很多接口对外所不需要的数据,因此DTO需要在BO的基础上,只要自己需要的数据,然后对外提供

在这个关系上,通常不会有数据内容的变化,内容变化要么在BO内部业务计算的时候完成,要么在解释VO的时候完成

我们的规范

开发规范

Domain 分层领域模型规约

(1)Basic:公共对象,所有 NO 级的公共类放到 basic 包下,如:BaseXxx

(2)PO(Persistent Object):持久化对象,xxxPO,xxx 即为数据表相关名

(3)BO(Business Object):业务对象,作用一:联表查询,多个 PO 组成 BO 的情况;作用二:Service层中间状态处理一律用 BO 来替代 Map(除非是动态的Map),如果 PO 可以复用拿来即用(奥母卡剃刀)

(4)DTO(Data Transfer Object):数据传输对象,Service 或 Client 出入对象;如果 Service 层返回分页实体类,分页实体类就是DTO,比如:Page<PO>, 那么这个整体就是一个DTO,包括类似 List<PO>,那么整个就可以看成是 DTO(BO 同理可得)

(5)VO(View Object):显示层对象,Controller 出入对象;Controller 层统一封装返回 ResultVO

Ps1:Common 模块:领域模型实体类(domain.basic/vo/dto/bo/po),如:ResultVO 位于 domain.vo

Ps2:工具类封装实体类时,禁止带XxxNO,取名尽量靠近工具类业务本身含义,如:JsonModel 形参

Ps3:只允许 Basic/VO 可以设定默认值

Ps4:Service private 方法出/入参封装不作限制,但禁止使用静态 Map

其他规约

  1. 禁止无共识的缩写
  2. 注释:类、接口、方法、代码、字段
  3. 数据库表名格式:t_项目/模块名_po名
  4. Client 模块命名格式:xxxClient(只含接口),每次迭代更新版本号
  5. 公共异常类封装,尽可能减少代码中出现没必要的 try...catch...(统一处理)
  6. 日志打印:INFO:无论如何都要打印(微服务出入必须打印),DEBUG:排查问题打印
  7. 私有方法、工具类等非 MVC 分层方法:形参个数不做限制,除非复用率很高需要封装
  8. Common 项目模块:领域模型实体类(domain)、工具类(util)、常量类等,每次迭代更新版本号
  9. 访问修饰符:Controller 不允许存在 private,统一挪到 Service 处理;类中修饰符顺序位置:public -> protected -> default -> private
  10. 代码必须符合 Alibaba & Sonarqube 规范
  11. MapStruct 查看详情

附:有必要用吗?

项目中真的有必要定义VO,BO,PO,DO,DTO吗?

还是要理性看待这个问题,要看我们项目“目的地”是什么。

如果项目比较小,是一个简单的MVC项目,又是单兵作战,我不建议使用VO,BO,PO,DO,DTO,直接用POJO负责各个层来传输就好,因为这种项目的“目的地”是快速完成。

而我们更多的时候,是持续迭代的团队协作项目,这个时候我们就建议用VO,BO,PO,DO,DTO,而且团队内要达成共识,形成一个标准规范

  1. 业务复杂,人员协同性要求高的场景下,这些规范性的东西不按着来虽然不会出错,程序照样跑,但是遵守规范会让程序更具扩展性和可读性;

  2. 让类语义更明确,很容易知道类的含义;

其实就是提升项目的可扩展性可维护性可阅读性

提升这些性能的尽头是经济效益

最后稍微总结一下,不管用哪种方式,只要团队内定义好一种适应的协同规范就行。

没有一个绝对好绝对坏的方式方法。

团队规范的尽头能提升项目的可扩展性可维护性可阅读性,从而降低bug率。

另附这些概念命名规范:

  • 数据对象:xxxPO,xxx即为数据表名(也可DO)

  • 数据传输对象:xxxDTO,xxx为业务领域相关的名称

  • 展示对象:xxxVO,xxx一般为网页名称

  • 业务对象:xxxBO,xxx是业务名称

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陆氪和他的那些代码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值