白话文解析LiteFlow的理念是什么?什么时候用该怎么用?干货满满
Gitee:https://gitee.com/dromara/liteFlow
Github:https://github.com/dromara/liteflow
LiteFlow一个现代化的开源规则引擎框架,以下文中简称LF。
前言
时常在社区里看到有的小伙伴在那提问:
LF在一个流程中如何暂停,等待操作员完成后,进行下一步该怎么做?
LF流程失败后,下一次能否继续上次的执行?
LF流程适不适合某个我的业务?
LF流程如何定时执行我的某个流程?
还有的同学表示即便全部看完文档,也不知道LF该用在何种业务场景。能够带来什么好处。
究其原因是错误理解了流程的概念和不知道规则引擎的概念。
流程
我们先说流程。
LiteFlow定位是一个规则引擎,而不是流程引擎。它并不完成流程所要做的事,其实压根LF和流程一点关系也没有。
那什么是流程呢,标准的定义是,流程由流程定义,节点要做的事和角色组成。每一个角色做一件事,根据定义的流程定义串起来就叫流程。最典型的例子就是审批流:采购员提交了一张采购申请,部门领导审核,审核通过则到了财务这里,财务专员根据预算进行审核,审核通过到了总监这里,总监审核通过,再到CEO这里签字批准。整个采购单状态变成待采购。然后进行采购流程。
以上就是标准的一个流程。3大要素,流程定义,事和角色一个都不能少。通常在实际落地过程中,流程引擎负责流程的流转和角色的分派。开发人员只需要定义流程,和开发每个角色需要做的逻辑即可。
流程引擎重点强调2点:
流程的定义,下一步是什么,整体的流向,有多少分支。
角色的分派,即下一步该由谁完成。
大部分流程引擎为了灵活性,也提供了流程定义的热更新以及添加角色,修改流程节点更改绑定角色的功能。
虽然LF从EL规则上来看,似乎也是一个个小模块的流转,但是LF并不涉及角色分派这件事。
规则
我们再来看规则引擎的概念。
规则引擎主要强调一件事,把业务中最主要的决策逻辑从程序中抽离出来,用预定义的DSL来实现。并且可以实时改变这些最主要的决策逻辑。
说的再白话点,就是决定逻辑走向的最关键的决策逻辑,不是在代码中的,可以放在外面的任意地方(文件里,数据库里,其他存储,远程获取)。并且这些决策逻辑并不是用你应用的代码语义来实现的。规则引擎提供一套语言,来书写这些决策逻辑。规则引擎也应该提供热更新这些决策代码的功能。
可以看出,规则引擎根本不涉及角色的概念,它更多的适用于一个相对比较复杂的逻辑块。把最核心的部分抽出来用规则引擎定义。
但是整个逻辑块基本要做的还是一件事情。只是部分抽出来而已。
标准的规则引擎处理的例子:
如果有人v我50块,我就去家门口的KFC吃一顿
如果有人v我200块,我就坐地铁去港式餐厅吃一顿
如果有人v我500块,我就打个车,去吃顿日式烤肉
如果有人v我2000块,我就去买身衣服,去吃顿惠林顿牛排,再整瓶酒。
如果有人v我100w,赶紧抽自己一巴掌,看自己醒了没。
有同学看到这,可能会说,那我搞个文件,存groovy代码,我应用每次执行到关键决策的时候,去读取这个文件里的groovy代码,然后解析执行。这不就是规则引擎吗,我要改变决策的时候,每次改那个文件里的groovy代码就行了。
还真是这样!这就是规则引擎!
简单来说,规则引擎就强调3个点:
决策代码不在你的应用程序里
拥有独特的DSL语义书写
实时更新,不用改变应用程序
所以,一些DSL项目也被称作为规则引擎,如Aviator,QLExpress。这些框架提供了热更的接口,稍作包装,就可以开发出一套最基本的规则引擎。
但是我更愿意把这些项目归类为表达式引擎,业界还有著名的SpEL(spring的EL),springframwork expression language,其实从全程就可以看出,官方定义了就是表达式语言。
LF满足决策代码可以不写在应用程序里,也拥有独特的DSL,也支持实时更新。但是LF怎么还拥有流转的功能?LF看起来怎么有点四不像啊?
那LF是什么呢
LF也是作用于一个大的逻辑块的,和角色没关系,满足规则引擎的需要的3个关键点。从这点来说,LF是规则引擎。
LiteFlow中的脚本节点已经满足了规则引擎的全部的定义了。那么LF只做脚本节点就可以了。可以热更,拥有独特的DSL,可以保存在任意地方。
但是LF也可以流转,从一个节点流转到另外一个节点,但是这里的节点是一个个小的拆分的逻辑块。其实这是LF独特的地方,这部分并不是标准规则引擎定义所必须的。我称之为:编排。
编排如何理解呢,说的专业点,这就是逻辑关系反转,看到这里,有些同学可能又开始看不懂了。你丫的怎么还自己造词呢 。
且听我慢慢道来。
spring的出现解决了依赖反转,我们不用spring的时候,对象的装载是自己new的,spring出现后,只需要在xml里声明后,各个代码块都可以注入了。就不用自己new了。这就是依赖反转。相信这个大家学习八股时已经背了无数遍了。
那么逻辑关系的进行,我们大部分代码还是A类调用B类的方法,B类调用C类的方法。这就是逻辑关系的绑死。如果A,B,C三个类在代码层面互不相干。但是我在xml里去规定,这三个的进行顺序。这就是逻辑关系反转。
逻辑关系反转有什么好处呢?
逻辑关系反转后,好处很多,首先每个类不再强依赖,所有的代码都讲究松耦合理论。那么逻辑关系反转后,就完美实现了松耦合。并且LF规定了每个类的声明方式,就显得所有的逻辑类都长的差不多。更加统一。
其次,逻辑关系反转后,你只需要看xml定义就可以大致理解这个大的逻辑块都干了什么事。非常直观。
再次,逻辑关系都可以热更,那么这是一件多么优雅的事情啊。
那么做逻辑关系反转的引擎我称之为:编排引擎。
所以,LiteFlow是规则引擎+编排引擎的结合体。
它既可以热更新最关键的决策逻辑,又可以热更新逻辑关系的组成。
所以LiteFlow做的是更现代化的规则引擎,它在做好规则引擎的基础上,超越了原本规则引擎所规定的范畴。
如何用好LF
其实如果对LF理解够深刻,它几乎是一个应用最核心的驱动器。妥妥神器,无论重构,要灵活,要解耦,它都不在话下。
如果对LF理解不够,那你可能感觉LF没什么用。也不知道该怎么用。
所以这就是我一开头提到的。理解流程和规则逻辑流的概念很重要。
LiteFlow提供的脚本多达7种,这些脚本可以充分书写你的关键决策逻辑。并且LF打通了所有脚本和Java的互通,用脚本写不了的。也可以调用java方法来完成。
LiteFlow提供的独特EL适用于做逻辑反转,让你的巨大复杂的逻辑变成一个个小的积木块,通过DSL来进行组搭,形成你业务的逻辑流。积木块可以是你的java组件,也可以是脚本写的决策逻辑。
所以一般项目推荐的做法,就是首先解耦你的复杂逻辑,按照业务边界拆成一个个小的组件,然后把最经常变动的决策逻辑用脚本组件来实现。加上DSL编写的逻辑关系反转表达式。这样形成的系统,其优雅度是非常高的。
你想想,你的关键决策代码,和逻辑关系均可以进行热改变,你的系统中耦合性几乎降低到了最低。改一个小组件不会牵扯到其他的组件的改变。
再回答开头的问题
如果你看到这,全都能理解的话,那么最开始的几个问题也就能轻而易举的能回答了。
LF因为没有角色的概念,全部流转的只是小逻辑块。所以没法暂停的。因为就相当于你普通写的瀑布式代码调用。只是换了一种方式来写而已。
LF不保存状态,是一个无状态的东西。一般来说,规则引擎都是无状态的。状态这回事其实还是要业务自己做的。况且有状态这回事情非常危险,一般框架不会去保证这个。
LF一般来说,所有用普通瀑布流代码一层层去调用都可以用LF去改造,LF并不针对于某个特殊的领域,都可以用的。除非你的定义是属于标准的流程引擎干的事。那么的确不应该选型LF。
关于定时,也不是LF该干的事。LF提供接口层面的执行器,外面套层定时框架即可。很简单。
LF对标的框架是什么?
LF的目标始一直没变过,那就是:超越Drools。
LF独特的理念是国产自研,全部的代码也是国产自研。非常适合拿来做信创改革。
Drools是国外老牌且一向作为行业标杆的规则引擎。相信了解过这行的都有听说过。
其实Drools只提供了标准的规则引擎,并没有提供逻辑关系反转的特性,而且它的DSL学习成本还是比较大的。而LF则用现成的语言来提供作为脚本,比如js,groovy,aviator,python,lua,甚至java本身也可以拿来做写脚本,这些根本不用再次学习。
LF除了规则引擎之外,更加拓展了规则引擎的范畴,使得LF能做的事情更多。
并且LF支持的存储中间件之丰富的,也绝非Drools能比拟的。
加上LF全中文文档,社区答疑体系在开源中首屈一指。Drools一堆英文文档,去哪答疑?
一定要说LF比不上的Drools的地方。那就是决策表体系。
Drools是不需要指定规则的,由决策表来多项匹配。LF由于提供了逻辑反转,是需要指定特定的规则的。
但是这个LF也准备在2.11.5中提供,弥补最后核心上的短板。
届时LF可以平替Drools。
我会为此一直坚守。
谨此此篇献给关注过LF的同学。