设为首页 收藏本站
查看: 827|回复: 0

[经验分享] DSL-SQL源码分析

[复制链接]

尚未签到

发表于 2016-11-11 04:57:09 | 显示全部楼层 |阅读模式
第一次分析源代码,不太会描述,部分文字摘自 在CLR之上的构建领域特定语言
http://www.infoq.com/cn/articles/internal-dsls-java
针对特定域语言(DSL)的定义问题,提出了一种基于对象的语言构造方法,该方法将特定域语言语义划分为领域相关语义和领域无关语义,针对领域相关语义,采用对象将其封装,并通过视图对象和模型对象分别完成领域相关语义的定义与解释;针对领域无关语义,利用现有语言开发工具,直接定义并生成语言基本特性的解释模块,最后将对象和语言基本特性相集成,从而完成DSL的定义与实现.采用基于对象的构造方法可迅速地定义DSL,且具有较强的扩展性.
1.简介
领域特定语言(DSL)通常被定义为一种特别针对某类特殊问题的计算机语言,它不打算解决其领域外的问题。对于DSL的正式研究已经持续很多年,直到最近,在程序员试图采用最易读并且简炼的方法来解决他们的问题的时候,内部DSL意外地被写入程序中。近来,随着关于Ruby和其他一些动态语言的出现,程序员对DSL的兴趣越来越浓。这些结构松散的语言给DSL提供某种方法,使得DSL允许最少的语法以及对某种特殊语言最直接的表现。但是,放弃编译器和使用类似Eclipse这样最强大的现代集成开发环境无疑是该方式的一大缺点。然而,作者终于成功地找到了这两个方法的折衷解决方式,并且,他们将证明该折衷方法不但可能,而且对于使用Java这样的结构性语言从面向DSL的方式来设计API很有帮助。本文将描述怎样使用Java语言来编写领域特定语言,并将建议一些组建DSL语言时可采用的模式。
Java适合用来创建内部领域特定语言吗?
在我们审视Java语言是否可以作为创建DSL的工具之前,我们首先需要引进“内部DSL”这个概念。一个内部DSL在由应用软件的主编程语言创建,对定制编译器和解析器的创建(和维护)都没有任何要求。Martin Fowler曾编写过大量各种类型的DSL,无论是内部的还是外部的,每种类型他都编写过一些不错的例子。但使用像Java这样的语言来创建DSL,他却仅仅一笔带过。
另外还要着重提出的很重要的一点是,在DSL和API两者间其实很难区分。在内部DSL的例子中,他们本质上几乎是一样的。在联想到DSL这个词汇的时候,我们其实是在利用主编程语言在有限的范围内创建易读的API。“内部DSL”几乎是一个特定领域内针对特定问题而创建的极具可读性的API的代名词。
任何内部DSL都受它基础语言的文法结构的限制。比如在使用Java的情况下,大括弧,小括弧和分号的使用是必须的,并且缺少闭包和元编程有可能会导致DSL比使用动态语言创建来的更冗长。
但从光明的一面来看,通过使用Java,我们同时能利用强大且成熟的类似于Eclipse和IntelliJ IDEA的集成开发环境,由于这些集成开发环境“自动完成(auto-complete)”、自动重构和debug等特性,使得DSL的创建、使用和维护来的更加简单。另外,Java5中的一些新特性(比如generic、varargs 和static imports)可以帮助我们创建比以往任何版本任何语言都简洁的API。
一般来说,使用Java编写的DSL不会造就一门业务用户可以上手的语言,而会是一种业务用户也会觉得易读的语言,同时,从程序员的角度,它也会是一种阅读和编写都很直接的语言。和外部DSL或由动态语言编写的DSL相比有优势,那就是编译器可以增强纠错能力并标识不合适的使用,而Ruby或Pearl会“愉快接受”荒谬的input并在运行时失败。这可以大大减少冗长的测试,并极大地提高应用程序的质量。然而,以这样的方式利用编译器来提高质量是一门艺术,目前,很多程序员都在为尽力满足编译器而非利用它来创建一种使用语法来增强语义的语言。
利用Java来创建DSL有利有弊。最终,你的业务需求和你所工作的环境将决定这个选择正确与否。
2.将Java作为内部DSL的平台
动态构建SQL是一个很好的例子,其建造了一个DSL以适合SQL领域,获得了引人注意的优势。
传统的使用SQL的Java代码一般类似于:

String sql="SELECT t.id " + "FROM table AS t "
+ "INNER JOIN table1 AS t1 ON (t.id=t1.id) "
+ "WHERE ((t.id='a') AND (t1.time BETWEEN '1900' AND '2000')) "
+ "GROUP BY t.id HAVING (t.id>1) " + "ORDER BY t.id ASC "

现在用DSL语言的java实现比表示SQL

Table t = table("table").as("t");
Table t1 = table("table1").as("t1");
Field tId = t.field("id");
Field t1Id = t1.field("id");
Field t1Time = t1.field("time");
Query query = select(tId).from(t).join(inner(t1, tId.eq(t1Id))).where(
and(tId.eq("'a'"), t1Time.between("'1900'", "'2000'")))
.groupBy(tId).having(tId.gt("1")).orderBy(asc(tId));
String sql=query.toString();

这个DSL版本有几项优点。后者能够透明地适应转换到使用PreparedStatement的方法——用String拼写SQL的版本则需要大量的修改才能适应转换到使用捆绑变量的方法。如果引用不正确或者一个integer变量被传递到date column作比较的话,后者版本根本无法通过编译。代码“nvl(foo, 'X') != 'X'”是Oracle SQL中的一种特殊形式,这个句型对于非Oracle SQL程序员或不熟悉SQL的人来说很难读懂。例如在SQL Server方言中,该代码应该这样表达“(foo is null or foo != 'X')”。但通过使用更易理解、更像人类语言的“isNotNullOr(rejectedValue)”来替代这段代码的话,显然会更具阅读性,并且系统也能够受到保护,从而避免将来为了利用另一个数据库供应商的设施而不得不修改最初的代码实现。
3.现在介绍DSL-SQL
DSL-SQL是thoughtWorks的开源项目
域代码 http://code.google.com/p/sql-dsl/
附件有源代码分析

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-298512-1-1.html 上篇帖子: javascript解析SQL 语句 下篇帖子: hql与sql区别
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表