Slide 1

Slide 1 text

DSL (Domain Specific Language) @Mark 2020.10.26 特定领域语⾔

Slide 2

Slide 2 text

DSL 特定领域(Domain)所专⻔是合计的词汇和语法,简化程序设计过程,提⾼ ⽣产效率的技术,同时也让⾮编程领域专家的⼈直接描述逻辑成为可能。

Slide 3

Slide 3 text

• 优点: 集中描述 『想要做什么』(What)的部 分,⽽不必对『如何做到』(How)进⾏描述

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

• ⽐如⼀个名为 rake的编译⼯具,功 能和 make差不多会分析⽂件依赖关 系,⾃动执⾏程序编译、链接等操作 • 例⼦表达了: • 1) 默认任务为test • 2) test的内容是执⾏ node, python,ruby三个任务 • 启动rake 是 : rake 任务

Slide 6

Slide 6 text

• DSL是对特定⼩规模语⾔的称呼,是⼀个新叫法,但是这个东⻄并不是稀 罕东⻄,尤其是Unix社区中诞⽣了很多『专⽤语⾔』⼯具 • ⽐如 awk(⽂本处理), make(构建) ,sed(数据流编辑) • Unix中还提供语法分析⽣成⼯具 yacc,以及词法分析器⽣存⼯具 lex • Yacc,lex本身也有⾃⼰的迷你语⾔

Slide 7

Slide 7 text

• 迷你语⾔都是专⽤于特定⽤途,⼤多数情况下⽆法完成复杂⼯作。 • 因此本质上和DSL都是⼀样的。 迷你语⾔

Slide 8

Slide 8 text

外部DSL

Slide 9

Slide 9 text

外部DSL 以迷你语⾔为代表的,专⻔语⾔引擎实现的DSL,统称为外 部DSL。

Slide 10

Slide 10 text

No content

Slide 11

Slide 11 text

• Java程序中⼤量使⽤了可拓展标记语⾔(XML)编写配置⽂件。这种 XML配置⽂件也是⼀种外部DSL 外部DSL例⼦ • 数据库访问所使⽤的 结构化查询语⾔(SQL)也是⼀种典型的外部DSL

Slide 12

Slide 12 text

• 独⽴于程序语⾔,对某个领域操作程序,不⼀定是同⼀个语⾔。 外部DSL优点 • 外部DSL是独⽴于程序语⾔开发,因此可以实现跨语⾔共享。 • 学会SQL可以在不同语⾔中使⽤SQL操作 • 例如正则表达式也是⼀种DSL,在Ruby,Perl,PHP,Python中都可以使 ⽤

Slide 13

Slide 13 text

内部DSL

Slide 14

Slide 14 text

内部DSL 外部DSL是从Unix中发展⽽来,内部DSL则是发源于Lisp和 Smalltalk的⽂化中。

Slide 15

Slide 15 text

内部DSL并不是创在⼀种新的语⾔,⽽是在现有语⾔中实现 DSL。⽽作为DSL的基础,这种语⾔称为宿主语⾔。 Lisp,Smalltalk,Ruby这些语⾔适合作为宿主语⾔,因此这 些语⾔的社区中经常使⽤内部DSL。

Slide 16

Slide 16 text

内部DSL优缺点 • 优缺点和外部DSL正好相反。 • ⽆需学习新语⾔,宿主语⾔的尝试依然有效。 • 甚⾄可以借助宿主语⾔,实现复杂逻辑的书写。 • 『寄⽣』在宿主语⾔上,使得可以轻松实现功能。即使『迷你语⾔』在拓 展线上都⽢拜下⻛。

Slide 17

Slide 17 text

DSL优势

Slide 18

Slide 18 text

DSL优势 • 更简洁的表达 • 减少与程序员交流成本 • 实现⽣产效率提⾼ • 不涉及内部细节,⽽是在⾼级层⾯上描述——抽象化 • # 不断抽象化其实是编程语⾔的未来发展⽅向之⼀

Slide 19

Slide 19 text

DSL的定义

Slide 20

Slide 20 text

DSL的定义 • 如何才算是 DSL呢?

Slide 21

Slide 21 text

DSL定义 • 观点1 像 『是否具备禁⽤于特认定⽤途的功能』、『(设计者)⾃⼰是 否将其命名为⼀种DSL』 这种标准,今天逐渐变得模棱两可

Slide 22

Slide 22 text

• ⻉尔实验室名⾔: • 库设计就是语⾔设计(Library design is language design). 我们在思考编程语⾔的时候,⼤多仅强调语法,但如果脱离了相当于词汇的 库、类和⽅法,语⾔也就⽆法思考。 也就是说 API也是构成编程语⾔的⼀个要素。

Slide 23

Slide 23 text

• Programming is a process of designing DSL for your own application. (编程就是为⾃⼰的应⽤程序设计DSL的过程) —— ⼤卫·托⻢斯

Slide 24

Slide 24 text

DSL定义 • 考虑到DSL实际上是编程语⾔抽象化得延伸,那么问题就不应该是什么是 DSL,什么不是DSL => DSL应该是将⾯向特定领域的API设计成优秀的 DSL这样⼀个设计的过程。

Slide 25

Slide 25 text

• DSL不仅仅是⼀种技术,⽽是程序开发的重要设计原理和原则之⼀,适⽤ 于任何软件的开发。

Slide 26

Slide 26 text

适合内部DSL的语⾔

Slide 27

Slide 27 text

• 虽然任何语⾔都可以成为宿主语⾔,但像Lisp,Smalltalk,Ruby这样的被认 为适合DSL的语⾔,都有⼀些共同的特征

Slide 28

Slide 28 text

• 简洁 DSL本来就是为了针对特定⽬的处理⽤的,⾼级的、简洁的⽅式进⾏描述。 因此简洁的描述⽅式才是最本质的。 简洁是作为DSL宿主语⾔不可或缺的要素。 Lisp、Ruby等于眼中,⽆需声明数据类型,编译器『规矩』也少,因此可 以变得简洁。

Slide 29

Slide 29 text

• 灵活 开发者通过⾼度抽象化代码集中描述 WHAT ⽽不是HOW。因此作为对抽象 化得⽀持,元编程等功能最好⽐较充实。 ⽐如Lisp具备宏(Macro)功能,只要遵循『⽤括号进⾏表达』的S表达式, 就可以实现⾃由表达。因此可以说Lisp语⾔本身就是⼀种可被编程的语⾔。 Ruby中的代码块(Block)功能可以实现控制结构,虽然不像Lisp那样万能, 但是⽤来实现内部DSL也⾜够了。

Slide 30

Slide 30 text

• 灵活 开发者通过⾼度抽象化代码集中描述 WHAT ⽽不是HOW。因此作为对抽象 化得⽀持,元编程等功能最好⽐较充实。 ⽐如Lisp具备宏(Macro)功能,只要遵循『⽤括号进⾏表达』的S表达式, 就可以实现⾃由表达。因此可以说Lisp语⾔本身就是⼀种可被编程的语⾔。 Ruby中的代码块(Block)功能可以实现控制结构,虽然不像Lisp那样万能, 但是⽤来实现内部DSL也⾜够了。

Slide 31

Slide 31 text

No content

Slide 32

Slide 32 text

No content

Slide 33

Slide 33 text

外部DSL实例

Slide 34

Slide 34 text

• 外部DSL就是拥有专⽤引擎的⼀种独⽴特定领语⾔。外部DSL也有各⾃不 同的实现⽔平。 最简单的莫过于配置⽂件,例如 YAML、JSON 更复杂⼀点DSL,虽然也是为特殊⽬的设计,但是可以编写出描述任何算法 的程序。例如 ⽂本处理的 awk。 再⽐如 ⾯向打印机的描述⻚⾯语⾔ PostScript 是⼀个基于逆波兰的图灵完 备语⾔。

Slide 35

Slide 35 text

还有⼀些⽐较特殊,虽然本身也是通⽤语⾔。叫做DSL并不合适,但是却与 特定计算机模型有很强关联性,也就具备了类似DSL的性质。 例如 Prolog 以⼀阶谓词逻辑为基础的语⾔。 统⼀,⽤于并⾏计算的Actor模型密切相关的 Erlang 虽然也是通⽤语⾔,但 是也具备了『⾯向并发编程领域的DSL』这个性质。

Slide 36

Slide 36 text

对于Java中: Java中 XML。由于Java中默认内置了解析XML的库,因此⽤XML写DSL很 容易被读取。这样可以省略为DSL开发语⾔引擎的步骤。 但是XML不论是阅读还是编写都⼗分冗⻓,并不是很友好。

Slide 37

Slide 37 text

DSL设计的构成要素

Slide 38

Slide 38 text

上下⽂(context) 语句 (Sentence) 单位(Unit) 词汇(Vocabulary) 层次结构(Hierarchy)

Slide 39

Slide 39 text

上下⽂ 作⽤就是 定义上下⽂,表示这个测 试的⼀个⼤框架。 ⼀个测试框架例⼦: ⽐如 context “a User instance” do 就表示对 『a User instance』这个 上下⽂的测试进⾏定义的意思 Should⽅法定义了『需要满⾜某个 条件』这样⼀个测试。

Slide 40

Slide 40 text

这样与其说定义测试,不如说定义 了⾏为(Behavior) 有时候也称为规则(Spec)。 前置定义这种Spec就是 BDD ⾏为 驱动开发。

Slide 41

Slide 41 text

⼀个⼩作品,在Ruby的语 法范围内到底能设计出多 接近英语的DSL。 这是⼀个描述做⾯包的 DSL。

Slide 42

Slide 42 text

接近⾃然语⾔的利弊 外⾏⼈容易纠结到底在哪⼉要加上 标点符号。顺序是否可以调换。 COBOL就遇到了这样的设计问题。 由于Ruby可以⾃由增加⽅法,所以 利⽤这⼀点,实现了上⾯的DSL

Slide 43

Slide 43 text

Ruby on Rails 包含的ActiveSupport库中, 『现在时间的20⼩时之前』可以写出 『20.hours.ago』 Rails不仅是⼀种Web框架,也可以说是以 Ruby为基础的DSL

Slide 44

Slide 44 text

词汇、层次 Rails中如果数据库users表中包含name属性, 可以这样调⽤: User.find_by_name(“⻢克”) find_by_name 是⾃动⽣成的

Slide 45

Slide 45 text

层次可以理解为嵌套上 下⽂ ⽤Ruby作为DSL⽣成 XML 看起来可能要⽐XML简 洁

Slide 46

Slide 46 text

Sinatra是⼀个规模较⼩ 的Web框架。 通过特殊的 get语法, 以简洁的形式,应⽤了 上下⽂。

Slide 47

Slide 47 text

⼩结

Slide 48

Slide 48 text

DSL虽然是最近出现,但是实际上已经从数⼗年前就使⽤的技术。 就像给设计模式起个名字⼀样,可以提⾼其认知度。 今后DSL也可能作为判断设计优秀与否的重要指标,对软件开发产⽣巨⼤影 响。

Slide 49

Slide 49 text

Q&A

Slide 50

Slide 50 text

THANKS