一开始看《聊聊架构》这本书有点懵的,因为觉得架构就是软件架构,里面提到一些生命周期,听上去学术,但实际上是很有道理的,架构是无处不在的,这里我会总接一些觉得还不错篇章,也作为一次读书笔记吧。
什么是代码
先看一张图
上面的方形可以理解为软件,结合我自己的编程经验,这就是一个典型的后端软件模型。
这里可以把代码分为三部分:1.访问业务生命周期的代码2.业务逻辑代码。3.存储部分代码
上图的服务就是访问业务生命周期的代码,业务逻辑就是业务。
那什么又是服务呢?
书里的一个例子很形象:客户去银行办业务,接待客户的是银行柜员,而不是专业业务人员。柜员就是一个服务,以用户听的懂的方式去和用户沟通,并把用户的要求转化为业务语言,再由银行内部的专业业务人员执行相应操作,柜员最后把执行结果转化为用户的语言,为其服务。所以服务就是一个通道,是访问业务的一个通道。
但上面的图暴露了一个很严重问题,过于耦合,服务为完成用户访问生命周期,但上图却承担包括了组合业务和存储这两个还要提供用户访问。用户为完成访问业务逻辑生命周期,需要做的是:
- 服务首先要把业务的状态从存储中加载。这是一个生命周期,主体为业务状态获取。
- 服务调用并组合业务逻辑完成业务的访问。这是一个生命周期,主体为业务访问。
- 服务把业务逻辑执行后的状态保存到存储中。这是一个生命周期,主体为业务状态保存。
这里拿自己的后端代码打个比方,之前为了高效开发,公司的后端代码架构基本就是上面这种架构,也就是MC架构,这里的C端控制器做的工作很多,有业务逻辑,有粘合代码,甚至还包括了存储获取代码。每个业务没有重用性,不过幸好写的是基于restful架构的api,每个业务都是一个接口,
业务代码基本上是独立的。但是业务代码没有重用性可言,所以上面这种模型是很不好的,我们应该弃用。
拆分后的架构

拆分后的架构如图所示,可以看出各部分是独立的,黏合代码整合了业务和存储,服务则整合了黏合代码。在实际应用中,服务为控制器中的action,业务在独立的logic层,存储在model层。而黏合代码可以看做一个管理者即XXManager,比如一个订单业务黏合代码就是一个OrderManager类。
为什么要这样做
有些人会问为什么不把存储挂在服务上,这样黏合代码就不需要了。但这样的后果就是让银行的核心人员,直接面接待客户,用户的访问因为沟通效率低就变得非常困难。黏合代码相当于一个具备行为和记忆的完整业务人,不应该直接面对用户。
正确的方式应该是给用户独立的访问通道,就好比银行采用柜台人员来做接待一样。服务相当于柜台是面向用户的。用户的需求是变化最频繁的,服务的方式可以避免频繁的用户需求变化对内部分工的冲击。没有服务的保护会导致用户的需求直接冲击存储,西存储非常脆弱必须保护起来。还有人会问,为何不把存储挂在业务上?这也是可以的,大家把这叫作活动记录( Active record)但这会让关心业务模型的代码人员,受到存储的影响,必然无法专注于业务生命周期上。并且存储的变动,会极大地影响业务生命周期所以一般也不采用这种方式。毕竟内存持久化的问题是计算机体系结构本身的问题,不应该由业务代比码人员来解决。采用存储挂在黏合代码上的方式,可以让黏合代码成为一个完整的虚拟人虚拟人具备记忆和行为,可以均衡地处理上述两个问题。有以上两种方式的好处,而又没有太大的弊病,这才是最合适的。因此代码就划分出了以下几个责任
- 服务专注于用户(User)的需求,通过组织黏合代码,也就是虚拟人所提供的生命周期活动完成需求。
- 黏合代码专注于管理业务中对象的生命周期,并且通过存储保存或加载业务中对象的状态,实现对业务虚拟人的模拟。
- 业务专注于实现业务的生命周期活动。
- 存储专注于数据的保存和加载,并让数据和存储设备的存储粒度一一对应。
分工后各个业务都是独立的,不同部分的开发人员可以并行的进行开发,不仅提升力效率而且缩短了时间。比如负责业务逻辑的可以专注与业务逻辑的开发,存储部分独立了那么DBA做一些sql优话也不会影响到业务层。各个部分都是独立的,虽然前期会加大一些工作量,但是职能清晰后的代码是易维护的,能进行单元测试的。