原文地址: https://zhuanlan.zhihu.com/p/179488071
最近一直在想前端与 DSL 的一些联系与发展,DSL 的概念在后端工程师中可能会更加熟悉,但在前端领域中也是充斥着 DSL 的身影。
DSL 简介
DSL(Domain Specific Language)中文翻译为领域特定语言,例如 SQL、JSON、正则表达式等。与之形成对比的是 GPL(General Purpose Language),中文翻译为通用编程语言,我们熟悉的 C、C++、JavaScript、Java 语言等就是。
特点
DSL 的特点,在《领域特定语言》这本书中的描述,按照我自己的理解为:
- 是一门便于人们理解的编程语言或规范语言,并且可以被计算机解释执行。
- 相比于通用编程语言,只能表达有限的逻辑。
- 因为受限的表达性,所以只会在某一些领域广泛应用。
分类
主要分为三类:外部 DSL、内部 DSL、语言工作台 。
- 内部 DSL 是一种通用编程语言的特定用法,只不过具有特定的风格。相对于前端最熟悉的就是 jQuery 库,还有 Grunt、Glup、Mocha 等,其都是基于 JavaScript 语言,在他们所需要解决的领域中形成一定语法风格。
`// jQuery $('#my-div') .slideDown() .find('button') .html('follow');
// Mocha describe('User', function () { describe('#save()', function () { it('should save without error', function (done) { var user = new User('Luna'); user.save(done); }); }); });`
- 外部 DSL 是一种独立的编程语言或规范语言,一般有其特定的语法。前端中除了 JavaScript,其实我们大多数使用的都属于外部 DSL 的范畴,比如 HTML、CSS、LESS、JSX 等。
<div> <header>title</header> <section>content</section> <footer>footer</footer> </div>
- **语言工作台 (Language Workbench)**是一种专用的 IDE,可以将 DSL 可视化,并且可以定义和构建一个 DSL。前端工程对于 IDE 和可视化的追求可以说一直是火热,VS code、各种前端搭建可视化工具。
UI DSL 的发展
Web 前端并不是只有 HTML/CSS/JS ,其实历史的洪流中还有 Silverlight、Flash、ActiveX 等,然而各种原因互联网选择了 HTML/CSS/JS 。JS 的初衷并不是为了构建复杂 UI 而设计的,所以对于越发复杂的 Web 前端,前端的 UI DSL 也是在循序渐进的发展,HTML/CSS/JS 的规范不断的在改进迭代,业界更是不满足于现在标准而不断的扩展,从 CSS 到 Less/Sass 、 JS/JSX、Vue 和 Angular 都有各自的组件和 Template 实现,再使用转译器,最终运行等效的代码。
通过基于现有语言,扩展或结合创造一种新的 UI DSL,对于前端开发者的接受程度可能会高,但现实原因只可能更复杂,各种标准规范委员会、浏览器厂商、前端 Runtime 等等。小程序则为了提高交互体验结合 Native 和 WebView 的各自优势,UI DSL 趋向于 Web 端语法,对 Web 前端开发人员友好。
相比 Web 端,移动端因为其原生的独特性 UI DSL 则是出现了断崖般的升级。例如 Object-C 到 Swift UI、Android 的 Kotlin Anko、跨平台 Flutter 的 Dart。各语言背后都是大厂商的支持,初衷都是想开发出更好构建 UI 的语言,大家的趋势都是 UI as Code 。
UI as Code
本质上移动端、Web 端虽然有些许不同,但都是前端,问题领域高度一致。UI as Code 在我看来,这个 Code 的意思,就是一门通用编程语言,然后基于这个编程语言来创建一门内部 DSL 来构建 UI ,逻辑和 UI 的编程都是同一门语言,更加高效并减轻开发者的负担。
Web 前端也有类似的发展趋势。CSS 出现了各种 CSS in JS 的方案,JS/HTML 扩展为 JSX,虽然还是有着浓重的 HTML/CSS 色彩。随着现在许多成熟的组件框架库出现,在开发中后台的时候,除了 JS ,很多时候就几乎只组装组件和一些简单的布局,已经没有写很多 CSS 和直接操作 DOM。这就感同身受了一句话:“编程就是在为自己的应用程序设计 DSL “ ,就是使用组件针对你开发的应用程序构建内部 DSL(封装组件、方法),通过牺牲一部分通用性灵活性提高开发效率。
Facebook 可以构建出 JSX ,Microsoft 可以创造出 TS ,国内也有 Vue ,相信前端在语言层面上的更大的机遇是会抽象出更加好用的 DSL。
可视化平台
前端搭建系统 / 可视化平台,难点多难度大,投入风险高,潜在的回报也巨大。大厂商都在投入研发通用性更高的可视化搭建平台,适用范围更广;小厂商则会针对特定业务来开发搭建系统,难度稍低见效快。如果把范围限定在二者之前,在一个适当的业务领域里,研发与业务领域专家充分沟通,投入研发相关的模型和 DSL ,以可视化作为辅助,在灵活性和效率上找到一个平衡点,可以大大提高领域生产力。
我们经常会去尝试创建拖拽加配置的可视化搭建系统来解决各种不同的业务。没有银弹,系统的复杂度不会消失,只会转移,这里就容易产生 COBOL 谬论:”编程语言很难是因为它不像我们平常交流的语言,如果把编程语言设计为像我们平常用的语言,就会容易多了“。"前端很难,我们把它做成可拖拽的可视化平台,就不需要前端开发了"。
antd 相当于是就是构建了基于 JSX 的 DSL ,在中后台前端开发领域,通过抽象基础的交互展示逻辑, 牺牲了极少的的可扩展性,通用性和灵活性都达到了一定程度。
可视化搭建系统中有一个难题是,当可视化搭建无法实现某些需求,开发者通过修改代码来实现需求后,之后可能就无法再继续转到平台上。对于代码和可视化搭建的互转是一个难题。如果换一个思路,可视化搭建转成的代码,不是直接的 HTML/CSS/JS,而是一个新的内部 DSL 或外部 DSL ,这个 DSL 背后的模型的在灵活性和代码 / 可视化的互转上有特定的设计,代码修改,只要符合这个 DSL 的规范,则可以转为可视化的平台中。这就又回到上面的讨论,没有银弹,以 UI as Code 为趋势,在某一方面上牺牲,缩小领域,换取高效。
产生的问题
不管是内部 DSL 或外部 DSL,盲目的创造 DSL ,造成的问题就是,大家学习与理解的负担越来越大,因为使用多种语言比使用一种语言复杂得多,开发可能没有提效反而更加复杂而容易造成 bug 。
但程序的复杂性不会消失,不使用 DSL,也会需要使用不同的程序库,好的程序库的设计就必不可少,可谓 “程序库设计就是语言设计”。然而一个好的 DSL 也应该是让人容易理解并且容易使用,降低学习成本。
结束语
当大家陷入大量业务开发的时候,不防跳出细节,看看一些抽象和理论的东西来找找灵感。随着网络的提速 5G、6G ,还是 AI、AR/VR 的高速发展,前端交互模式的改变和创新,前端可以探索的东西应该是越来越多的。
参考文章
- https://en.wikipedia.org/wiki/Domain-specific_language
- https://en.wikipedia.org/wiki/General-purpose_language
- https://github.com/munificent/ui-as-code
- DSL 与界面设计杂谈 https://www.yuque.com/arvinxx/note/ax74w9
- 前端 DSL 实践指南(上)—— 内部 DSL https://juejin.im/post/5e4ddf38e51d4526f23a19e1
- 前端开发编程语言的过去、现在和未来 https://johnhax.net/2019/fe-lang/article1
- DSL 的误区 http://www.yinwang.org/blog-cn/2017/05/25/dsl
- 谈谈 DSL 以及 DSL 的应用(以 CocoaPods 为例)https://draveness.me/dsl/
- 《领域特定语言》