一体多面:哪有什么DO、BO、DTO,只不过是司空见惯的日常

1 分层疑问

无论DDD还是MVC模式构建项目,势必涉及到工程结构的分层,每一层由于定位不同,所以访问的对象也不同,那么对象在每一层传递时就会涉及到对象的转换,这时有人会产生以下疑问:

  • 对象种类多,增加理解成本
  • 对象之间转换,增加代码成本
  • 编写代码时有时不同层对象几乎一样

即使有这样的疑问,我也认为分层是必要的,所以本文我们尝试回答上述疑问。

2 通用分层模型

两种通用模型是MVC和DDD,我之前在文章《DDD理论建模与实现全流程》也详细讨论DDD建模和落地全流程,本文只涉及对象的讨论,所以会对模型有所简化。

2.1 模型分类

  • 数据对象:DO(data object)
  • 业务对象:BO(business object)
  • 视图对象:VO(view object)
  • 数据传输对象:DTO(data transfer object)
  • 领域对象:DMO(domain object)
  • 聚合对象:AGG(aggregation)

2.2 MVC

MVC模型总体分为三层:

  • 持久层(persistence)
  • 业务层(business)
  • 表现层(presentation/client)

每一层使用对象:

  • 持久层
    • 输入对象:DO
    • 输出对象:DO
  • 业务层
    • 输入对象:BO
    • 输出对象:BO
  • 表现层
    • 输入对象:VO/DTO
    • 输出对象:VO/DTO

2.3 DDD

DDD模型总体分为四层:

  • 基础设施层(infrastructure)
  • 领域层(domain)
  • 应用层(application)
  • 外部访问层(presentation/client)

每一层使用对象:

  • 基础设施层
    • 输入对象:DO
    • 输出对象:DO
  • 领域层
    • 输入对象:DMO
    • 输出对象:DMO
  • 应用层
    • 输入对象:AGG
    • 输出对象:DTO
  • 外部访问层
    • 输入对象:VO/DTO
    • 输出对象:VO/DTO

3 生活实例

这些对象看起来比较复杂,理解成本很高,好像是为了分层硬造出来的概念。其实不然,这些对象在生活中司空见惯,只不过大家并没有觉察。我们设想有一家三口,小明、小明爸爸和小明妈妈,看看这些对象是怎么应用在生活中的。

3.1 MVC

3.1.1 数据对象(DO)

数据对象作用是直接持久化至数据库,是最本质的一种对象,这就像小明在卧室中穿着背心睡觉,这接近于人最本质的一种状态,小明此时是一种数据对象。

3.1.2 业务对象(BO)

小明起床走出卧室,这时小明就不仅仅是他自己了,他还多了很多身份,例如儿子、学生、足球队队员,不同身份输入和输出信息是不一样的。作为儿子要回应家长的要求,作为学生要回应老师的要求,作为足球队员要回应教练的要求。作为小明从数据对象,在不同的身份场景中变成了不同的业务对象。

3.1.3 视图对象/数据传输对象(VO/DTO)

小明吃完早饭准备去上学,但是嘴角粘上了饭粒,出门前要把饭粒擦掉。数据传输对象需要注意简洁性和安全新,最重要的是只携带必要信息,而不应该携带不必须要信息,所以此时小明变成了视图对象。

3.2 DDD

3.2.1 领域对象(DMO)

领域对象要做到领域完备,从本质上来说与业务对象相同,但是通常使用充血模型,业务对象通常使用贫血模型。

3.2.2 聚合对象(AGG)

学校要开家长会要求小明、小明妈妈和小明爸爸全部参加,其中小明负责大扫除,小明妈妈负责出黑板报,小明爸爸负责教小朋友们踢足球。此时学校和家长联系时是以家庭为单位的,家庭就是聚合对象。

4 一体多面

通过上述实例我们看到,即使是同一个自然人,在不同的场景下也有不同的身份,不同的身份对他的要求是不同的,输入和输出也是不同的。这就是一体多面。

同理对于同一个对象,即使其在数据库只有一条数据,但是由于场景的不同,输入和输出也是不同的,所以有了各种看似复杂的对象。我们再回看上面三个问题,可以尝试给出本文的答案:

对象种类多,增加理解成本:这是必须要付出的成本,小明不能嘴角挂着饭粒去上学

对象之间转换,增加代码成本:这是必须要付出的成本,不同角色切换时必须要付出切换成本,小明不能用回应足球队教练的输出回应老师或者老师,这是截然不同的角色

编写代码时有时不同层对象属性几乎一样:小明作为一个自然人,他自身固有特性也是相同的,所以表现在对象上是很多属性是一致的。但是不同的角色是有不同要求的,所以为了一些细微的差别,也是要新增对象的,这是必要的代价

相关推荐
高级程序源13 分钟前
django校企合作实习基地管理系统82506-计算机课程设计、毕业设计
vue.js·后端·python·mysql·django·课程设计·pygame
盖伦发发34 分钟前
Redis 核心教学: 数据结构, 缓存设计, 分布式锁
java·redis·后端·软件工程
卷毛的技术笔记36 分钟前
RocketMQ事务消息:我把分布式事务这层窗户纸捅破了
java·分布式·后端·java-rocketmq
.冰块.44 分钟前
OpenStack 为什么被叫做云操作系统?核心架构深度解析
架构·open stack
Brilliantwxx44 分钟前
【STM32】 从HAL库源码深度解析I2C(源码解析+面试题)
开发语言·stm32·单片机·嵌入式硬件·架构
铁皮饭盒1 小时前
网页端, 40mb离线模型, 自动抠图, 不用 Python,不用服务器,不用 API Key, 不用显卡
前端·javascript·后端
IT_陈寒1 小时前
Redis并发写入踩坑记录:别让超时设置坑了你
前端·人工智能·后端
拒绝内耗。1 小时前
高并发系统如何提升吞吐量?从扩容、缓存、异步到数据库优化
架构·高并发
Bs_MoneyMagnet1 小时前
基于springboot+vue的图书馆预约系统的设计与实现 源码+文档
java·vue.js·spring boot·后端·毕业设计·图书管理系统·计算机毕业设计
PiaoKe___1 小时前
从端云解耦到可编程 Android 实例:云手机架构解析与 Python 批量管控实战
arm开发·python·架构·自动化