规则引擎的设计与实现 | 青训营笔记

111 阅读3分钟

这是我参与「第五届青训营」伴学笔记创作活动的第6天


1、认识规则引擎

1.1、规则引擎的定义

规则引擎是一种嵌入在应用服务中的组件,可以将灵活多变的业务决策从服务代码中分离出来。通过使用预定义的语义模块来编写业务逻辑规则。在执行时接受数据输入、解释业务规则,并做出决策。

好处如下:

  • 解决开发人员重复编码的问题
  • 业务决策和服务本身解耦,提高服务的可维护性
  • 缩短开发路径,提高效率
1.2、组成部分:
  • 数据输入
    • 支持接受使用预定义的语义编写的规则作为策略集。比如price > 500 接受业务的数据作为执行过程中的参数,比如价格、标签等
  • 规则理解
    • 能够按照预先定义的词法、语法、优先级、运算符等正确理解业务规则所表达的语义。
  • 规则执行
    • 根据执行时输入的参数对策略集中的规则进行正确的解释和执行。同时对规则执行过程中的数据类型进行检查,确保执行结果正确
1.3、应用场景:
  • 风控对抗
  • 活动策略运营
  • 数据分析和清洗

2、编译原理基本概念


2.1、词法分析:

词法分析就是把源代码字符串转换为词法单元(Token)的这个过程。

2.2、语法分析:

语法分析就是在词法分析的基础上,识别表达式的语法结构的过程

2.3、抽象语法树:

2.3.1、上下文无关语法:

    语言句子无需考虑上下文,就可以判断正确性。可以使用巴科斯范式(BNF)来表达
    产生式:一个表达式可以由另外已知类型的表达式或者符号推导产生

2.3.2、递归下降算法:

    递归下降算法就是自顶向下构造语法树
    不断的对Token进行语法展开(下降),展开过程中可能会遇到递归的情况。
2.4、类型检查:

2.4.1、类型综合:

    根据子表达式的类型构造出父表达式的类型。例如,表达式A+B的类型是根据AB的类型定义的

2.4.2、编译时检查&运行时检查:

    类型检查可以发生在表达式的编译阶段,即在构造语法树的阶段;
    可以发生在执行时的阶段

3、设计一个规则引擎


3.1、设计目标:

设计一个规则引擎,支持特定的词法、运算符、数据类型和优先级。并且支持基于以上预定义语法的规则表达式的编译和执行。

  • 词法(合法Token)
  • 运算符
  • 数据类型
  • 优先级
3.2、词法分析:
  • 参数:由字母数字下划线组成eg: _ab2、user_name
  • 布尔值: true、false
  • 字符串: " abcd" 、 'abcd’ . `abcd`
  • 十进制int: 1234
  • 十进制float: 123.5
  • 一元运算符:+ -
  • 二元运算符: +- * /%><>= <=== !=
  • 逻辑操作符:&& || !
  • 括号:()
3.3、语法分析:

3.3.1、优先级的表达:

type precedence struct {
    validSymbols   []Symbol           //当前优先级支持的运算符类型
    nextPrecedence *precedence        //更高优先级的
    planner        planner            //当前优先级的处理函数
}

3.3.2、语法树结构:

    一元运算符:左子树为空,右子树为右操作数
    二元运算符:左子树为左操作数,右子树为右操作数括号:左子树为空,右子树为内部表达式的AST
3.4、语法树执行与类型检查:

3.4.1、语法树执行:

   预先定义好每种操作符的执行逻辑。
   对抽象语法树进行后续遍历执行,即:
   · 先执行左子树,得到左节点的值
   · 再执行右子树,得到有节点的值
   · 最后根据根节点的操作符执行得到根节点的值。

3.4.2、类型检查: 检查时机:执行时检查

检查方法:在一个节点的左右子节点执行完成后,分别校验左右子节点的类型是否符合对应操作符的类型检查预设规则

  • '>'符号要求左右子节点的值都存在且为int或float.
  • '!'符号要求左节点为空且右节点的值为bool

4、规则引擎的实现


还需继续更新...