码迷,mamicode.com
首页 > 其他好文 > 详细

设计模式简记-设计符合设计原则的业务系统之实现

时间:2020-04-26 12:37:47      阅读:73      评论:0      收藏:0      [点我收藏+]

标签:通用   数据校验   代码   反转   就是   设计   需要   代码重复   就会   

3.10 实战一:如何开发实现一个遵从设计原则的积分兑换系统?

3.10.1业务开发包含的工作

  • 无外乎三方面的工作要做:接口设计、数据库设计和业务模型设计
  • 数据库和接口的设计非常重要,一旦设计好并投入使用之后,这两部分都不能轻易改动。
    • 改动数据库表结构,需要涉及数据的迁移和适配;
    • 改动接口,需要推动接口的使用者作相应的代码修改。
3.10.1.1 积分系统的数据库设计
  • 只需要一张记录积分流水明细的表

    积分明细表
    id 明细id
    user_id 用户id
    channel_id 赚取或消费渠道
    event_id 相关事件ID,如订单id,评论id,优惠券换购交易id
    credit 积分(赚取为正,消费为负)
    create_time 积分赚取或消费时间
    expired_time 积分过期时间
3.10.1.2 积分系统的接口设计
  • 接口设计要符合单一职责原则,粒度越小通用性就越好

  • 接口粒度太小也会带来一些问题:通讯开销;原子操作被分开,涉及分布式事务数据一致性问题。

  • 借鉴 facade(外观)设计模式,在职责单一的细粒度接口之上,再封装一层粗粒度的接口给外部使用。

    接口 参数 返回
    赚取积分 userId,channelId,eventId,credit,expiredTime 积分明细ID
    消费积分 userId,channelId,eventId,credit,expiredTime 积分明细ID
    查询积分 userId 总可用积分
    查询总积分明细 userId+分页参数 id,userId,channelId,eventId,
    credit,createTime,expiredTime
    查询赚取积分明细 userId+分页参数 id,userId,channelId,eventId,
    credit,createTime,expiredTime
    查询消费积分明细 userId+分页参数 id,userId,channelId,eventId,
    credit,createTime,expiredTime
3.10.1.3 业务模型设计
  • 三层架构的Service

    ^: 大部分业务系统的开发都可以分为 Controller、Service、Repository 三层。Controller 层负责接口暴露,Repository 层负责数据读写,Service 层负责核心业务逻辑,也就是这里说的业务模型

  • 简单系统选择贫血开发模式

    ^: 基于贫血模型的传统开发模式和基于充血模型的 DDD 开发模式,前者是一种面向过程的编程风格,后者是一种面向对象的编程风格,无论是DDD还是OOP,高级开发模式应对复杂系统;积分系统业务相对比较简单,选择简单的基于贫血模型的传统开发模式就足够了。

  • 简单选择跟其他业务系统一块部署

3.10.2 为什么分MVC三层开发?

3.10.2.1 分层能起到代码复用的作用
  • 同一个 Repository 可能会被多个 Service 来调用,同一个 Service 可能会被多个 Controller 调用
  • 满足DRY原则
3.10.2.2 分层能起到隔离变化的作用
  • 分层体现了抽象和封装:Repository 层封装了对数据库访问的操作,提供了抽象的数据访问接口

  • 基于接口而非实现编程的设计思想,Service 层使用 Repository 层提供的接口,并不关心其底层依赖的是哪种具体的数据库。方便替换数据库的时候:只需要改动 Repository 层的代码

  • Controller、Service、Repository 三层代码的稳定程度不同、引起变化的原因不同,分成三层来组织代码,能有效地隔离变化:Controller可能经常变化,分层后Controller变化并不影响其他层的稳定。

3.10.2.3 分层能起到隔离关注点的作用
  • Repository 层只关注数据的读写。
  • Service 层只关注业务逻辑,不关注数据的来源。
  • Controller 层只关注与外界打交道,数据校验、封装、格式转换,并不关心业务逻辑。
  • 三层之间的关注点不同,分层之后,职责分明,更加符合单一职责原则,代码的内聚性更好
3.10.2.4 分层能提高代码的可测试性
  • 代码都放到一个类中,这个类的代码会因为需求的迭代而无限膨胀。
  • 代码过多之后,可读性、可维护性就会变差。
  • 拆分代码:拆分有垂直和水平两个方向。
    • 水平方向基于业务来做拆分,就是模块化;
    • 垂直方向基于流程来做拆分,就是这里说的分层。
  • 还是那句话,不管是分层、模块化,还是 OOP、DDD,以及各种设计模式、原则和思想,都是为了应对复杂系统,应对系统的复杂性。对于简单系统来说,其实是发挥不了作用的,就是俗话说的“杀鸡焉用牛刀”。

3.10.3 BO、VO、Entity 存在的意义是什么?

^ : 针对 Controller、Service、Repository 三层,每层都会定义相应的数据对象,它们分别是 VO(View Object)、BO(Business Object)、Entity,例如 UserVo、UserBo、UserEntity。在实际的开发中,VO、BO、Entity 可能存在大量的重复字段,甚至三者包含的字段完全一样。在开发的过程中,经常需要重复定义三个几乎一样的类,显然是一种重复劳动。

3.10.3.1 更加推荐每层都定义各自的数据对象这种设计思路
  • VO、BO、Entity 并非完全一样。比如,我们可以在 UserEntity、UserBo 中定义 Password 字段,但显然不能在 UserVo 中定义 Password 字段,否则就会将用户的密码暴露出去。
  • VO、BO、Entity 三个类虽然代码重复,但功能语义不重复,从职责上讲是不一样的,是符合DRY原则的。
  • 为了尽量减少每层之间的耦合,把职责边界划分明确,每层都会维护自己的数据对象,层与层之间通过接口交互。对于非常大的项目来说,结构清晰是第一位的!
3.10.3.2 既然 VO、BO、Entity 不能合并,那如何解决代码重复的问题呢?
  • 继承可以解决代码重复问题

    可以将公共的字段定义在父类中,让 VO、BO、Entity 都继承这个父类,各自只定义特有的字段。因为这里的继承层次很浅,也不复杂,并不会影响代码的可读性和可维护性。后期如果因为业务的需要,有些字段需要从父类移动到子类,或者从子类提取到父类,代码改起来也并不复杂。

  • 组合也可以解决代码重复的问题

    可以将公共的字段抽取到公共的类中,VO、BO、Entity 通过组合关系来复用这个类的代码。

3.10.3.3 不同分层之间的数据对象该如何互相转化?

? 整个开发的过程会涉及“Entity 到 BO”和“BO 到 VO”这两种转化

  • Java 中提供了多种数据对象转化工具,比如 BeanUtils、Dozer 等,可以大大简化繁琐的对象转化工作。
3.10.3.4 贫血模型违背封装特性如何解决?
  • VO、BO、Entity 都是基于贫血模型的,而且为了兼容框架或开发库(比如 MyBatis、Dozer、BeanUtils),我们还需要定义每个字段的 set 方法。这些都违背 OOP 的封装特性,会导致数据被随意修改。
  • Entity 和 VO 的生命周期是有限的,都仅限在本层范围内,即便设计成贫血、定义每个字段的 set 方法,相对来说也是安全的
  • Service 层包含比较多的业务逻辑代码,所以 BO 就存在被任意修改的风险了。但是,设计的问题本身就没有最优解,只有权衡。为了使用方便,我们只能做一些妥协,放弃 BO 的封装特性,由程序员自己来负责这些数据对象的不被错误使用。

3.10.4 总结用到的设计原则和思想

高内聚,松耦合 不同功能划分到不同的模块,让模块高内聚,松耦合
单一职责原则 模块设计尽量职责单一;分层设计也是为了职责单一
依赖注入 MVC:下层的类通过依赖注入的方式注入到上层的代码
依赖反转原则 通过类似spring IOC这样的容器来管理对象的创建、生命周期
基于接口而非实现编程 MVC:Service层使Respository层提供的接口,不关心底层数据库类型
封装、抽象 分层体现了抽象和封装的思想,隔离关注点和变化
DRY与继承、组合 VO、BO、Entity代码重复,但语义不重复,符合DRY;
解决重复问题可用到继承和组合的方法
面向对象设计 合适的功能放到合适的模块中,体现了面向对象设计(合适的代码放到合适的类)

设计模式简记-设计符合设计原则的业务系统之实现

标签:通用   数据校验   代码   反转   就是   设计   需要   代码重复   就会   

原文地址:https://www.cnblogs.com/wod-Y/p/12778696.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!