An Introduce to DSL Programming
本文先介绍了元编程的概念,接着举了几个DSL的例子,最后总结了DSL开发的前景。
在讨论DSL之前,首先讨论一下元数据。
元数据指对数据信息的描述,比如Latex对排版的描述,Mac中的plist,gradle对Android项目的描述,Java中的注解,甚至通信领域中通过ASN.1对LTE报文的描述,都可以称作“元数据”。这种描述可以看作为一种抽象语法,即Abstract Syntax。如果这种抽象语法的描述只为特定领域设计,就被称作领域专属语言(DSL, Domain Specific Language)。
DSL的分类 | 举例 |
---|---|
内部DSL | Ruby, Lisp, Java(Annotation), Groovy, kotlin |
外部DSL | XML, SQL, JSON, Plist, Regex, Markdown, SCSS, React |
领域专属语言与通用语言是相对的,它一般用于解决特定的专业问题,适合不太懂编程但是又有简化工作需求的专业人员(比如金融、通信、机器人),以减少编码工作量。
在Java中,甚至不仅在JavaEE中,在Android中也使用范围非常广泛。主要有外部描述与自描述两种方法
属性就是不经意间新建的元数据。
- app:xx
下文将具体叙述如何通过DSL将业务与实现分离出来的。
在硬件开发中,一般先设计电路,再进行C的软件移植。在这个过程中,电子工程师精通电路设计而不懂C语言,如果在使用元数据以前,可能是这样的:比较小的团队可能需要一个同时精通C与电子领域业务的专家来支撑项目,工资高、新人培养难度大不说,极有可能产生单点故障;大的团队可能会将项目文档化,先让电子领域专家写设计原型,然后交给SE写文档,最后让开发照着文档填接口,这样最后的结果就是延长了开发周期,需求易变质,开会次数多。而这些文档、沟通其实是可以用计算机代劳的。
而使用元数据后,专家可以通过鼠标在软件平台中拖拽来设计芯片、电路等物理数据。软件平台的引擎对设计图进行解析,并能够生成准确的电子元件的C语言头文件。最后C语言开发者通过调用头文件这类SDK进行软件层的开发,进而对硬件进行控制。这样就实现了设计与开发分离,让传统行业(电子通信、电气、汽车等)与IT技术的合作成为可能,并节约了无谓的重复手工劳动时间。
- 领域专业知识 + 电路设计图(元数据,可能用xml进行描述)
- |
- |(元数据处理引擎处理)
- |
- 硬件平台的C语言SDK代码
- |
- |(软件开发者,可以找便宜外包,不需要理解物理实现细节)
- |
- 基于SDK的上层开发
在编写终端程序时,当输入外部参数为空时,一般要输出Help或者Usage信息,JCommand就是用于处理用户输入数据的Parser,通过定义注解元数据
- static class Arguments {
- @Parameter(names = { "-h", "--help" }, description = "Help message", help = true)
- boolean help;
- @Parameter(names = { "--conf-file" }, description = "Configuration file")
- public String confFile;
- @Parameter(description = "persistent://prop/cluster/ns/my-topic", required = true)
- public List<String> topic;
- @Parameter(names = { "-t", "--num-topics" }, description = "Number of topics")
- public int numDestinations = 1;
- }
当你运行程序时,比如输入下列参数,JCommand就会自动为
对象映射并赋值。
- confFile
- . / app - t 20--conf - file / usr / etc / app.cfg
通过上述注解,简化了繁琐的入参命令Parse流程,代码看起来也更简洁。
在Groovy中,通过DSL可以用易读的写法生成XML
最后将生成
- <html>
- <head>
- <title>Hello</title>
- <script ahref='https://xxxx.com/vue.js' />
- </head>
- <body>
- <p>Excited</p>
- </body>
- </html>
这里相对于Java这样的动态语言,最为不同的就是
这个并不存在的方法居然可以通过编译并运行,它内部重写了
- xml.html
方法,并进行闭包遍历,少写了许多POJO对象,效率更高。
- invokeMethod
看了上面的DSL介绍,各位可能激动不已,跃跃欲试了,如果你正在看某个技术汇报胶片,甚至已经激动地打算全员推广DSL了,其实你忘记了DSL的风险,它只是看起来很美好
等语法(想想ant脚本有多难用吧),也就是直接用XML写AST,这样最终结果痛苦不堪。这类DSL统统不如直接调用Java自带的JSScriptEngine直接eval(同时注意安全风险)。
- <if>
各位可能在DSL的书籍中看到通过DSL降低代码量的例子,但是众所周知,在总信息量不变的情况下,代码行数越短,它的“潜规则”信息量就越多,而这些一旦出现问题,很难定位。
元驱动开发是高效分工的产物,通过DSL编写一个小范围内使用的语言,可以降低成本,提高程序可维护性。但是DSL一旦没玩好,反而是一个大坑。结合我做过的DSL项目,我的建议如下:
下面列举了一些书籍与工具
来源: https://juejin.im/entry/59f29ad06fb9a0451d40b671