Atitit. 提升软件开发效率and 开发质量---java 实现dsl 4gl 的本质and 精髓 O725
1. DSL主要分为三类:外部DSL、内部DSL,以及语言工作台。 1
2. DSL规则 2
2.1. DSL = 整洁的代码 2
2.2. DSL必须以文本代码的形式出现 2
2.3. DSL的语法应该尽可能地接近英语或者其他自然语言 2
3. DSL 文本形式 or 图形标识 2
4. 实现方式 2
4.1. 2. 管道抽象 2
4.2. 3. 层次结构抽象 3
4.3. 4. 异步抽象 3
5. 常见的dsl 4
5.1. css ,html.easyui 表单验证等.. 4
5.2. Rule Engine)语言、drools,工作流(Workflow)语言等。 Jbpm 4
5.3. SQL hql linq ,XQuery,正则表达式 4
5.4. 业务api.通用模块。工作流语言。。图形化编程.ant ,shell..Java 6注解,attilaxc#.常见的DSL还有规则引擎(AOP实现,,框架api ,,.xml..json..yaml 4
6. #--实现java内部 DSL 4
6.1. 参考在的语言 anno frm tapestry?? 4
6.2. Groovy 4
6.3. Ide整合的dsl--code templete 5
6.4. 方法链 5
返回this: 5
返回中间对象 5
相比返回中间对象的的方式来说,返回this的方式更加容易组织连贯接口的代码 6
6.5. 静态工厂方法(static factory method)和import对于创建简洁易读的DSL来说是不错的助手。 6
6.6. 元编程; 6
6.7. 编译工具;可以使用lex,yacc,或者javacc,antlr 6
6.8. 使用框架 6
6.9. Std lib 7
7. DSL and 易读API的区别 7
8. Java实现dsl的限制 7
9. Java 实现dsl的优点 7
10. 结论 7
11. 参考 8
1. DSL主要分为三类:外部DSL、内部DSL,以及语言工作台。
2. DSL规则
2.1. DSL = 整洁的代码
2.2. DSL必须以文本代码的形式出现
2.3. DSL的语法应该尽可能地接近英语或者其他自然语言
作者:: 老哇的爪子 Attilax 艾龙, EMAIL:1466519819@qq.com
转载请注明来源: http://blog.csdn.net/attilax
3. DSL 文本形式 or 图形标识
……或者为什么不使用图形标识?文本型的DSLs有几大优势。首先是更加容易建立语言以及一个好的编辑器。其次,文本型的工件比图形化的模型库更加 容易集成到现有的开发工具(CVS/SVN diff/merge)中。第三,文本型的DSLs通常更容易被开发者接受,因为“真正的开发人员不画图”。
如果对于系统的某些方面,图形标识有助于看清楚架构元素之间的关系,你可以使用类似于Graphviz或者Prefuse之类的工具。既然模型以一 种清晰而又干净的形式包含了相关的数据,我们就可以轻易的将模型数据导出成GraphViz或者Prefuse工具能够阅读的形式。
4. 实现方式
4.1. 2. 管道抽象
在Shell中,我们可以通过管道将一系列的小命令组合在一起实现复杂的功能。管道中流动的是单一类型的文本流,计算过程就是从输入流到输出流的变 换过程,每个命令是对文本流的一次变换作用,通过管道将作用叠加起来。在Shell中,很多时候我们只需要一句话就能完成log统计这样的中小规模问题。 和其他抽象机制相比,管道的优美在于无嵌套。比如下面这段C程序,由于嵌套层次较深,不容易一下子理解清楚:
//Cmin(max(min(max(a,b),c),d),e)
而用管道来表达同样的功能则清晰得多:
#!/bin/bashmax a b | min c | max d | min e
4.2. 3. 层次结构抽象
除了管道这种“线性”结构外,流畅接口还可用于构造层次结构抽象。比如,用Javascript动态创建创建下面的HTML片段:
<div id="’product_123’" class="’product’"><img src="’preview_123.jpg’" alt="" /><ul> <li>Name: iPad2 32G</li> <li>Price: 3600</li></ul></div>
若采用Javascript的DOM API:
而下面流畅接口API则要有表现力得多:
//Javascriptvar obj =$.div({id:’product_123’, class:’product’}) .img({src:’preview_123.jpg’}) .ul() .li().text(‘Name: iPad2 32G’)._li() .li().text(‘Price: 3600’)._li() ._ul() ._div();
4.3. 4. 异步抽象
流畅接口不仅可以构造复杂的层次抽象,还可以用于构造异步抽象。在基于回调机制的异步模式中,多个异步调用的同步和嵌套问题是使用异步的难点所 在。有时一个稍复杂的调用和同步关系会导致代码充满了复杂的同步检查和层层回调,难以理解和维护。这个问题从本质上讲和上面HTML的例子一样,是由于多 数通用语言并未把异步作为基本元素/语义,许多异步实现模式是向语言的妥协。针对这个问题,我用Javascript编写了一个基于流畅接口的异步 DSL,示例代码如下:
5. 常见的dsl
5.1. css ,html.easyui 表单验证等..
5.2. Rule Engine)语言、drools,工作流(Workflow)语言等。 Jbpm
5.3. SQL hql linq ,XQuery,正则表达式
5.4. 业务api.通用模块。工作流语言。。图形化编程.ant ,shell..Java 6注解,attilaxc#.常见的DSL还有规则引擎(AOP实现,,框架api ,,.xml..json..yaml
6. #--实现java内部 DSL
6.1. 参考在的语言 anno frm tapestry??
实现方式1:::
实现方式2:::
6.2. Groovy
6.3. Ide整合的dsl--code templete
使用Java,我们同时能利用强大且成熟的类似于Eclipse和IntelliJ IDEA的集成开发环境,由于这些集成开发环境“自动完成(auto-complete)”、自动重构和debug等特性,使得DSL的创建、使用和维护 来的更加简单。另外,Java5中的一些新特性(比如generic、varargs 和static imports)可以帮助我们创建比以往任何版本任何语言都简洁的API。
6.4. 方法链
使用方法链接来创建DSL有两种方式,这两种方式都涉及到链接中方法的返回值。我们的选择是返回this或者返回一个中间对象,这决定于我们试图要所达到的目的。
返回this:
在可以以下列方式来调用链接中方法的时候,我们通常返回this:
· 可选择的
· 以任何次序调用
· 可以调用任何次数
我们发现运用这个方法的两个用例:
1 相关对象行为链接
2 一个对象的简单构造/配置
使用连贯接口,再一次减少了代码噪音,所带来的结果是更易读的代码。需要指出的很重要的一点是,在返回this的时候,链中任何方法都可以在任何时候被调用,并且可以被调用任何次数。在我们的例子中,color这个方法我们可想调用多少次就调用多少次,并且每次调用都会覆盖上一次调用所设置的值,这在应用程序的上下文中可能是合理的。
返回中间对象
从连贯接口的方法中返回中间对象和返回this的方式相比,有这样一些优点:
· 我们可以使用编译器来强制业务规则(比如:必需属性)
· 我们可以通过限制链中下一个元素的可用选项,通过一个特殊途径引导我们的连贯接口用户
· 在用户可以(或必须)调用哪些方法、调用顺序、用户可以调用多少次等方面,给了API创建者更大的控制力
相比返回中间对象的的方式来说,返回this的方式更加容易组织连贯接口的代码
对方法返回this的连贯接口建档比对返回中间对象的连贯接口建档来的简单的多,尤其是在使用Javadoc来建档的情况下。
6.5. 静态工厂方法(static factory method)和import对于创建简洁易读的DSL来说是不错的助手。
dialog.table("results").selectCell(6, 8); // row 6, column 8
dialog.table("results").selectCell(row(6).column(8));
6.6. 元编程;
1. 利用现有语言进行元编程;(比如:我们web开发常用的一些ssh框架,而语言层面,lisp,ruby这些语言的宏编程直接提供元编程能力)
6.7. 编译工具;可以使用lex,yacc,或者javacc,antlr
等帮助我们建立新语言的描述和解释。比如antlr提供了词法描述,语法描述,各 种目标语言(java,c,c++)的词法分析器,语法分析器生成。利用他你可以实现一个完整的语言。在各种建模工具逆向工程,比如通过代码生成图表描述 的工具uml,powerdesign)等都可以看到他的身影;
6.8. 使用框架
Rails框架被称为基于Ruby的DSL,用于管理Ruby开发的Web应用程序。Rails之所以被称为DSL,原因之一在于Rails应用了一些Ruby语言的特性,使得基于Rails编程看上去与基于通用目的的Ruby语言编程并不相同。
如果把Rails看作是一种语言,它应该是基于Ruby、以Ruby为根基的,同时它自身也有独立的特性。
Rails都看作一个很大的DSL
6.9. Std lib
7. DSL and 易读API的区别
在DSL和API两者间其实很难区分。在内部DSL的例子中,他们本质上几乎是一样的。在联想到DSL这个词汇的时候,我们其实是在利用主编程语言在有限的范围内创建易读的API。“内部DSL”几乎是一个特定领域内针对特定问题而创建的极具可读性的API的代名词。
8. Java实现dsl的限制
任何内部DSL都受它基础语言的文法结构的限制。比如在使用Java的情况下,大括弧,小括弧和分号的使用是必须的,并且缺少闭包和元编程有可能会导致DSL比使用动态语言创建来的更冗长。
9. Java 实现dsl的优点
一般来说,使用Java编写的DSL不会造就一门业务用户可以上手的语言,而会是一种业务用户也会觉得易读的语言,同时,从程序员的角度,它也会是一种阅读和编写都很直接的语言。和外部DSL或由动态语言编写的DSL相比有优势,那就是编译器可以增强纠错能力并标识不合适的使用,
10. 结论
Java适用于创建开发人员易读易写的、并且对于商业用户用样易读的内部领域特定语言。用Java创建的DSL可能比那些由动态语言创建的DSL来 的冗长。但好的一面是,通过使用Java,我们可以利用编译器来增强DSL的语义。另外,我们依赖于成熟且强大的Java集成开发环境,从而使DSL的创 建、使用和维护更加简单。
11. 参考
Paip.声明式编程以及DSL 总结 - attilax的专栏 - 博客频道 - CSDN.NET
paip. dsl 编程语言优点以及 常见的dsl - attilax的专栏 - 博客频道 - CSDN.NET
DSL 用于Java开发中 - linugb118--java space - BlogJava.htm
atitit.提升开发效率--java实现DSL
API设计新思维:用流畅接口构造内部DSL _ IT瘾