Javs脚本解析引擎架构设计与实现

一、背景

1.1 技术背景

为了增强CodeMaker代码生成能力,特别构建了基于脚本语言的Javs语法和规则框架体系,但是需要引擎解析Javs脚本文件,所以需要构建一个JavsScript脚本解析引擎服务。对于该服务的定位就是将Javs脚本内容解析为Java原生代码,提供解析规则的实现和关键字识别转换的能力。

1.2 整体背景

为了方便阅读本文,并了解本文讲述的内容如有需要可以先看一下前面两篇关于Javs的文章:

Java业务代码脚本引擎JAVS项目简介

JavsScript核心语法和特性介绍

二、需求

2.1 需求整体内容

  1. 构建Javs整体语法结构和常见关键字
  2. 对常见关键字进行分类解析
  3. 与codeMaker进行打通,将Javs引擎融入到后端代码生成流程中
  4. 搭建整个Javs引擎的内核服务能力

2.2 整体实现步骤

  1. 读取项目元代码,构建包,类,方法,参数模型,Springbean模型,多继承和实现模型(从plantuml 或者api等领域文档)
  2. 配置javs脚本关键字,函数实现模型(可选),可定制化
  3. 编写javs脚本时序图文档,每个核心业务类里面的大概方法逻辑
  4. 启动项目,调用javs对外接口
  5. javs内部构建每个核心业务类的方法内容
  6. 返回方法内容被引用到代码生成器中构建方法内容

三、解析流程

本小节从业务流程视角简单描述下javs与codemaker相关的解析流程。

2.1 整体解析流程

  1. 对接codeMaker的整体流程图
Javs脚本解析引擎架构设计与实现
javsScript引擎&codeMaker整体执行流程 (2).png
  1. Javs解析引擎本身的设计思路流程图

在下面的流程中,我们对领域模型文档和API模型做了建模,这个元数据模型已经比较熟悉了,虽然不是特别成熟但是足以为javs的依赖功能提供助力,另外一方面我们仍然需要构建Javs本身的业务模型,让Javs的模型去依赖领域API模型,进而实现两种模型的打通,为后续的流程提供帮助。Javs脚本解析引擎架构设计与实现

2.2 javs内部翻译流程

这里我们看一下Javs的整体翻译流程,首先需要对每个Javs类文件进行解析拿到代码行内容,然后针对每行内容进行分类解析,最终经过一系列处理返回对应的Java原生代码,由于Javs的类文件中比较核心的内容就是func函数内容,所以我们可以汇总每个func的Java原生代码然后返回到codeMaker的代码生成流程中,这样即可完成代码方法内容的构建。Javs脚本解析引擎架构设计与实现

四、技术方案设计

4.0 方案设计与技术决策

在前面两篇Javs的介绍文章中也透露了一些技术决策,这里需要重点说明一下Javs引擎的开发与Javs语法规则的设计是并行的,而且构建时间也非常短,只完成了常见场景下的语法和关键字设计。所以整体上看就是快,并没有从底层语法树或者AST的角度详细设计,相当于通过不同的设计模式和模块分层来构建整个引擎内容。这么做的一些原因有以下几点:

  1. 一旦Javs项目失败,投入的沉没成本太多,不划算
  2. 对编译和脚本语言本身的设计涉及到AST语法树,对技术能力的要求比较高
  3. Javs本身的定位问题,未来的发展是向上还是向下其实还不明朗,不如先快速构建一版可用的。

4.1 javs引擎整体架构

Javs脚本解析引擎架构设计与实现如上图是整个Javs引擎的核心架构模块内容,这里简单介绍一下不同的层和模块信息:

  1. 模块说明

整个工程从模块的角度来看分为两个模块,一个是client模块,提供模型和接口定义并承担对接外部服务调用的职责。core模块是解析引擎的核心部分。

  1. 接口层

接口层位于client模块,主要提供对外调用接口签名和内部关键字处理函数接口。具体接口模型下面会讲到。

  1. 模型层

模型层包括三部分,一部分是从codeMaker中复制精简过的领域类图元数据模型,另一部分是解析JavsScript脚本进行建模的新模型,两者有依赖关系,另外就是在建模过程中识别的一些值对象枚举模型。模型层相当于领域层,所以这里也仍然是放在client模块中的。

  1. 服务层

服务层负责整个解析流程的实现和对函数层的调用,服务层根据不同的场景提供了丰富的服务能力,并通过一定的设计模式进行层次解耦。另外服务层也提供了一些独立的service类作为公共服务能力帮助解析javs脚本内容。

  1. 函数层

函数层是Javs解析引擎的核心所在,负责对不同的关键字函数和变体关键字提供场景化统一化的解析能力,同时基于面向接口的编程方式结合策略模式为新增的关键字场景提供了扩展能力。函数层根据分析的三类关键字场景分别提供了对应的实现。简单来说函数层完成了将Javs代码转换为java代码的过程,后续由服务层组装整体方法内容,共同实现javs代码解析为Java代码的功能。

4.2 引擎核心业务模型

4.2.1 java元数据业务模型

Javs脚本解析引擎架构设计与实现上图是经过简化的领域类图元模型,主要目的是为了方便快速构建javs引擎的核心模型,将不必要的一些属性全部删除,同时在开发测试过程中避免直接依赖该模型导致的测试开发进度缓慢。

4.2.2 javs引擎核心模型

Javs脚本解析引擎架构设计与实现上图是Javs引擎模型的第一版内容,对于引擎类项目来说使用领域驱动设计的建模方法会有点挑战,也正是本项目吸引人的地方之一。当然建模也不是一次就搞定的,所以上面的模型依然有一些瑕疵,后面会根据实际场景和需要继续优化。

4.2.3 引擎核心服务层接口设计

Javs脚本解析引擎架构设计与实现上图是Javs引擎的接口设计部分,开发实现过程中主要以面向接口编程为主,抽象类为辅助,结合上下文模型进行层次解耦。从上图可以知道对于不同类型下的关键字进行了区分,同时对每个关键字或者变体都有收拢和单独的实现。除了接口声明另外还有一些单独的类来辅助完成一些特定的功能。

4.3 引擎执行流程(时序图)

这里通过赋值场景的解析来看一下调用类图的时序过程:Javs脚本解析引擎架构设计与实现

五、总结

这里对整个设计和实现过程进行一次总结,不管好的坏的都是一次成长。

5.1 测试驱动开发

Javs引擎在构建初期就有意打算使用测试驱动开发(TDD)的模式进行核心代码的编写,因此在测试代码文件目录中构建了一些不同场景的javsScript文件和领域类图PlantUML文档辅助测试代码。这么做的一个好处就是实现过程中对不同场景的测试覆盖率会比平时的开发模式高一点,后期的模块之间的集成测试问题会少一些。当然,因为时间关系等并没有严格执行下去,只对主流程和一些重点的解析场景采用了这种开发模式。

5.2 设计模式应用

这里需要重点强调一些设计模式在本项目中的使用,相当于在模块设计中的一些小的技术决策:

5.2.1 适配器模式

这个模式在codeMaker与Javs对接的接口中有一些体现,主要是模型的适配,在解析流程中需要将codeMaker中的领域类图元模型转换到经过精简的元模型,同时解析完成后还需要进行方法匹配以填充方法内容,完善codeMaker中的领域类图元模型数据。

5.2.2 策略模式

这里的策略模式也沿用了codeMaker的一些好的实践,一种是常规的策略,就是有几个实现类就直接进行引用来达到策略路由效果,另外一种就是设计一个策略场景注解,对实现进行打标。用一个策略容器类实现ApplicationContextAware接口来统一管理所有策略场景,这样的实现的好处就是比较灵活,扩展性更高,对扩展开放,对修改关闭,同时也能帮助更好的进行服务分层解耦。

5.2.3 管道模式

在进行解析模块的设计实现中考察了管道模式,命令模式和责任链模式,发现对脚本解析的过程类似于Shell的管道模式,另外命令模式则没有明确的触发点所以感觉不太合适,责任链的话在进行多个解析场景的串联中显得也不是很好。所以这里重点应用了这个不常见的设计模式。在这次应用中根据场景一层一层的解析替换不同的关键字从而达到正确的解析效果,另外这里的管道设计也比较简单,就两个管道进行了结合。

5.2.4 过滤器模式

从本质上来说过滤器,管道,和责任链都差不多,但是这里对过滤器模式则进行了一次简单的应用,过滤器对一些简单细微的场景进行特定过滤之后则不再进入解析流程中达到了过滤的目的。管道模式则则是在整个粗粒度上进行了解析场景的对接。


原文始发于微信公众号(神帅的架构实战):Javs脚本解析引擎架构设计与实现

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/241455.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!