BT

如何利用碎片时间提升技术认知与能力? 点击获取答案

如何判断真伪Ruby DSL?

| 作者 Werner Schuster 关注 9 他的粉丝 ,译者 Jason lai 关注 0 他的粉丝 发布于 2007年6月22日. 估计阅读时间: 8 分钟 | QCon上海2018 关注大数据平台技术选型、搭建、系统迁移和优化的经验。

在Ruby社区中,“领域特定语言(Domain Specific Language,DSL)”已经成为一个非常流行的时髦词汇。Make的替代工具Rake就是其中一个人气很旺的例子,尤其在Martin Fowler撰文介绍它之后,它更是声名鹊起。DSL这个词同样也用于描述Ruby on Rails中ActiveRecord组件的某些概念。

实际上,DSL这个概念和Ruby没有什么关系,早在Ruby之前它就已经问世了很长的一段时间了。通常,我们用它来描述拥有特定的语言构造(Construct)、适用于表述某个特定领域的概念的一门语言。举例而言,Make这个构建工具就包含了自己的一门语言,允许以声明的方式定义构建目标(Build Targets)和这些目标的构建方式,以及目标之间的依赖关系。此外的一个概念就是内部DSL,内部DSL使用的是一门已有语言的语法,这个已有语言称为宿主语言(Host Language),比如Ruby。我们使用宿主语言的各种方式来构建语言构造,使其看起来像一门截然不同的语言。上面提到的Rake就使用了这种方式,使得下面的代码成为可能:

task :codeGen do
#do the code generation
end

正如你所能看到的,宿主语言应当非常灵活,才能允许DSL看起来截然不同。

然而,近来DSL这个字眼似乎有被滥用的趋势,导致它所代表的意思越来越含糊不清。似乎在一段代码中把方法调用的括号省掉以后,我们就可以大大方方地给这段代码贴上DSL的标签。是这样吗?O'Reilly的博客作者chromatic贴出一个半开玩笑的列表,作为判断一段代码是否为DSL的依据——或者说,至少在我们给这段代码贴上DSL标签的时候,我们可以根据这些标准看看。其中的几条是像这样的:

  1. 除了Ruby以外,你还用过哪门语言写过代码没(PHP和HTML不算数)?如果没有的话,那这是一门DSL。
  2. 你所聪明地去掉括号的定义型语法特性是否一系列函数参数?如果是这样的话,那这是一门DSL。
  3. 代码是否主要就包含一系列的键-值对?欢迎来到DSL的国度,你就是其中的一员!

chromatic列表中的第5项特别说到:

  1. 你是否曾经认真使用过“……这代码读起来就像英语!”这样的话?你最好去一趟医院,因为你已经患DSL流感了!

关于创建DSL,存在着一个非常流行的支持论调:DSL使我们得以编写出易于阅读及理解的代码,并且不会将代码的意思隐藏在如for循环、条件语句之类的语言构造之后。然而,David A. Black对此提出了一个不同的观点

下面这个:
with Employee "123-45-6789" do
dock_salary 1000
warn_about :misconduct
end
并不是一门领域特定语言,它是领域特定语言。注意在这里我少用了“一门”这个词。它是领域特定的没错,而且也使用了类似语言的构造,但它并不是一门语言。它只是Ruby的代码,使用直表其意的方法名称和易懂的语义,从而有助于领域特定用语(Idioms)的使用。

使用一个针对领域的词汇表来命名代码元素并不是件新鲜事,相反,对于设计人来说它应当是一个显而易见的选择。

那么,DSL这个字眼是有害或者有误导作用的么?未必。Smalltalk开发人员Blaine Buxton对此发表观点说

我一直就不理解:到底DSL出了什么大问题?当然,我并不是反过来说DSL不好。但我相信DSL是一个良好的面向对象设计的绿色副产品。所以,我曾经觉得所有在这方面的讨论和技巧挺烦人的。我心里一直这么跟自己说:“如果你的设计非常好,那么它[DSL]就自然而然产生了。”

但是我该好好敲敲自己的脑壳了。良好的设计又重新成为流行趋势,对此我应当感到高兴才对。你知道吗?我确实感到高兴。现在,我不再对那些讨论感到厌烦了。相反,我开始慢慢品味这些讨论的结果了。我甚至为之前保佑负罪感。你看,DSL一直都是Smalltalk的一部分。对于我们[Smalltalk程序员]来说,它再自然不过了,因为这就是我们学会写[Smalltalk]代码的方式。我记得我已经把“代码读起来应当像交谈(Code should read like a conversation)”这句至理名言吞进肚里,变成我思维的一部分了。而现在社区里面新一代的人们已经发现这个事实,并且在使用它,这真是太酷了。

含有可被扭转/改变的语法,从而可以写出更加简练的代码的语言是很有用的,但良好的设计仍然取决于开发人员本身。

这一点存在另外一面。有一些DSL使用Ruby的构造及Ruby语法中比较罕见的一些情况。尽管这可以让开发人员实现出某种特定形式的代码,但是并不意味着这是一种良好的设计。毕竟,虽然代码只要写一次,但需要经过多次阅读和修改,这个事实毫无疑问到现在都还没有人能否认。

最近在Urban Honking上的一篇文章引发了对这个话题的一次辩论。文章揭示了为什么HTML解析库Hpricot使得下面一段代码成为可能:

Hpricot(my_document)

从根本上说,这里使用了一个叫做Hpricot函数创建了Hpricot的一个新对象,并对my_document进行解析。然而,Smalltalk领域的博客作者James Robertson表示反对

Urban Honking费了九牛二虎之力,解释了为什么使用Ruby的一些语法技巧得出类似Hpricot(my_document)这样的东西会是一件好事的原因。在这里我提个问题:如果你偶然在代码中碰到这样的技巧性写法,你会明白这代码是干嘛的吗?

在解释如何提高代码质量之后,他接着说:

我已经用Smalltalk用得聪明过头好多次了;这绝不是一个好主意。

Stuart Halloway也站出来声援这个观点

如果你打算改变一门语言的惯用法,那么你得先有一个很有说服力的理由。我同意James的观点,这个例子不够令人信服。

接着,他又针对API设计的多种不同解决方案给出了一个颇有意思的纵览,并且阐述了如何设计出一套可以用来编写出表义清晰代码的API。

亲爱的读者,您又是持什么样的看法呢?对于使代码更容易阅读的良好设计和使用能让我们少敲几下键盘、但令代码难于维护的编程技巧之间的界限,你又是如何划分的呢?如果你需要审视自己是否已从良好设计的航线上迷失,并且误入Hacking以及灵活运用语法技巧的百慕大,存在什么有效的方法吗?

查看英文原文:What's a Ruby DSL and what isn't?

评价本文

专业度
风格

您好,朋友!

您需要 注册一个InfoQ账号 或者 才能进行评论。在您完成注册后还需要进行一些设置。

获得来自InfoQ的更多体验。

告诉我们您的想法

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

更高级的语言。 by fei li

说说我个人对DSL(领域特定语言)的理解,
1.很多开发都需要相应的领域知识,比如,银行,保险,电信等等。同时是技术专家和领域专家的人比较少(个人推测),但是单在某个领域是专家的人就不少。所以,作为开发者提供一种让某个领域的专家更易懂的该领域语言(DSL)不失为一种比较好的解决方案。

2.我们将某个领域的语言 翻译成开发人员能够理解的语言(Ruby、Jave等),Ruby、Jave等虚拟机、编译器又将我们写的代码翻译成计算机可以理解的语言(01代码)。从某种角度上说DSL是我们为某个领域所特别开发的语言,作为开发人员就是在做高级语言编译器。

3.Ruby具有快速建立DSL的能力(个人看法)。

以上纯属个人看法,浅薄之处,请不用客气的指出,谢谢。

Re: 更高级的语言。 by Jacky Li

我非常赞同第一点看法

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

2 讨论

登陆InfoQ,与你最关心的话题互动。


找回密码....

Follow

关注你最喜爱的话题和作者

快速浏览网站内你所感兴趣话题的精选内容。

Like

内容自由定制

选择想要阅读的主题和喜爱的作者定制自己的新闻源。

Notifications

获取更新

设置通知机制以获取内容更新对您而言是否重要

BT