web服务程序设计探索(4)——数据总线-分层模型

一、数据总线-分层模型

这里写图片描述
为了使整个业务处理流程中,各层次功能界限划分更为清晰,降低各层次间的耦合性,参考计算机系统数据总线的方式,使数据流向各层。可以将数据总线想象成一根大的水管,整个流程像是“污水处理”过程:服务层(service层)接到最初的污水之后,将里面的一些物质初步整理出来(提取出参数,转化格式等),然后放入一个包(event-package)中,标注好这个包的ID以及它在service层的处理结果,然后扔回到水管中;包沿水管流到下一层(core业务逻辑层)进行处理,core业务逻辑层拿到service层处理后的数据,根据ID对应的业务规则进行处理,将处理结果塞回到包中,再扔回到水管;包流到db数据修改层,这一层会检查这个包是不是自己要处理的包,如果不是原样扔回到水管,如果是,则进行处理,并将处理结果塞回到包中,把包扔回到水管…最后包流回到service层,这层按照具体的协议,从包中取出数据,处理后返回给客户端。

整个过程中,每一层的输入都包含一个event-package流入的接口(还有自身所需的一些其他参数);返回一个更新之后的event-package;各层之间没有直接的函数耦合。

二、数据包结构说明

event-package的数据结构如下:

{:event-id :事件ID
 :result   :success/:failed ;;事件处理结果
 :reason   nil ;;导致事件处理结果(失败)的原因
 :params   {:param1 .. :param2};; 事件参数
 :db       {};;db层所需要的数据
 :resp     {};;resp层所需要的数据
}

对于每个业务请求,流经每一层时,每层的处理结果都会反映在:result字段中,如果在该层处理失败,则会将:result改为:failed,并且在:reason中说明原因(如:invalid-username);core业务逻辑处理层,依旧是系统的核心层,它决定这整个业务处理的核心逻辑,其处理后,会将数据放入:resp和:db(如果需要修改数据库);:db层和:resp层就可以从这些字段拿到自己处理时所需要的数据;

二、层次说明

service层

该层为服务层,主要提供网络服务,如http服务;这层会对客户端过来的消息进行解析,如从url或body中取出参数,对参数的数据格式进行转换,对请求进行路由等;提取出来的参数,放在event-package的:params字段中;

core业务逻辑处理层

该层依旧为系统的核心层,根据每个请求对应的业务处理规则,对业务进行处理,处理后的数据。该层是一个纯函数层,它的数据来源有两个:一个event-package里面的params,一个是db-data;它的输出是一个更新后的event-package:如果请求不满足业务规则,将设:result 为:failed,并在:reason中注明原因;如果满足业务规则,则将处理之后的数据放到:db和:resp中,供下层使用。

db数据修改层

该层为副作用层,也就是对数据进行修改,它从db中获取自己处理过程所需要的数据。该层并不是一个脱离业务处理流程的、单纯执行transaction的层,它需要理解自己需要对那些event-id进行处理,它需要知道自己在每个业务流程中要承担的角色。同样它会将处理结果反映到event-package中。

resp-msg层

该层主要根据上面层次的处理结果,生成返回给客户端消息内容,但这个消息并不是最终消息,只是将上面层次的处理结果“翻译”成消息协议所规定的消息。比如如果流入的event-package为:

{:event-id :add-user
 :result :failed
 :reason :invalid-username
 :db     nil
 :resp   nil}

resp会将其翻译为:

{:result :failed :data {:msg "非法用户名“ :reason :invalid-username}}

该数据被传回到service层,service层会为每个reason指定相应的http状态码,然后加上:data数据,返回给客户端。

三、优点

低耦合性

每一层都是相互独立的,甚至是可拆装的。比如拿掉了db层,整个程序也能正常走通。层与层之间的耦合是数据耦合,也就是说,只要该层能够理解这个数据结构,就可以通过拿到的数据进行处理。

开发节奏好、效率高

每层都是独立的,因而可以独立开发。只要定义好接口的数据结构,就可以并行开发或者先行开发某一层;比如可以先开发最核心的core业务逻辑处理层,再开发resp,这样就能将核心业务通过单元测试用例跑起来(因为这两层是纯函数的),并且通过测试用以保证核心逻辑的正确性和稳定性;逻辑开发完成,就可以实现service层,这样可以迅速和客户端实现联调;最后再开发db层,使用真实的数据读写;

先写纯函数层、再写副作用层,尽力将开发时间停留在纯函数的编写,这是一个好的开发节奏。纯函数具有易测试的特点,因此适合于“测试驱动开发”的模式,能够快速开发出正确、稳定的业务逻辑。

易于维护

因为层次间相互独立,每次基本上都可以使用自己的特有的技术,比如可能需要改变的db层:开始使用的是mysql的数据库进行存取,而现在需要使用datomic数据库。此时可以很轻易的进行替换,因为event-package中有db层所需要的所有数据,并且这些数据都是业务数据,并不是根据db层所使用的技术定的。再比如service层,如果不想使用http提供网络服务,而是使用socket,那么也只需要更换service层即可,只是接受客户端参数的处理和回复消息处理因技术不同而发生改变,不会影响其他层次。

易于扩展

比如要加入业务日志记录,可以再加一个log层,而不需要在其他层次中插入各种log/error,log/info语句。这有点像spring的面向切面编程;再比如,如果要将数据发送到某个远程服务进行处理,可以选择修改db层(封装了各种数据库处理,远程调用等操作),也可以选择再加一层。

四、缺点

一个大的event-package数据结构,感觉有点大。每个请求处理,都会需要修改event-package,而修改event-package像是业务之外的“额外操作”。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值