web服务程序设计探索(3)——中间件模型

来源:互联网 发布:淘宝最畅销产品排行榜 编辑:程序博客网 时间:2024/06/06 20:43

一、中间件模型

这里写图片描述

中间建模型是插件模型的一种改进版。上次提高插件模型中,核心业务逻辑处理模块并不是一个真正的“纯函数”,因为它里面存在写操作。中间件模型正是将这些写操作剥离出来,放在一个中间件中。中间件只负责执行事务(包括数据库操作,rmi/rpc/http远程调用,内存数据操作等),不理解业务,比如它只负责SQL语句的执行,而不知道SQL是如何组织的,也不知道SQL的内容。

二、模块说明

因为大多数模块和插件模型一样,这里只介绍不一样的模块。

插件组装模块

该模块的职责还是为核心业务处理模块提供一些插件,但不同的是,这些插件全部都是读数据的插件,而不包括写数据插件。因为中间件模型中,核心业务处理模块的写操作全部被提出来,作为该模块的返回值,流入到事务执行中间件中被处理。因此,逻辑处理模块只需要读数据的中间件,以保证该模块的“纯函数性”。如:

(defn handle     [{:keys [fn-user-info fn-update-user]} username gender]    (let [user-info (fn-user-info username)          update-tx (fn-update-user (assoc user-info :gender gender)]          ;; 逻辑处理模块返回的数据结构         {:resp {:user-info user-info}          :db   update-tx          :mem  {:method :update-user                 :params user-info}          :rmi  {:method :update-user                 :params [username gender]}})

注意,上面的fn-update-user插件,并不是执行更新操作的插件,而是用于生成更新语句的插件。此时,逻辑处理模块返回的数据数据结构中,db表示要执行的数据库操作,mem表示要执行的内存操作,rmi表示要执行的远程调用操作。

事务执行中间件

事务执行中间件在拿到逻辑处理模块返回的数据之后,会执行:db,:mem,:rmi中要指定操作。中间件只负责执行事务,不理解业务。

三、优点

纯函数

该模型的核心优点是:将核心业务逻辑处理模块变成了“纯函数”,所有数据来源于参数,函数没有任何副作用,返回值包含了要返回的全部信息,使得这个模块更安全,也更加容易被测试。

副作用压缩在最小范围

因为所有的事务都只是在事务执行中间件中执行,使得副作用被压缩在了中间件这一层。另外,因为中间件是被排除在整个业务处理逻辑之外的(它不理解业务),可以认为整个业务处理就是一个纯函数!

四、缺点

代码复杂度增加

因为中间件不理解业务,使得业务逻辑处理模块需要负责安排准备好要执行的事务以及事务执行所需要的所有参数,甚至还可能需要制定这些事务执行的顺序等,并从业务处理模块的返回值中返回。这样在业务处理模块的返回值变为一个很复杂的结构。

一个奇怪的返回值

核心业务模块的返回值如下:

{:resp {:user-info user-info :db   update-tx :mem  {:method :update-user        :params user-info} :rmi  {:method :update-user        :params [username gender]}}

这是一个很奇怪的数据结构,它的语义感觉毫无内聚性。其中:resp表示需要返回给客户端的数据,:db表示写数据库的sql语句,:rmi表示要执行的远程调用操作及所需参数,其中:resp中的数据才是纯粹的数据,而:mem:rmi则是自带语义的数据(即用数据表达的操作)。

个人理解的一种合理的业务处理流程应该是:输入业务处理所需参数,输出业务处理相关的数据。举个例子:

公会会长向某个玩家发送一张加入公会的邀请函

在这个场景中,抽象出来的业务处理流程是:新增一张邀请函。处理过程可能为:

(defn add-invitation    [db-data {:keys[inviter invitee]}]    ;; TODO 被邀请人是否存在?    ;; TODO 被邀请人是否已经在公会?    ;; TODO 邀请人是否有邀请权限?    ;; 所有条件都满足,则生成一张新的邀请函    {:inviter inviter     :invitee invitee     :guild  "公会名"})

这样才是一个内聚的业务处理模块:当所有业务条件都满足时,成功生成一张完整的邀请函(包含邀请函的所有信息)。至于这张邀请函有没有被送回到客户端,以怎样的格式送回到客户端,是否被保存到数据库,已什么样的格式保存,怎样被保存…这些都不应该是业务逻辑模块所要关心的。

原创粉丝点击