一直以来,对于 DSL 这个词大家应该是既熟悉而又陌生,熟悉的是它写起来像啥样,陌生的是他的本质到底是什么,而今天作为第一篇在博客发布的文章就想来探讨一下这个问题。

DSL 的本质与解释

首先,我们来看看 Wiki 是怎么解释 DSL 的:

A domain-specific language (DSL) is a computer language specialized to a particular application domain. This is in contrast to a general-purpose language (GPL), which is broadly applicable across domains (原文出处:Wiki: Domain-Specific Language

而把上面择要翻译过来就是:DSL (领域特定语言) 是专注于某个应用程序领域的计算机语言,而对比起 GPL (通用程序设计语言,例如 Java / C / Python…),DSL 能够在特定的应用领域中具有更大的拓展性及其延伸性。看到这里可能还有部分人不明白这到底是怎么一回事,其实简单来说 DSL 就是为解决特定领域的事情而生的,如果曾经作为 Java 程序员,你可能会经常使用 Maven 跟 Gradle 这两款包管理器去管理你的依赖/库,而透过对比两者语法上更是大相径庭,例如 Maven 采用的是 XML 语法的标记语言,因此我们先来看一下在 Maven 引用依赖部分是怎么写的:

1
2
3
4
5
<dependency>
<groupId>group</groupId>
<artifactId>project</artifactId>
<version>1.0.0</version>
</dependency>

而 Gradle 则是像这样:

1
2
3
dependencies {
compile group: "group", name: "project", version: 1.0.0
}

从上述看到的两种包管理框架语法差别都很大,而 Gradle 对比起 Maven 而言则要更为简洁,而这是为什么呢?最主要的其实就是这两者各自采用了不同种类的语法,Maven 采用的是基于 GPL 的标记语言: GPML (General-purpose markup languages),而 GPML 还包含了 XML YAML GML 等等。除此以外,我们想要在 Maven 里插入有关构建时执行的代码段(或是Task)是非常困难的,其 XML 语法的甚至都大大束缚了代码编写,例如 if switch 这一类流程控制的语法在 XML 上实现就显得非常困难或根本无法实现。由此可见,其实 Maven 虽然用了 XML,但其本身是基于 GPML 的,对于解决特定范畴的问题就显得特别的繁琐了。

而 Gradle 呢?除了继承自 Groovy 的语法外,其本身还具有一个特性:为解决 Java,Kotlin,Scala 等包问题管理而推出的一种独立框架,也就三基于 DSL 设计思想出来的产物,而相较于 Maven,Gradle 其本身就是为了解决特定领域的问题而生的,其本身语法上导入包更简洁,而且可以比 Maven 更方便解决插入构建期的代码段,解决了 Maven 一直以来难以实现的地方。

DSL 的设计目标

DSL 的设计理应十分谨慎,在软件工程上,DSL 总是负责解决领域相关问题及应用于特定领域。一个良好的 DSL 语法设计可以有助于在特定领域更方便地使用,以至于提升开发效率。

以下给出在 Wiki 给出的三个设计重点的定义,而且均是有别于 GPL 的:

domain-specific languages are less comprehensive.
domain-specific languages are much more expressive in their domain.
domain-specific languages should exhibit minimal redundancy.

  • DSL 相较于 GPL 而言范用性要低,因为需要专注于单个特定领域
  • DSL 理应在特定领域上比基于 GPL 发挥的作用更大更广
  • DSL 应该要尽可能地将(语法设计)冗余部分最小化,更为简单

总结

总括而言,虽然 GPL 出来的产物可以广泛地应用在不同领域上,例如序列化,上述的 Maven 包管理等,有些时候这类语言在解决某些领域上的特定问题就很困难。而 DSL 则可以解决某些特定领域的问题,而且提出该领域应用更优的解决方案,就如同上述的 Gradle,SQL 等。

延伸阅读