业务编程如何进行通用性抽象

00:03

大部分人的疑惑:虽然写了领域里面的通用设计,例如资产入库、出库、调拨,但是在实际的应用中,我们会发现不可能通过领域方法来实现业务,业务通常有条件控制。

我们在最初的领域设计时,首先要考虑通用性,通用性解决的是一个通用领域的问题。

在领域服务之上还有一层业务层,业务层解决具体的问题。

01:25

以滴滴为例,业务就是:

  • 如果是企业用户则不可以使用优惠券
  • 如果是个人用户查询是否有可用的优惠券
  • 如果是专车司机则分成比例为 0.8
  • 如果是优享司机则分成比例为 0.7
  • 如果 。。。。

痛点:编程都是流程式,产品告诉我什么,我就怎么写。

在生活中,数字晶体管的数字显示是通过单个晶体管的亮灭实现的。

如果按照之前的写法,那么就是:

  • 如果显示数字 7,则亮 1 2 3 号晶体管。
  • 如果。。。

所谓面向对象,就是不按照产品的逻辑思考,不是去分析如何显示数字,而是思考如何控制晶体管的亮和灭。

所有的灯都会有一个编号:

100000, 010000, 000001 …

最终可以通过控制编码 110001 来控制。

出入库实际上就对应商品的可用和不可用,也就对应着灯的亮灭。

06:02

以电商系统为例,会有经销商、门店等。

这时候我们会抽象出一个概念——上下文,上下文包含条件里面的企业、个人、专车等。

会将所有的条件放到上下文中,那么基于什么样的条件做什么样的事情,会有一个上下文来协调。

07:19

以请假为例,请假实际上对应这一个业务,请假的上下文包含申请人、理由、天数等。

以报销为例,报销对应一个业务,报销的上下文包含金额、银行卡信息。

对于业务而言,最终要得到一个结果,结果就是一个模型(模型就是领域服务中封装的模型)。

上下文封装 OK 了,就可以进入领域层了。

生活中,人力只看单子,领域服务也是一样,单子各项都有了,再进行处理。

编程时会面向上下文编程,拿到上下文会对上下文进行处理/修改。

条件间存在 AND 或者 OR 的关系。

做什么可以做的细粒度一点,我们可以使用优惠券。

每一个 filter 都可以抽象出一个独立的组件,就是领域服务,例如抵消券的接口。

15:07

我们会抽象出三大部分:

  1. 上下文
  2. 针对上下文的 filter
  3. 针对上下文的条件(条件也可以理解为一个接口,结果是 true 和 false,如何拼装条件就是连接

参考 querydsl。

  1. 一个上下文在经过以上步骤的处理下,最终会形成面向领域服务的 model,model 再配合领域服务实现代码的通用性,上层根据业务随时添加组件。

21:25

在代码中:

element matcher,实际上来自于 bytebuddy,面向字节码编程的抽象。

面向字节码实际上就是改写 class 的。

bytebuddy 可以用于条件的拼装,所有的条件可以通过组件的形式写上。

扩展方式如下:

如果代码写了 400-500 行,如果上线出问题,只能回滚。

如果使用 filter,改动逻辑,下掉这个 filter 或者上线这个 filter,也就是做一个灰度。

修改条件时,不更改,只新增。

25:58

Filter 没有现成的,实际上是我们封装的业务逻辑点。

实际上就是责任链。