聂同学

一个程序员和架构师的实践与思考

一场似非而是的DSL(三)

上回说到,可读和全局,是我们的DSL形式要解决的主要问题。

  • 全局,要求DSL结构要精练,同时最好是层级结构,避免指针引用。
  • 可读,要求DSL能以一种形式表达各个不同的业务方面,所以这个形式必须相当通用。

此时那个最纠结的问题出现了:“相当通用”的DSL是不是D S L?毕竟,“通用”在一端,S在另一端。

幸运的是:我们决定先找到这个DSL再讨论它是不是真正的DSL。

既然需要相当通用,我们决定从通用的配置形式出发,我们的办法是——

  1. 清理要描述的对象,明确其结构和关系,形成确定的业务模型。在这里就是“特征机制“涉及到的知识层的各个概念,比如特征、扩展点、扩展等。这个工作其实在“特征机制”设计期就已经完成了。
  2. 保证知识层业务模型的可读性,在我们Java系统中,就表现为相关的类(特征、扩展点、扩展等,包括抽象的类和具体的类),它们的类名和属性名、关系名都准确精练、可读。
  3. 然后我们使用一种通用的配置形式将这些类实例化(一些javabean),并关联在一起。这时候发现,我们的DSL,基本上等同于描述Bean图的DSL。

    这种配置方式是很常见的,有很多实现方法:

    • Spring Bean XML:这个形式简单直白,通用性非常强,但过于冗长了些,很难满足全局性要求。噪音很多,很难说可读。
    • 定制namespace的Spring Bean XML和其他简单的XML:粗略一看是个好主意,比上面的办法在体积和噪音两个方面都改善挺多。但仔细看看不对,要保证通用性,这种方法只能退化为前一种。
    • Json:形式上比较简洁,噪音比较少,基本已经满足要求。只是需要在配置中补充一些类型信息,而且处理这些信息需要自己实现,比较繁琐。
    • YAML:跟Json相似,类型信息方面实现上简洁些。
    • Groovy ObjectGraphBuilder:当我们已经开始深入研究YAML的实现细节的时候,回忆到世界上还有这个,各方面都符合要求。

至此,我们基本上找到了符合要求的DSL形式,期间也花了很多时间来思考那个纠结的问题:“相当通用”的DSL是不是DSL?现在,我们的回答是:这个DSL就是我们想要的DSL。我们认为——

  • 作为一门语言,其通用或者专用,主要是从使用者的视角来衡量,而不是从设计者、实现者的视角。虽然我们用通用的形式设计、用通用的方法实现这个dsl,但使用者撰写、维护时能接触到的,都是专有业务领域的概念,很少有领域之外的噪音。
  • 任何定义,都是为作用服务的。我们选择DSL,是由于它的作用,而不是它的定义。如果一个东西被用作DSL,则它就是DSL。

一场似非而是的DSL的故事就是这样,如果有同学对我们这个DSL具体是怎样的有兴趣,可以要求我写故事后传……

dsl, 架构, 设计

分享 -