Markus Völter 是" Model-Driven Software Development "一书的合著者之一,最近他出版了一本模型驱动软件开发( model-driven software development ,简称 MDSD )领域的新书。 “ DSL Engineering ”一书专注于领域特定语言的设计与实现(DSLs)。
DSLs 是指那些具有优选的词汇表,并在某一特定领域用于有效描述问题和解决方案的语言。相比之下,像 Java 这样的通用目的语言(general pupose languages ,简称 GPL)可以用于描述相同的问题和解决方案,但是它们最大的特点是需要更加冗长的程序,并且更难以使用工具进行分析,也更难以被领域专家所理解。
因此,设计良好的 DSLs 非常适合非编程人员用以在形式上定义业务相关模型。通常,这些模型稍后可以转变为例如 GPL 源代码或文档这样的工件。
InfoQ 有机会联系到了该书的主要作者 Markus Völter 和联合作者之一的 Christrian Dietrich。
InfoQ:能分别聊聊你们在DSLs**** 领域的相关经验吗?
Markus Völter: 我在模型和代码生成相关的领域已经工作了差不多 10 年。我是从使用基于 UML 的语言和生成器开始的,但是很快转移到了 DSL 阵营。特别是在使用现代的语言工作台时,DSL 的方式比 UML 更加强大也更具生产力。总之,我自己花了十年的时间来构建语言、分析器和代码生成器,同时也帮助我的客户做着相同的事情。这些项目包括对 AUTOSAR 标准的概念验证、用于架构定义的各种 DSLs、用于配置助听器和冰箱的 DSLs 以及在保险业务和需求工程中的 DSLs 等。在工具方面,我主要使用老当益壮的 openArchitectureWare 框架、Eclipse EMF/GMF/Xtext 以及最近的 JetBrains MPS。在最近的两年里,我花了很多的时间用于开发 mbeddr 系统,这是一个用于基于 JetBrains MPS 之上的嵌入式软件开发环境,该环境也是基于 DSLs 的。
Christian Dietrich: 我在建模项目方面已经工作了六年以上。我首次接触 MDSD 是在一个使用 UML 和专有代码生成器的项目中。从那以后我使用 openArchitectureWare 以及基于 UML 和基于 EMF 的模型做了很多事。在 2008 年,我发现了 oAW Xtext,当时我简直太激动了:相比于曾经使用 lex 和 yacc 或者是 antlr, 使用合理的工具来创建文本语言变得如此简单。我开始深入这个框架,自该项目迁移到 Eclipse 起,我在工作中使用它做了很多的事情。同时,我在业余时间成为了 Eclipse Xtext 论坛的支持者。我也使用 MDSD 和 DSLs 领域的其他一些技术做过一些工作,比如 MPS,但主要还是专注于 Xtext。
InfoQ:你们的书覆盖了设计、实现和应用领域特定语言的整个周期。使用DSLs**** 和模型驱动软件开发(MDSD)的最有效点(sweet spot)是什么?
Markus: 我不认为存在一个所谓最有效的点,这也是为什么本书在它的四个部分中描述了六个不同领域的适应性。这些领域包括需求工程、软件架构、非常特定的应用逻辑、软件实现、将 DSLs 作为开发者工具以及在软件产品线的环境中使用它们。我在以上的每个领域中都见到过 DSLs 很棒的使用案例。这里有一些指导方针来帮助你从大致上判断在以上任意一个领域中使用某种 DSL 是否会成功(当然,除此之外,必须具有足够胜任的开发者):你是否真正理解你将要创建 DSL 的所在领域,或者至少有某些方式来逐渐形成这种理解。同样,该领域需要足够多的特定抽象或标记来保证构建和使用 DSL 取代某种代码库或框架的 GPL。另一个使用 DSL 的绝佳原因是你需要对程序做进一步的分析,而该分析需要静态的(比如编译时)领域层面的语义。再一个原因是你想让非程序员在该领域开发应用(请注意我在这里没有使用“程序”一词),这需要去除掉所有的 GPL,因为它会通过代码引入噪声。最后,你越频繁地使用 DSL 来构建系统,创建 DSL 的成本将越低(这就是语言工作台的来由),也更容易对 DSL 创建进行验证。
InfoQ:另一方面,你是否能给我们一些提示,在什么时候不要使用这些技术?
Markus: 好的,如果当我先前所描述的标准都不符合的时候,将不适合使用这些技术 :-) 更严肃的是,有一种说法认为任何有用的 DSL 将不可避免地最终以 GPL 的形态结束。我的经验告诉我这是不对的,但是,肯定的是如果你在没有真正理解 DSL 的情况下开始开发 DSL 将会是一种风险。直到你真正理解了该领域,那么你的 DSL 将会优美、声明式的并且简单。但是在这个时刻,你可能会尝试将 GPLs 中的循环、条件判断和所有其他东西添加到 DSL 中。这确实是个风险。模块化的语言和语言扩展可以对这个风险进行稍许的弥补:使用别的方式来取代开发一种完整的独立 DSL,你可以考虑通过使用领域特定的概念对一种例如 Java 或 C 这样的基础语言进行增量扩展。用户通常都可以回到 Java 或 C 的层面,所以你将不需要为领域中的每个角落提供 DSL 概念。一些当前的语言工作台(特别是 MPS)真的非常擅长此类的语言模块化。我在前面所提到的 mbeddr 项目通过对这种思想的探索,使用嵌入式软件开发的领域特定概念对 C 进行了增量扩展。
InfoQ:这听起来真是两全其美—非常强大。但是这样一来应用开发将会再次成为软件开发者的职责吗?
Markus: 是的,你说的没错。这些工作针对的是那些了解基础语言的程序员所使用的 DSLs。这很好地突出了两种不同风格的 DSLs 之间的区别:应用领域 DSLs 原本就是为领域专家准备的;它们只包含了领域概念,理想情况下将不包含别的任何内容。它们通常是被自顶而下(top-down)开发的,也就是说你是从现实世界领域中的概念开始的。与此相对的,如果你愿意,可以使用技术 DSLs。他们是为开发者准备的。它们通常通过向 GPL“添加”领域特定的抽象进行构建,它们“应该”包含所有该 GPL 的东西,并且不限制特定的用户使用,但是仍然通过提供较高层面的概念简化了开发。它们通常是通过自底而上(bottom up)的方式开发的,就是说你是从该 GPL 和现存的方言或模式开始的。
InfoQ: Christian**,你目前正在德国最大的MDSD项目中工作。如果要成功地设计和使用领域特定语言,应该按什么样的步骤进行?**
Christian: 第一步就是理解领域及其概念。如果没有这些知识,你将无法发现正确的抽象。然后,当你为语言定义抽象和具体语法的时候,应该一直着眼于概念的易懂性和清晰的语义。这通常将反复地帮助你进行工作。如果你使用 DSLs 来生成代码或文档,或者使用解释器来进行一些模拟,那么请使用 DSLs 中的概念来将这些工件开发在一起。这将帮助你检验抽象语法的质量。如果你将 DSL 和生成器开发成框架:那么就吃你自己的狗粮吧(译者注:eat your own dog food,俚语,特指公司使用自己生产的产品)。这样一来你就能看到你的 DSL 究竟是达到了预期的目标还是毫无用处。还有一种观点是在早期就考虑模型的大小和规模从而设计出使用实际模型执行的 DSL。使用五行代码的测试文件是不可能发现关于对性能的误解的。
InfoQ:回顾你这些年所参与的项目,使用DSLs**** 最常见的陷阱是什么?
Christian: 我认为一个比较常见的陷阱是随着时间的流逝,DSLs 要么对于每个特定情况的概念定义过于工程化,导致零抽象,要么变得过于通用成为"GPLish"。用户最终将堕入复杂性的地域。为了削弱这种效果,随着时间的变化我们需要对 DSL 进行进化。因此你不要畏惧对语言进行重构,特别是你可以通过工具支持来完成这项工作。相比于 Xtext,在 MPS 中更早的进行了重构。另一个常见的陷阱是过于将精力集中在具体的语法上,而忽视了抽象语法和语义。根据我前面提到的,在一个与领域没有接触且没有应用的象牙塔里开发 DSLs 这一思想是错误的。你必须经常去证明你的 DSLs 是符合领域需求的。
InfoQ: Markus**,看来使用DSLs和模型驱动方法不可能在一开始就有所回报。你能不能就什么样的项目规模及配置可以受益于MDSD谈谈你的观点?**
Markus: 我无法同意你刚才所说的。我可以在两个小时内构建一个小型的 DSL,当然它在第一天就给我带来了回报。理所当然,一个更大型的 DSL 需要更长的时间去开发,因此它也需要更长的时间来获取回报。这都跟比率有关,所以事实上真的没有特定的规模和配置。我曾看到过由小型团队开发的简易 DSL。我同样也看到过花费了大量精力的 DSL,估计得跨越产品平台几年甚至是几十年之久的生命周期才能获得回报。尤其是在一开始,较好的想法是从一个简单问题开始,随着投入更多的精力,和平常的项目一样,失败的风险终将会由于那些与大小及规模相关联的众所周知的原因而逐渐变大。再次强调,我喜欢那种对一种基础语言进行增量扩展的方式:它允许你根据需求的增长从而添加更多的领域特定抽象(“三振出局,你将自动化”)。
InfoQ:在这本书中,提到了三种DSL**** 框架—Xtext, Jetbrains MPS 和 Spoofax。你能详细描述下这些框架之间的区别吗?它们之间可以互相替换吗?它们是否有其独有的场景和用例?
Markus: 它们三个差别很大,这也是我们在书中选用这三个框架的主要原因。Xtext 目前主要用于构建文本的、外部的 DSLs。它很成熟、有着很好的支持并且也支持 Eclipse EMF,它是现今大部分建模成果的支柱。Spoofax 也是基于 Eclipse 的,但是它并不依赖于 EMF。它是荷兰代尔夫特工业大学(TU Delft)开发的一个系统,在它所支持的特性方面更具创新性,比如它具有一种用于名字绑定和作用域选取(scoping)的声明性语言,在语言模块化方面很大程度上超越了 Xtext。但是从另一角度来看,它还不是非常普遍。JetBrains MPS 则与前两项更加不同。它并不使用普通的文本编辑和文本解析,取而代之的是一种投影方式,通过这种方式每一次的编辑操作会直接修改抽象语法树(AST),你所看到或与之交互的仅仅是投影。这将允许用户使用更加宽泛的标记,包括表格、分数条以及今年晚些时候的各种图形。这同样使得很容易对语言进行扩展,并且可以在单个程序中各自关联成熟的扩展。MPS 并不像 Xtext 那样被广泛使用,但是使用人数正在不断增长。拥有了这三个工具,你便可以构建实用的(bread-and-butter)DSLs 了,这些工具可以替换着使用。但是不管则样,它们的偏重点是不同的。举个例子,配合 Xbase 的 Xtext 与 Xtext 的交互操作非常适合于 Java 生态圈。可以非常容易地构建 DSLs 来复用 Java 的类型和表达式,并生成 Java 代码。Spoofax 由一个研究性的小组开发,所以同时也是个研究成果的承载工具,展示了一些它最近的特性。如果你要构建整个语言的生态系统,并且它还具有语言之间的引用、扩展和内嵌等,又或者在需要“奇怪的”领域标记的时候,那么 MPS 很明显拥有其有效点。很难简略地回答这个问题。我想你应该读读这本书的第三部分,然后就会形成你自己的观点了:-)
这本书的纸版和PDF 都已经可以获取。后者可以通过自愿捐赠的方式下载到。该书目前还没有特定的电子阅读器格式。
关于图书作者
Markus Völter 已经在模型驱动软件开发和领域特定语言领域工作了 10 年之久。他同时也是在该主题方面活跃于各种会议的演讲者。
Christian Dietrich 是德国 Itemis AG 公司的咨询师。Itemis 不仅仅提供 Eclipse 项目 Xtext 和 Xtend 在定义 DSLs 和通过模型生成工件方面的咨询服务,同时也是这些项目活跃的开发组织。
评论