一、模型图
该模型是自己摸索出来的一种web服务设计模型,整个围绕核心业务逻辑处理模块进行。在这个模型中,core业务逻辑处理中心处理负责执行所有逻辑处理流程,该模块所需要的所有副作用操作都以“插件”的形式从参数中传入。而所谓的“插件”,其实就是一些处理副作用读写的函数。
二、模块说明
service模块
提供网络服务,根据具体使用的技术,对客户端来的请求进行路由分发,提取出请求参数,对参数进行解密、格式转换、验证,对客户端进行登录认证等;对要返回给客户端的数据进行包装,比如转换成客户端所要求的格式、加密、加status-code等。这些操作独立于业务逻辑之外,是各个请求所通用的,通常可以以中间件的形式来实现。
core业务逻辑处理模块
业务逻辑处理模块实现了整个业务流程,在这个模块中,数据来源有两块:一是客户端请求所带的参数,二是从插件中获取的数据;也就是,这个模块会以参数的形式告诉调用者,我需要哪些插件(fn集合),需要哪些其他参数;调用者负责提供正确的插件和参数。示例:
(defn handle
[{:keys [fn-save-db fn-user-info]} username]
(let [user-info (fn-user-info username)]
(fn-save-db use-info)))
这个核心逻辑处理函数告诉调用者,我需要两个插件:一个保存数据到数据库,一个获取用户信息的插件;需要一个参数——用户名;这些插件集合,通过一个map结构传过来。
该模块的输出就是要返回给客户端的消息数据,这些数据还需要service层根据不同使用的网络技术做一些处理。
db-center模块
该模块封装了后台所需数据所有数据来源:数据库、内存数据、第三方远程调用、随机数据、时间数据等,也就是将所有副作用的操作函数封装了起来。
插件组装模块
该模块非常小,就是为每个请求对应的业务逻辑处理函数提供所需的插件集合。
resp-msg模块
根据客户端与服务器消息协议,组装对应的消息体。
三、优点
所有数据都来源于参数
该模型的主要优点是:核心业务逻辑处理模块通过接口参数的方式,明确告知调用者:要用这个模块,就需要提供该模块所需要的插件和数据。调用者可以在保证插件接口不变的基础之上,根据不同的需要实现插件。在使用这个模块时,控制权在调用者手中。
易于测试
保证核心业务逻辑的正确性和可靠性,是保证系统正确性的核心。测试时,可以用假的数据来实现插件,使输入到业务逻辑模块的插件返回我们指定的值(或执行我们指定的操作),这就相当于测试一个“纯函数”:输入什么参数,就输出对应的返回值。如此一来,可以很轻松地进行单元测试,保证核心逻辑的正确性。
而在系统实际运行时,就可以传入用真实数据库技术实现的插件了。
副作用的封装
db-center中封装了所有副作用操作,包括真实数据库读写,rmi/rpc/http等远程调用,内存数据读写,随机数生成,当前时间获取等;这些数据操作通过统一接口暴露给外部调用者。根据不同的使用场景,可以对这些接口进行不同的实现,比如用假数据实现一个local版(内存版)的服务(不远处调用数据库服务以及其他第三方服务等)。
四、缺点
核心业务逻辑处理模块,并不是一个真正的“纯函数”,虽然在测试的时候,可以像测试纯函数一样进行单元测试,然而因为模块中在存在写操作,如fn-sava-db,这些操作会改变一些外部资源。因此这个模块还是不安全的,然而核心业务逻辑理论上讲,只需处理逻辑,应该是非常纯的一个过程,数据的写操作并不应该是逻辑过程该干的活,因此这个模型仍有待改进。