实例讲解 Ruby DSL
Ruby 语言的一大特色就是其非常强大 DSL 能力。
那什么是 DSL 呢?英文全称为 "Domain-Specific Language", Martin Fowler 对其的定义为:
Domain-specific language (noun): a computer programming language of limited expressiveness focused on a particular domain.
大家可以想象一下,一门用来解决特定领域问题的语言,它相对于通用领域的语言,所面对的问题是有限的,因此相对而言,领域特定语言的表达是更简洁的,因为使用领域特定语言就相当于默认已经给定了上下文。
领域特定语言分为外部 DSL 和内部 DSL,我们要讲解的 Ruby 语言编写的 DSL 就属于内部 DSL。
上面讲过了,DSL 是用于解决特定领域问题的语言,那什么是特定领域呢?举个例子,Rails 可以说就是一门 DSL , 因为它就是 Web 开发这一特定领域的一套解决方案。
如果按照 Rails 给定的思路写程序,那么就能用较少的代码,完成更多的工作。
下面我会以命令行应用的 UI 为例来介绍一下 DSL 的用法。
领域问题
要使用领域特定语言, 就一定要知道 领域问题 是什么。
以构建命令行应用为例,要面对的一个领域问题就是 UI 的构建。
命令行的表现能力是有限的,因此对于命令行的 UI, 基本也有一套固定的思路。
和 RESTFul 有一套固定格式类似,命令行应用也是有一套自己的参数格式的。
一个命令后应用可以被分为 Executable
Options
Arguments
这么几个部分。
先以下面这个命令行应用为例子:
grep --ignore-case -r "some string" /tmp
Executable
grep
也就是被执行的程序
Options
--ignore-case
和 -r
,前者是 long-form
,后者是 short-form
。同一个 option 可以同时拥有 long-form 和 short-form 两种写法。
Arguments
some string
和 /tmp
Command
实际上更复杂的命令行程序还有 Command 这个概念,不过这里不作讨论。
我们的任务
解决命令行应用的 help UI 的构建问题,设定好 options 后,可以方便的打印出各项 options 的用法。
非 DSL 的写法
这里不做具体实现了,就写点伪代码。
一般的思路无非就是:
创建一个散列表来储存 options 的信息,然后解析之,最后打印出来。
DSL 的写法
先看看 Ruby 标准库自带的 OptionParser 是怎么做的
运行结果:
怎么样,是不是可读性上了一个档次。
创建自己的 DSL
在下面这个例子中, 我们要创建一个用于 "模拟" git 提交记录的 DSL, 类似于 git 中的 Lorem Ipsum.
比如说为了讲解 git 的分支使用方式, 我可能需要一个用于教学的 git 仓库, 如果真的自己手动一次一次地提交, 或者写成脚本都是很枯燥乏味的. 如果有如下的方式来方便地构建一组提交记录, 那想必是极好的,DSL 的写法如下:
可以看到 DSL 的表达力非常强,一个产品的开发流程就这样展示出来了。
下面就是具体的实现,这一定不是最好的实现,但足够理解了
运行结果如下:
总结
限于篇幅,本文到此为止,有兴趣的同学可以自己实现 commit 方法,让这段代码可以变成真正有用的脚本。 最后引用《Ruby元编程》中的一句话:
根本没有什么元编程,从来只有编程而已。
异步社区是一个有料、有货,又专业的IT专业图书社区,在这里可以读到最新、最热的IT类图书!我想要社区的《JavaScript框架设计(第2版)》 这本书,这本书是深度学习领域奠基性的经典图书,请大家帮我点赞!
转载声明:本文转载自异步社区
原文链接:https://www.epubit.com/articleDetails?id=N6622300c-6b1d-4a2b-a179-5f6b2b1ebef4
- 点赞
- 收藏
- 关注作者
评论(0)