关于java分层领域模型与属性映射的思考

背景:

在近期的解析程序开发工作中,常常需要定义DTO对象,比如与服务端解析程序协作时定义了QueryDto、SubmitDto,再联系接口开发工作中常常使用的VO对象,比如DBizDictVO、DBizActivityVO,因此对相关的领域模型进行了学习总结。

内容:

参考业界的一些规约,梳理了以下几种领域模型:
DO (Data Object): 数据对象,它与数据库表字段一一对应,通过DAO层向上传输数据源对象。
DTO (Data Transfer Object): 数据传输对象,它是Service或Manager层向外传输的对象。
BO (Business Object): 业务对象,它是由Service层输出的封装业务逻辑的对象。
AO (Application Object): 应用对象,它是在Web层与Service层之间使用的对象,极为贴近展示层,复用度不高。
VO (View Object): 显示层对象,通常是Web层向模板渲染引擎层传输的对象。
Query/Param: 数据查询/参数对象,各层接收上层的查询请求。

思考下面几个问题:

为什么要有这些领域模型?
在实际开发中如何选择、使用领域模型?实际项目是如何做的?
使用领域模型时有哪些注意事项或问题?如何解决?

为什么要有这些领域模型?

1.假设不定义DTO和VO,直接将DO用到数据访问层、服务层、控制层和外部访问接口上,当表中删除或修改一个字段,因为DO必须同步修改,那么这种修改将会蔓延到各层,这并不符合高内聚低耦合的原则。
2.通过定义不同的DTO可以控制对不同系统暴露不同的属性,通过属性映射还可以实现具体的字段名称的隐藏,安全性得以提高。
3.不同业务使用不同的模型,当一个业务发生变更需要修改字段时,不需要考虑对其它业务的影响,如果使用同一个模型则可能因为“不敢乱改”而产生很多不优雅的兼容性代码。
4.如果不定义Query/Param对象而使用Map来接收前端的参数,获取时则可能出现反序列化类型丢失问题。另外,很可能因为粗心导致设置和获取时的key不一致,进而引发 BUG。
因此总体来说,使用不同分层的领域模型能够让程序更加健壮、更容易拓展,可以降低系统各层的耦合度。

在实际开发中如何选择使用领域模型?实际项目是如何做的?

下表从请求、响应两个视角列举出项目中每层领域模型的常见用法:
在这里插入图片描述
每一层基本都自己对应的领域模型。如果过于追求每一层都用自己的领域模型,那么一次完整的请求响应过程中就会导致一个对象出现3次以上的转换,这会给实际的开发效率和代码性能带来一定的影响。
在实际项目中,Service/Manager可以操作DO模型,因为这个层级本身的工作也是业务逻辑处理和数据组装。为了更好的职责划分,Controller/TService层的领域模型不允许传入DAO层,DAO层的领域模型不允许传入到Controller/TService。如下图所示:
在这里插入图片描述

分层对于代码规范比较重要,决定代码是否可复用,职责是否清晰。如何分层与人的主观性、项目属性有紧密联系,我认为只要满足职责逻辑清晰,后续维护容易,就是好的分层,并且分层领域模型的优势在系统较大时会体现得更加明显。

使用领域模型时有哪些注意事项或问题?如何解决?

在多层应用中使用领域模型,绕不开的一个问题是常常需要对不同层的对象进行转换,转换方式多种多样,下面分析常见几种解决方案的优劣势。
1.org.apache.commons.beanutils.BeanUtils#copyProperties
2.org.springframework.beans.BeanUtils#copyProperties(java.lang.Object, java.lang.Object)
3.org.dozer.Mapper#map(java.lang.Object, java.lang.Class)
4.net.sf.cglib.beans.BeanCopier#copy()
5.ma.glasnost.orika.MapperFacade#map(S, D)
6.mapstruct
7.原生getter/setter
以上7种转换方式可以进一步分类比较:
1、2、3底层都是利用了反射,性能不高,代码量少,一般只需要一行。
4、5都是基于代理的思想,底层利用了动态字节码技术,4中cglib依赖了asm库,5中orika则是依赖javassist,性能较高,代码量少。
6基于代理在编译期自动生成转换代码,性能高,代码量少。
7原生的性能最高,但代码量大。

1-5基于反射和字节码增强技术实现的映射,当修改一个类属性时,开发人员难以感知到对其它转换类的影响。多次对象映射时,如果属性不完全一致容易出错。

最后,关于7需要开发人员编写的代码量大的问题,发现可以使用IDE插件GenerateO2O来解决。

在这里插入图片描述

觉得有用的话点个赞吧~

猜你喜欢

转载自blog.csdn.net/csdnklsdm/article/details/121105953
今日推荐