
地 址:北京市密云区66号
电 话:15323008686
网址:dsesh.com
邮 箱:84188640@qq.com
如何做遵从设计原则的何做换系积分(fen)兑换系统?(设计模式二十二)
业务开(kai)发包括哪些工作?

三方面:接口设计、数据库设计和业务模型设计(ji)(也(ye)就(jiu)是(shi)设计式(shi)业务逻辑)。

数据库和接口的原则设计非常重要,一旦设计好并投入使用之后,分兑这两部分都不能(neng)轻易改(gai)动。统设先数据库和接口设计,计模业务逻辑代码侧重内部实现,何做换系不涉及被外部依赖的设计式接口,也不包含持久化的原则数据,所以对改动的分兑容忍性更(geng)大。

针对积分系统,统设我们先来看(kan),计模如何设计数据库。何做换系
接下来,设计(ji)式我们再来看(kan),原则如何设计积分系统的接口。
最后(hou),我们来看业务模型的(de)设计。
业(ye)务相对比较简单,所以,选择简单的基于贫血模型(xing)的传统开发模式就足够了。
为什么要分 MVC 三层开发?
几点原因:
1.分层能起到代码复用的作用
2.分(fen)层能起到隔离变(bian)化的作用
3.分层能起到隔离关(guan)注点(dian)的作用
Repository 层只关注数据(ju)的读写。Service 层只(zhi)关注业务逻辑,不关注数据的来源。 Controller 层只关注与外(wai)界打(da)交道,数据校验、封装、格式转换,并(bing)不关心业务逻辑。三层之间的关注点不同,分层之后,职责分明,更加符合单一职责原则,代码的内聚性更(geng)好。
4.分层能提高代码的可(ke)测试性
后面讲单元测试的(de)时候,我(wo)们会讲到,单元测试不依赖不可控的外部组件,比如数据库。分层之后,Repsitory 层的代码通过依赖注入的方式供 Service 层使用,当要测试包含核心业务(wu)逻辑的(de) Service 层代码的时候,我们可以用 mock 的数据源替代真实的数据库,注入到 Service 层代码中。
5.分层能(neng)应对系统的复杂性
所有的代码都放到一个类(lei)中,那这个类的代码就(jiu)会因为需求的迭代而无限膨胀。我(wo)们知道,当一个类或一个函数的代(dai)码过多之后,可读性、可维护性就(jiu)会变(bian)差。那(na)我们就要想办法拆分。拆分有垂直和水平两个方向。水平方向基(ji)于业务(wu)来做拆分,就是模块化;垂直方(fang)向基于流程来做拆分,就是这(zhe)里说的(de)分层。
BO、VO、Entity 存在的意义是什么?
针对 Controller、Service、Repository 三层,每层都会定义相应的(de)数据对象,它们分别VO(View Object)、BO(Business Object)、Entity,例如UserVo、UserBo、UserEntity。在实际的开发中,VO、BO、Entity可能存在大量(liang)的重复字段,甚至三者包含的字段完全(quan)一样。在开发的过程中,我们经常需要重复定义三个几乎一样的类,显然是一种重复劳动。
相对于每层定义各自的数据对象来说,是不是定义一个公共的数据对象更(geng)好些(xie)呢?
实际上,我更加推荐每(mei)层都定义各自(zi)的数据(ju)对象这种设计思路,主要有以下3个(ge)方面(mian)的原(yuan)因。
VO、BO、Entity并非完全一样。比如(ru),我们可以在 UserEntity、UserBo 中定义 Password 字段,但显然不能(neng)在 UserVo 中(zhong)定义 Password 字段,否则就会将用户的密码暴露出去。
VO、BO、Entity 三个(ge)类虽然代码重复,但功能语义不重复,从(cong)职责上讲是不一样的。所以,也并不能算违背 DRY 原则。在前面讲到 DRY 原则的时候(hou),针对这种情况,如果合并为同一个类,那也会存在后期因为需求的变化(hua)而需要再拆分的问题。
为了尽量(liang)减少每(mei)层之间的耦合,把职责边界划分明确(que),每层都(dou)会维护自己的(de)数据对象,层与层之(zhi)间通过接口交互。数据从(cong)下(xia)一层传递到上一层的时候,将下一层的数据对象转化成上一层的数据(ju)对象,再继续处(chu)理。虽然这样(yang)的设计稍微有些繁琐,每层都(dou)需要定义各自的数据对象,需要做数据对象之间的转化,但是(shi)分层清晰。对于非常大的项目来说,结构清晰是第一位的!
既然VO、BO、Entity不能合并,那如(ru)何解决代(dai)码重复的问题(ti)呢?
我们可以将公共的字段定义在父类中,使用继承或(huo)者组合。
代码重复问题解决了,那(na)不同分层之间(jian)的数据对象该如何互相转(zhuan)化呢?
Java 中提供了多种(zhong)数据(ju)对(dui)象转(zhuan)化工(gong)具,比如 BeanUtils、Dozer等,可以大大简化繁琐的对象转化工作。如果你是用其他编程语言来做(zuo) 开发,也可以借鉴 Java 这些(xie)工具(ju)类的设计思路,自己在项目中实现(xian)对象转化工具类。
VO、BO、Entity 都是基于贫血模型的,而且为了(le)兼容框架或(huo)开发库(比如MyBatis、 Dozer、BeanUtils),我们还(hai)需要定(ding)义每(mei)个字段的 set 方法。这些都(dou)违背 OOP 的封装特性,会导致数据(ju)被随意修改。那到底该怎么办好呢?
前面我们也提到过,Entity 和 VO 的生命周期是有(you)限的,都仅限在本层范围内。而对应的 Repository 层和Controller层也都不包含太多业务逻辑,所以也不会有太多代码随意修改数(shu)据(ju),即便设计成贫血、定义每(mei)个字段的 set 方法,相对来说也是(shi)安全的(de)。
总结用(yong)到的(de)设计原则和思想
重点回顾
需要掌握的(de)重点内容(rong)。
1. 为什么要分MVC 三层开发?
5 点原因:
分层能起到代码复用的作(zuo)用分层能起到隔离变化的作用分层能起到隔离关注点的作用分层能提高代码的可测试(shi)性分层能应(ying)对系统(tong)的复杂性(xing)2.BO、VO、Entity 存在的意义是什么?
从设计的角度来说,VO、BO、Entity 的设计(ji)思路并不违反 DRY 原则,为了分(fen)层清晰、减少耦合,多维护几个类的成(cheng)本也并不是不能接受的。但是,如果你真的有代码洁癖,对于代码重复(fu)的问题,我们可以通过继承或者(zhe)组合来解决。
尽管 VO、BO、Entity 的设计违背 OOP 的封装特性(xing),有被(bei)随意修改的风险。但 Entity 和 VO 的生命周期(qi)是有限的,都(dou)仅限(xian)在(zai)本层范围内,相对(dui)来说是安全的。Service 层包含比(bi)较多的业务逻辑代码,所以 BO 就存在被任意修改的风险了。为了使用方便,我们只能做一些妥协,放弃BO的封装(zhuang)特性,由程序员(yuan)自己来负责这些数据对象的不被错误使(shi)用。
3. 总结用到的设计原则和思想
从表(biao)面上看,做业务开发可能并不是特别有技术挑战,但是实际(ji)上,如果你(ni)要做到知其然知(zhi)其所以然,做(zuo)到透彻理解、真的懂,并不是件(jian)容易的事情。深挖一下,你会发现这其中还是蕴含了很多设计原则、思想和(he)模式的。