DSL/API/GUI之辩

文章探讨了DSL、API和GUI在查询和表达复杂逻辑时的优缺点,以ElasticSearch查询为例。DSL提供类SQL的简洁语法,而API更直接但可能复杂。GUI适合简单查询,但在表达复杂逻辑时可能变得臃肿。设计过程中,建议先定义DSL文法,构建语义模型,然后转换为API或GUI。ANTLR常用于Java中的语法解析,但ANTLR4不再自动构建外部访问者,需要手动处理CST到AST的转换。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

DSL/API/GUI之辩

以ElasticSearch的查询为例,API的例子是ES提供的原生json查询接口,写起来比较复杂:

{
"size":0,
"query": {
  "filtered":{
    "query": {"match": { "content": "ERROR"}},
    "filter":{
      "range" : {
        "time" : { "gte" : 0, "lte" : 1515470055256}
      }
    }    
  }    
},
 "aggs": {
    "_group_count0": {
      "terms": {
        "field": "group"
      },
      "aggs":{
        "_group_count1":{
          "terms":{
            "field": "host",
            "order":{"_count": "desc"}
          }
        }
      }
    }
  }
}

若用DSL表达,是这样:
STAT COUNT(*) AS errnum WHERE MATCH(content, “ERROR”) AND time>=time1 AND time<=time2 BY group,host SORT errnum;
这是类SQL的语法,相比API要简单易懂很多。

GUI的例子就是类似日志普通查询的GUI:搜索框+展示栏。
在表述复杂逻辑方面,DSL比GUI做的更好,比如下面的水平统计,用GUI做界面会比较臃肿:
STAT group,COUNT(content) AS total,
COUNT(EVAL(MATCH(content, “ERROR”))) AS errnum,
COUNT(EVAL(MATCH(content, “WARN”))) AS warnnum BY group SORT -total

设计心得

我们要做DSL到json API之间的翻译,首先要构建一个描述json API的中间模型IM,将DSL翻译为IM,再从IM翻译为json。这个IM就是Martin Fowler提到的“语义模型”。
实际中,IM往往是AST(抽象语法树)。
综上,DSL到目标的翻译过程是:
DSL -> 语义模型 -> 目标结构

实践中,我们在做DSL的设计时,步骤建议是这样:

  1. 写DSL文法
  2. 根据DSL文法设计并组装语义模型
  3. 做语义模型到目标结构的翻译。
    有时,我们会发现,以API或GUI方式提供语义模型给用户使用也是可以的,不是必须要暴露DSL(DSL可作为一个增强功能的卖点)。本质上,DSL/API/GUI都是语义模型的外在呈现。

java做语法解析一般用antlr,antlr里AST的遍历方法:

  1. 内嵌遍历器 好处:屏蔽节点实现细节; 坏处:不够灵活,翻译代码分散在各个节点类中,牵一发动全身,不方便维护
  2. 外部访问者 好处:灵活,翻译代码在一个类里;坏处:要暴露节点实现细节,按节点类型分发需要一些技巧才能避免丑陋的“硬分派”。
  3. ANTLR3的树文法能自动为我们构建外部访问者,这样避免了手写重复代码。不过ANTLR4已没有这个功能了,我们只能自行从CST(具体语法树)转AST。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值