写点什么

Obie Fernandez 谈敏捷 Ruby DSL

  • 2007-04-16
  • 本文字数:2107 字

    阅读完需:约 7 分钟

Software-Engineering Radio (一个向资深软件开发者提供音频节目的站点)最近就DSL(特定领域语言)和Ruby 语言如何使得编写内部DSL 变得更加方便等问题采访了InfoQ 的专家Obie Fernandez ,摘要如下:

DSL 是一种专注于某一特定领域的语言,使用通用语言(如 C 或者 Java)当然可以得到与 DSL 相同的功能。但是这样会产生大量繁琐的代码并导致大量的领域知识被隐藏在通用语言构造中(如 for 循环,if 条件,方法调用,import 声明等等)。

生成以及维护通用语言编写的代码本身也是问题所在:专家们必须将他们的知识变为代码。通常这些专家(销售人员,经理或者园丁)缺少编程知识,这意味着他们必须与程序员进行协作。当然,这也意味对代码的任何一次修改都包括许多繁琐的步骤:如果一个领域专家需要改变某些功能,她必须首先与程序员进行交流,由程序员实现这些修改,然后领域专家检查这些代码是否表现出期望的行为,诸如此类。

对于上述问题,其中一个可能的解决方案是开发一种适应特定环境的语言,非技术人员可以用它来解决问题。这种语言较通用语言更简洁并且仅仅提供目标领域所需要的类型以及特定的语言构造。

在访谈中, Obie 将 DSL 类比为自然语言中的俚语或者行话。全世界喜爱咖啡的人对下面这句话一定非常熟悉:

Venti half-caf, non-fat, no foam, no whip latte

在正常的对话中,上述语言不能传递正确的语义。并且世界上大多数的咖啡馆里可能仅仅提供最普通的牛奶加咖啡。但是在合适的场所使用上述语言(例如,星巴克),它将让你使用最少的词语喝到想要的饮料并且很少会造成误解。

有多种方式可以实现 DSL。其中一个选择是定义一种语法并使用解析器生成工具(如 ANTLR 或者 YACC)来生成解析器。通过它可以将 DSL 代码转化为某种可以被解释的数据结构(语法树)。其中一个例子是 Make 文件,它被用来定义构建过程(编译,打包,部署)。另一种方式是使用 XML 而不是解析器,它将对于解析器生成工具的依赖变为对于 XML 解析器的依赖,有许多工具可以用来支撑 XML 处理(使用 DOM 解析器可以得到类似语法树的数据结构,同时使用 XPATH 来提取数据,等等)。Ant,是一个基于 XML 的 DSL, 构建过程被定义为 XML 格式。Make 和 Ant 就是 _ 外部 _DSL 最典型的实现。

另一个解决方案是 _ 内部 _DSL, 它不需要使用任何解析器生成工具以及 XML 解析器,取而代之的是使用现有的合法的通用语言的构造,很明显,这种语言的构造必须非常灵活才可以容纳各种简练的 DSL 代码。

内部 DSL 的终极解决工具非 LISP 以及类 LISP 语言莫属,原因是 LISP 灵活的语法,它可以被概括为:

  • 原子
    几乎任何字符都可以成为原子,如foo:::bar:::甚至加号都是合法的原子
  • 零个或多个原子组成的序列
    放入圆括号中

LISP 宏特性使得开发者可以很轻易的在 LISP 中定义 DSL 并且将其解释或者展开为可以执行的通常的 LISP 代码。

另外一种适于使用内部 DSL 的语言是 Ruby, 没什么可惊奇的,想想 Ruby 丰富的语法吧,它是 Ruby 得以支持内部 DSL 的部分特性。下面是 Obie 在 PPT 上所使用到的观点以及相应的示例代码:

  • 方法调用中括号可以省略。这看起来没什么大不了的, 但是它使得下面的声明成为合法的 Ruby 代码: order = latte venti, half_caf, non_fat, no_foam, no_whip 在上面的例子中,latte(拿铁咖啡)以及我们所需要的特别的口味儿都是方法调用的一部分。latte 方法返回一个将咖啡各个属性进行了初始化的对象。

  • 类的定义在载入时可以被动态执行 class RuleSet < ActiveRecord::Base has_many :commends, :dependend => :delete_all # ... more... end 这是一个内部 DSL 在 Rails 的 ActiveRecord 中的例子。has_many 调用会在类第一次被载入时执行。这个调用被用来设定类的关联以及行为,例如,它可以通过 define_method 调用向类添加一些方法。这样这段 DSL 代码的用户可以使用非常简洁,描述性的方式来定义类某些方面的行为。事实上,这与 LISP 宏有很多相似的地方,他们都在代码被载入时进行工作。

  • 简洁的代码块书写格式(Block)块是自包含的 Ruby 代码。它可以被保存,当作参数传递并在以后执行,这个概念也被称做是匿名方法,lamda 演算或者闭包(Closures),在 Ruby 中向方法传递块非常简洁紧凑,它使得实现特定语言构造变得非常容易, Rake 是与 Make 和 Ant 非常相似的构建工具,我们来看一个例子:

    task :default => [:test] task :test do ruby "test/unittest.rb" end 上面的类使用了我们在这里提到的所有的三种概念。task 是一种方法调用,但是没有圆括号让它变的更具描述性。task 调用在载入时被执行,对内部数据结构进行设置。test 任务的逻辑在块中进行定义(在 do 和 end 之间的代码),并在适当的时候被执行。

在 Ruby 中,内部 DSL 使得编写简洁和描述性的规范变得非常容易。正如我们从 has_many 例子中看到的,内部 DSL 也可以很容易的与通常命令式的 Ruby 代码进行混合。

译者简介:胡凯是 InfoQ 中文站的志愿者翻译。2006 年加入 ThoughtWorks ,通过在 ThoughtWorks 多个国家和多个项目的敏捷实践,坚定地站在了敏捷阵营中,目前在进行 CruiseControl 相关的敏捷开源项目。他和许多敏捷开发者一样活跃在敏捷中国 CruiseControl-China 社区中。

2007-04-16 20:001145

评论

发布
暂无评论
发现更多内容

如何在TypeScript/JavaScript项目里引入MD5校验和

华为云开发者联盟

JavaScript typescript npm md5 MD5校验

医疗保健行业如何从区块链中受益?

CECBC

安卓隐私沙箱来了!Android Privacy Sandbox简介

XCG00

android

网络损伤工具大乱斗

声网

Dev for Dev 网络损伤 网络仿真 网络与传输

你知道MySQL InnoDB 的内存组件有哪些吗?

程序猿阿星

MySQL MySQL InnoDB Buffer Pool

再谈 AI 及未来的趋势 | 社区征文

宇宙之一粟

AI 新春征文 2月月更

IDP深度 | 企业到底需要何种数据分析挖掘工具?

Baihai IDP

人工智能 数据挖掘 商业智能

万字详解数据仓库、数据湖、数据中台和湖仓一体

五分钟学大数据

数据中台 数据仓库 数据湖 湖仓一体

系统学习 TypeScript(一)——认识 TypeScript

编程三昧

typescript

模块 8 作业

miliving

【营】在开局,提升【豹】发力 - vivo活动插件管理平台

vivo互联网技术

前端 插件系统 构架

Bloom Filter 优化- CrimsonDB系列论文(一)

Emc

存储 LSM-Tree

提权方式及原理简介(面试)

喀拉峻

黑客

netty系列之:EventExecutor,EventExecutorGroup和netty中的实现

程序那些事

Java Netty 程序那些事 2月月更

【架构训练营-模块三】

默光

架构训练营5期

面试突击24:为什么wait和notify必须放在synchronized中?

王磊

面试 java面试

「前端CI/CD系列」第一篇:如何用建木CI往七牛云上传文件

Jianmu

CDN CI/CD 文件存储 七牛云 建木CI

龙蜥社区一周动态 | 2.14-2.20

OpenAnolis小助手

Linux 开源 动态

java培训:JVM 的面试题

@零度

JVM JAVA开发

学生管理系统模块4作业

刘洋

#架构实战营 「架构实战营」

【漏洞分析】反序列化漏洞

网络安全学海

网络安全 信息安全 渗透测试 WEB安全 安全漏洞

浅谈 AI 物联网基础常识 | 社区征文

liuzhen007

AI 新春征文 2月月更

大厂晋升指南:材料准备,PPT写作和现场答辩

邴越

大厂技能 2月月更 晋升 职级

如何理解用户的行为?

石云升

产品经理 用户研究 用户模型 2月月更

当前主流视频编码技术浅析| 社区征文

王强

视频编解码 新春征文

基于CC2530(ZigBee设计)的温度报警器

DS小龙哥

2月月更

从冬奥看中国科技(六):千里光伏初长成

脑极体

Spring Boot AOP 扫盲,实现接口访问的统一日志记录

沉默王二

Java

扔掉 Electron,拥抱基于 Rust 开发的 Tauri

百瓶技术

rust 前端 框架开发 tauri

凡泰极客加入中商联互联网应用工作委员会并荣任常务委员单位

FinClip

AI安全技术总结与展望| 社区征文

herosunly

人工智能 新春征文 2月月更

Obie Fernandez谈敏捷Ruby DSL_Ruby_Werner Schuster_InfoQ精选文章