1、 钱包业务背景介绍

很多具有支付、购买功能的应用(比如淘宝、滴滴出行、极客时间等)都支持钱包的功能。 应用为每个用户开设一个系统内的虚拟钱包账户,支持用户充值、提现、支付、冻结、透 支 转赠、查询账户余额、查询交易流水等操作。下图是一张典型的钱包功能界面,你可以 直观地感受一下 。

image.png

一般一个虚拟账户都会对应一个真实的支付账户,有可能是银行卡账户,也有可能是三方支付账户,(比如支付宝、微信) 我们设定钱包只有以下五种核心功能(其他比如冻结、透支、转赠等不常用的功能)

  1. 充值
  2. 体现
  3. 支付
  4. 查询余额
  5. 查询交易流水

1.1、 充值

用户通过三方支付渠道,把自己银行卡账户内的钱,充值到虚拟钱包账号中

image.png


1.2、 支付

image.png


1.3、 提现

image.png


1.4、 查询余额

我们看一下虚拟钱包中的余额数字


1.5、 查询交易流水

查询交易流水也比较简单。我们只支持三种类型的交易流水:充值、支付、提现。在用户充 值、支付、提现的时候,我们会记录相应的交易信息。在需要查询的时候,我们只需要将之 前记录的交易流水,按照时间、类型等条件过滤之后,显示出来即可


1.6、 钱包系统的设计思路

image.png
image.png

image.png


如上图可以看出从两个方向就会两种不同的主表和字段,

  1. 第一种设计思路更好些。因为交易流水有两个功能:一个是业务功能,比如,提供用 户查询交易流水信息;另一个是非业务功能,保证数据的一致性。这里主要是指支付操作数 据的一致性
  2. 保证数据一致性的方法有很多,比如依赖数据库事务的原子性 ,但是,这样的做法不够灵活,因为我们的有可能做了分库分表,支付涉及的两个账 户可能存储在不同的库中,无法直接利用数据库本身的事务特性
  3. 但是,为了保证数据的强一致性,它们的实现逻辑一般都比较复杂,本身的性能也不高,会影响业务的执行时间 . 不保证数据的强一致性,只实现数据的最终一致性 ——-> 交易流水要实现的非业务功能
  4. 实际需要最终结果一致性业务的情况

第一种方式(钱包交易流水) √

支付这样的类似转账的操作,我们在操作两个钱包账户余额之前,先记录交易流水,并 且标记为“待执行”,当两个钱包的加减金额都完成之后,我们再回过头来,将交易流水标 记为“成功”。在给两个钱包加减金额的过程中,如果有任意一个操作失败,我们就将交易 记录的状态标记为“失败”。我们通过后台补漏 Job,拉取状态为“失败”或者长时间处 于“待执行”状态的交易记录,重新执行或者人工介入处理

~~第二种方式(虚拟钱包交易流水) ~~

~~使用两条交易流水来记录支付操作,那记录两条交易 流水本身又存在数据的一致性问题,有可能入账的交易流水记录成功,出账的交易流水信息 记录失败 ~~

问题:
从系统设计的角度,我们不应该在虚拟钱包系统的交易流水中记录交易类型。
从产品需求的角度来说,我们又必须记录交易流水的交易类型
解决对策

我们通过方式一查询上层钱包系统的交易流水信息,去满足用户查询交易流水的功能需求,而虚拟 钱包中的交易流水就只是用来解决数据一致性问题。实际上,它的作用还有很多,比如用来 对账等。限于篇幅


2、 基于贫血模型的传统开发模式

https://gitee.com/daoshizhuagui/designpatene.git
chapter12中mvc
image.png
image.png


3、 基于充血模型的 DDD 开发模式

代码同上哈
本质就是精简了业务模型,将部分业务逻辑放在实体类中

image.png
image.png


4、 辩证思考与灵活应用

4.1在基于充血模型的 DDD 开发模式中,将业务逻辑移动到 Domain 中,Service 类变得很薄,但在我们的代码设计与实现中,并没有完全将 Service 类去掉,这是为什么?或者说,Service 类在这种情况下担当的职责是什么?哪些 功能逻辑会放到 Service 类中?

  1. Service 类负责与 Repository 交流
  2. .Service 类负责跨领域模型的业务聚合功能
  3. .Service 类负责一些非功能性及与三方系统交互的工作

    4.2 在基于充血模型的 DDD 开发模式中,尽管 Service 层被改造成了 充血模型,但是 Controller 层和 Repository 层还是贫血模型,是否有必要也进行充血领 域建模呢?

    没必要

    Controller 层主要负责接口的暴露,Repository 层主要负责与数据库打 交道,这两层包含的业务逻辑并不多,前面我们也提到了,如果业务逻辑比较简单,就没必 要做充血建模,即便设计成充血模型,类也非常单薄,看起来也很奇怪。 尽管这样的设计是一种面向过程的编程风格,但我们只要控制好面向过程编程风格的副作 用,照样可以开发出优秀的软件。那这里的副作用怎么控制呢