为什么选择DSL(上)
DSL (domain specific language, 领域特定语言),简单的说,就是为某种特定的目的设计的一种与特定目的(业务本质)更加匹配的语言。
DSL和通用语言的区别在于,DSL往往不是图灵完备的,它只为某一类 问题服务,不希望可以描述所有的可计算问题。
另一个角度看,高级语言相对于低级语言,比如C相对于ASM也可以视为DSL。它在更高的层面抽象关键字和语法。if/for/while和function相对汇编指令cmp/1dr/sdr/mov描述的并不是同一层面的问题。前者关心的是逻辑,后者关心硬件。越高级的层面,越抽象,越专门,越特定领域(同时意味着它对环境的依赖度更高,递弱代偿,好有道理)。
为什么选择DSL(上)DSL带来的好处是明显的,更加贴近业务。但目前看,这并不是一个普遍的选项,所以先看看使用DSL的困难吧。
技术门槛:
首先要做抽象和建模,抽取核心领域概念(及实体、聚合根关系),并据此设计关键字、语法;
如果选择外部DSL还需要设计DSL和宿主语言之间的转换器,内部DSL要设计对关键字的封装;
对于稍复杂的情况,DSL未必能完成完整的功能,需要设计DSL实现部分与宿主语言实现部分之间的边界(即分层设计),因此选择DSL往往意味着也会选择分层架构。
其中每一项工作都不那么容易实现。但抽象建模和分层结构,对于复杂系统,即便不选择DSL,也是需要充分考虑的事情。
另外还需要考虑DSL本身的学习成本;
维护成本:
随着需求增加,代码变动增加。会出现现有语法不能描述的情况。这时需要扩展语法和转换器。如果转换器本身设计不够解耦,这种扩展会比较困难,同时伴随着风险(产品毕竟发布了,换编译器也许会引入某些隐含的故障)。
同时某种DSL在自我演化的过程中,不可避免的希望支持更多的功能和场景,特别是有个独立的团队维护DSL时。也就是追求图灵完备的歧途。这个时候的取舍,包括是不是某些情况就不支持,用宿主语言实现,做好隔离即可?
也许还有一种蜕化的情况,随着时间推移,DSL能描述的部分比例越发少了。某种原因(比如没有技术能力保持DSL的适当的进化能力)。DSL渐渐不使用了,成为僵尸残存在系统中。
考虑一个场景,DSL开始设计的可以比较好的工作了,并且在比较长的时间(比如一两个版本或者几个月)都不需要维护,最初设计它的专家去做别的事了,DSL本身的维护成为一个真空地带。某些功能可以在现有的语法实现,增加一个关键字更好。但所有的技术判断和改进都没有做;有过去一些时间,DSL本身的技术债债台高筑;最终更多的实现选择用宿主代码实现...DSL一步步的失去了对系统的描述能力。
选择的困难:
怎么能下定决心选择DSL?处理某些罕见的,充满自信的人数不太多精英团队,对于大型项目,选择DSL肯定是一个艰难的决定。怎么能确定今天的投入未来一定会有好的收益?
最开始的时候,系统比较简单,似乎没有必要做DSL。有一天系统复杂了,某些相似的领域概念以千奇百怪的实现实现,大量的重复;当复杂的时候在选择设计DSL对代码进行重构?重写?这个想来也是非常困难的事。
所以,重要的事情是认识到所面对的系统潜在的复杂度和可能存在的周期。如果系统的复杂度是可以预见的大,而且生存周期相当长(比如5年甚至更多),那么是否选择DSL可能是最初就要做的一些决定。
上述并非危言耸听,实际所谈是使用DSL需要提前考虑的三个关键问题: 选择的理由和时机,所需的技术储备 和 长期维护机制。anyway,DSL不是银弹,它只是一种需要完整支持才能发挥价值的工具。下一段主要会谈希望通过DSL解决的问题和与之配套的方法。