DSL-Domain Specific Language

领域特定语言(DSL-Domain Specific Language)的基本思想:针对特定类型问题的计算机语言,而不是针对软件问题的通用语言。

DSL在如今的互联网时代非常普遍:包括CSS,正则表达式,make,rake,ant,SQL,HQL,many bits of Rails,JMock中的expectations,dot语言工具包Graphviz,FIT,struts配置文件等。

什么是DSL(特定领域语言)

可能已经接触DSL很过年,但并没有注意它。如果曾编写过makefile或使用CSS设计过网页,那么就已经见识过DSL了。DSL是为特定任务定制设计的小型的,富有表现力的编程语言。

与Java之类的通用语言不同,DSL功能的表达范围相当有限。DSL专注于某种类型的问题或某个领域,并在有限范围内表达一组狭隘的解决方案。这是DSL的优点 -简洁明了。

好的DSL就像一道由大师烹饪出来的美食,既让人吃的爽又搭配了均衡的营养。DSL设计应始终考虑不要让使用者担心它的语法问题。例如:

matrixA.multiply(matrixB);

matrixA * matrixB

这两种表达方式孰优孰劣高下立判。

DSL通常分为内部DSL(Internal DSLs)和外部DSL(external DSLs),这是一个重要的区别。

外部DSL设计独立于任何特定语言,作为外部DSL的作者,可以使用任何语言和工具来实现DSL。

内部DSL是使用宿主语言。在主流语言(如Java和C#)中也可以执行内部DSL。内部DSLs也被称为嵌入式DSLs或FluentInterfaces。内部DSL采用宿主语言的语法,因此不必花费时间或精力来写编译或解析。

外部DSL(external DSLs)

外部DSLs有自己的自定义语法,可以编写一个完整的解析器来处理它们。在Unix社区中有一个非常强大的传统。许多XML配置最终都成为外部DSLs,尽管XML的语法非常不适合这一目的。

外部DSL通常定义为使用单独语言编写,例如:Unix小语言和XML配置文件就是这种风格的例子。

外部DSL的关键优势在于可以自由选择喜欢的任何形式。因此,可以以最简单的形式表达域,以便进行读取和修改。格式仅受限于构建翻译器的能力,翻译器可以解析配置文件并生成可执行文件 - 通常采用擅长的语言。

因此,一个明显的缺点是 - 必须构建一个翻译器。对于一种简单的语言,这并不困难。虽然复杂(高级)的语言会增加难度 - 但并不总是那么糟糕。已有现成的分析器生成器和编译器编译工具,能够帮助操作相当复杂的语言,当然,DSL的全部意义在于简单。XML限制了DSL的形式,但是很容易解析。

与此问题相关的是对设计DSL困难的担忧 - 语言设计很难,因此,设计多个DSL对于大多数项目来说太难了。这种反对意见通常源于习惯了通用语言而不是DSL。API设计和DSL设计之间的区别相当小 - 所以设计DSL并不比设计好的API困难多少。

对于许多人来说,外部DSL的一大优势是可以在运行时评估DSL。这允许在不重新编译程序的情况下修改常用的参数。这是XML配置文件在Java世界中如此受欢迎的主要原因。虽然这只是静态编译语言的一个问题,现在对混合编译时和运行时语言也越来越感兴趣,例如.NET中的IronPython。这将允许在大多数C#系统的上下文中评估IronPython内部DSL。这是Unix世界中将C / C ++与脚本语言混合的常用技术。

内部DSL

内部DSL颠覆了外部DSL的优点和缺点。内部DSL更接近编程语言。使用内部DSL可以降低工具成本 - 但是由此产生的对DSL本身的限制也会大大降低其优势,特别在仅限于使用基于C语言的情况下。外部DSL实现优势具有更大的潜力,但设计语言,构建翻译器以及能够支持编程的工具成本也相对更高。

DSL可以通过解释或代码生成来实现。解释(读取DSL脚本并在运行时执行)通常是最简单的,但代码生成有时是必不可少的。通常,生成的代码就是它自身的语言,例如Java或C。