从开发者角度看微软领域特定语言 (DSL) 工具

  • Hartmut Wilms
  • 霍泰稳

2007 年 3 月 31 日

话题:.NETC#语言 & 开发架构

领域特定语言(DSLs)是架构方面的一个热点。微软开始在自己的软件产品线里支持 DSL,并通过最近发布的Visual Studio 2005 SDK集成到它的软件开发流程中。尽管现在已经有许多关于 DSL 的信息,但它仍然是一个抽象的架构概念。现在看看 Mike James 博士是如何从一个开发者的角度去理解Visual Studio DSL 工具的。

DSL 是指软件开发中出于某特定考虑而设计的小的、目标明确的语言。它们的作用是,使用某特定领域里惯用的符号或者表示法对该领域的实体或者流程进行建模。这就是它们区别于那些提供统一符号表示的通用建模语言(如 UML)的地方。另外一个区别是 UML 经常被用作于(定义如此,非只能用于)文档分析或者设计交付,而领域特定语言既可以用作建模工具,还可以用作代码生成器。

在他的文章中,James 抱怨说:

……文章、案例、白皮书,甚至视频介绍都是那么糟糕。他们浪费了太多的时间做无用功,而恰恰严重忽视了最明显的问题——使用领域特定语言工具的新手可能会遇到什么问题?大多数案例过于复杂,看上去就像魔术,比如告诉你“现在把下面的 XML 粘贴到一个新的文件中”,而不解释为什么,以及 XML 文件是从那儿来的,或者它有什么用等,其实这些远不是新手们所关心的问题。本文不是洋洋洒洒数千言给你解释如何改变一个图表的颜色,而是主要讲述那些文档中缺失的部分,如怎样使用领域特定语言工具从一个定制的图表中实际产生一些代码。一旦你明白了如何去做,那么那些文档看上去才会有点意思。

James 解释说微软的 DSL 工具提供了一种图形化的操作方式。在开始创建一个领域特定语言(DSL)时,是围绕 DSL 设计器进行的,设计器的功能是设计和产生 DSL 或者设计依附于可生成代码 DSL 的模型。开始的时候,设计器的设计器(Designer-Designer)概念听起来有些迷糊,但是当你理解了这一思想后,就很明白了。完整的 DSL 设计包含两个阶段:

  1. 为你的 DSL 文法设计相应的图形表示。简单地说,你必须为你的语言设计图形、连接器和底层的元模型(包括文字性属性);
  2. 写代码模板,即使用存储在 DSL 中的实例(图表)信息产生对应的代码。

文章中,James 提供了一个基于微语言(MinimalLanguage)模板(装有 SDK)的 DSL Hello-World 例子。他一点儿也没有提到如何增加图表或者模型部分如何连接到图形上等细节。相反,他花了很多时间解释代码生成的过程。

代码生成是基于 TextTemplate(.tt) 文件的。这些模板包括直接生成(复制)为访问模型或者用于动态生成的目标或者元代码(meta-code)的代码。James 说最小代码和元代码是非常让人困惑的。另外, DSL 模型部分所基于的(没有文档的)元类结构(Meta-Class-Structure)概念,对理解这些问题也没有实质性的帮助。

实际上没有类结构的文档说明,只有一些没有用的特定案例。针对文档问题我发现的唯一的解决方法是在 DSL 设计器里阅读源文件。比如,在最初的项目中如果你打开 DomainClasses.cs 文件,就会发现那些组成模型的类的定义。
Mike James 博士总结说:

现在的 DSL 工具难以使用,最初的学习曲线也非常陡峭,学习的投入和产出不成正比,很不划算。尽管充满了新的专业术语和时不时让你百思不得其解哪儿出了问题,坦白地说,图形设计器很容易上手。但是,代码生成原理遇到了一直受元代码困扰的代码生成器或者软件工厂问题的障碍。这个问题就是,在表示(as-is)代码和实际执行的代码产生更多代码后,会有一堆恐怖的混合代码。这个组合天生就是那么难以理解,也很难控制。我们真的需要一些更大胆的新想法。
如果要使用微软的 DSL 工具,需要下载安装Visual Studio 2005 SDK v4.0,而且机子上要安装有 Visual Studio 2005 专业版或者 Visual Studio 2005 团队版的某一版本。尽管没有明确说明,在安装 VS 2005 时还是要确认选择 Visual C++ 环境,因为当前发布的工具是使用 VC++ 项目生成的附属 DLL,它存储了 DSL 的源代码。注:感谢 ThoughtWorks 咨询师徐昊对本文翻译的技术审校。
.NETC#语言 & 开发架构