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

88 阅读4分钟

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

一、本堂课重点内容

本节课程为实践课,主要分为四个方面:

  1. 规则引擎的组成部分和应用场景
  2. 规则引擎的设计与实现原理
  3. 设计并实现一个规则引擎 - YoungEngine
  4. 实现一个Web版规则引擎(自行实现)

二、详细知识点介绍

1 认识规则引擎
  • 定义:规则引擎是嵌入在应用中的组件,它将业务决策从应用程序代码中抽离出来,并使用预定义的语义模块编写决策。接受数据输入,解释业务规则,并根据规则做出决策。

  • 好处

    • 业务人员可以直接去修改业务和决策,解决开发人员重复编码的问题。
    • 业务决策与服务本身解耦,提高服务的可维护性。
    • 缩短开发路径,提高效率。
  • 组成部分

    • 数据输入:接受使用预定义的语义编写的规则作为策略集。
    • 规则理解:能够按照预定义语义正确理解业务规则。
    • 规则执行:根据输入的参数对策略集中的规则进行正确的理解和执行,在执行过程中对数据类型进行检查。
  • 应用场景:风控对抗、活动策略运营、数据分析和清洗。

2 编译原理基本概念
  • 词法分析

    • 概念:把源代码字符串转换为词法单元(Token)的过程。

    • 识别Token:有限自动机

      • 有限自动机是一个状态机,它的状态数量是有限的。该状态机在任何一个状态,基于输入的字符,都能做一个确定的状态转换。

        img
  • 语法分析

    • 概念:在词法分析的基础上,识别表达式的语法结构。这个结构是一个树状结构,这棵树叫做抽象语法树。

    • 抽象语法树(AST):表达式的语法结构可以用树来表示,每个结点是一个语法单元。这个单元的构成规则就叫语法,每个结点可以有下级结点。

    • 上下文无关语法:语言句子无需考虑上下文,就可以考虑正确性,可以使用巴科斯范式(BNF)来表达。

      • 巴科斯范式:一种上下文无关语法,它使用一系列符号和表达式来创建字符串生成规则。

      • 巴科斯范式表示语法规则的方式

        <expr> ::= <expr> + <term>
                 | <expr> - <term>
                 | <term>
        
        <term> ::= <term> * <factor>
                 | <term> / <factor>
                 | <factor>
        
        <factor> ::= ( <expr> )
                   | Num
        
        • 非终结符用尖括号括起。每条规则的左部是一个非终结符,右部是由非终结符和终结符组成的一个符号串,中间一般以 “::=” 分开。
        • 具有相同左部的规则可以共用一个左部,各右部之间以直竖“|”隔开。
    • 递归下降算法:自顶向下构造语法树,不断对Token进行语法展开(下降),展开过程中可能会遇到递归的情况。

  • 类型检查

    • 类型综合:根据子表达式的类型构造出父表达式的类型。eg. A+B的类型是根据A和B的类型定义的。

    • 编译时检查:在表达式的编译阶段即构造语法树阶段检查,需要提前声明参数的类型。

      运行时检查:在执行时检查。

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

  • 词法分析:设计状态机。

  • 语法分析

    • 设计上下文无关语法即巴科斯范式。

    • 运算符优先级的表达

      image.png
    • 语法树结构

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

    • 语法树执行

      • 预先定义好每种操作符的执行逻辑。
      • 对AST进行后序遍历
    • 类型检查:在一个结点的左右子结点执行完成后,分别校验左右子结点的类型是否符合对应操作符的类型检查预设规则。

4 实现规则引擎(见代码)