2020年第一届低代码研讨会上, Jordi Cabot发表了一篇文章(或者说观点),对比了低代码和模型驱动开发的关系,认为低代码等于模型驱动开发。但实际上,不少低代码系统并不是使用模型驱动的,而是采用另一个策略,即代码生成。那这两者区别是什么,各有什么优势, 本文会详细介绍。
关于代码生成和模型解释
在模型驱动开发中,代码生成用于从更高级别的模型生成代码,以创建可运行的应用程序。让我们考虑下面这个使用领域特定语言(Domain-Specific Language, DSL)创建的领域模型:
Customer {
Name: String;
Address: String;
}
如果我们想为这个小模型生成Java代码,我们可以使用模板引擎。模板包含Java代码和一些Token,这些Token将根据模型来填充。例如,我们可以为域模型中的每个实体使用模板。模板代表一个Java类,实体的名称作为类名(例如客户)。对于每个属性,将生成一个私有字段。
在模型解释的情况下,我们不会通过生成代码的方式来从模型中创建一个可运行软件应用程序。在模型解释中,我们会使用一个(比如)Java实现的通用引擎用,模型直接由这个引擎来解释。例如,这个通用的Java程序中包含一个带有属性name的类Entity和一个包含该实体属性(name-value对)的hashmap。在这种情况下,客户实体不是由Java类表示的,而是由一个带有属性名称的Entity对象表示的,该属性name的值是Customer。这些实体对象是根据模型中的信息创建的。
代码生成和模型解释都在实践中使用。让我们来看看这些方法相互比较的优势。
代码生成的优势
与模型解释相比,代码生成具有以下优点:
- 它保护你的知识产权:通过代码生成,你可以为特定的客户端生成一个应用程序。当使用模型解释时,你必须给把整个运行时引擎给客户,这样才能实现整个应用。例如,如果要构建一个网站,你可以把运行网站所需的所有代码给到客户即可。而如果使用解释器,你必须给他们整个系统来解释任何可以用你的DSL描述的网络应用。当您的产品有大量客户的时候,这一点尤其重要。
- 它可以适应您的客户架构:当使用模型解释时,您必须按照自己选择的架构实现解释器。在代码生成的情况下,您可以根据客户的要求来生成代码。
- 生成的实现更容易理解:您可以查看生成的代码并直接理解应用程序的行为。在模型解释的情况下,您必须理解解释器的通用实现和模型的语义。
- 更容易上手:如果您已经手工构建了一个应用程序,您可以开始使用代码生成,方法是将现有代码转换为模板,并用token替换部分代码,token将被模型信息替换。如果您为同一个领域构建了多个应用程序(例如,为不同的客户),您可以开始分析这些应用程序。静态代码(即所有应用程序的代码都是相同的)可以放在域框架中,只需要生成可变代码即可(即您需要创建域特定语言来建模可变性)。
- 它更容易迭代:正如前面所解释的,您可以通过将现有代码转换为代码生成模板来开始使用代码生成。当然,您可以通过迭代的方式做到这一点。首先,您只生成代码的一部分,其他部分将手动实现,稍后,您可以扩展代码生成器以生成代码的更多部分。您的DSL也是如此。起初,它可以是初级的,以反映将要生成的代码。以后,您可以通过提高抽象级别来提升领域专业能力。
- 编译器为它提供了的附加的检查能力:当您生成代码时,需要编译该代码。这个编译步骤是一个附加的检查,因为编译器将检查生成的代码是否有错误。如果有解释器,您需要在模型解释期间自己进行这些检查,或者您需要在建模环境和解释器之间创建一个紧耦合。
- 调试生成器本身比调试解释器更容易:如果您需要调试解释器,则始终需要条件断点,因为解释器代码是通用的。
- 模板的变化更容易跟踪:代码生成模板只是文本文件,因此变化很容易跟踪(例如通过使用版本控制系统)。解释器代码的变化也是如此,但是,这段代码是通用的,不容易搞清楚到底发生了什么变化。
模型解释的优点
与代码生成相比,模型解释具有以下优点:
- 它支持快速变更:模型中的更改不需要再次代码生成、编译、测试和重新部署。这将缩短上线时间。
- 它支持在运行时进行更改:因为模型在运行时可用,所以甚至可以在不停止运行应用程序的情况下更改模型。
- 更容易移植:解释器原则上创建一个独立于平台的目标来执行模型。创建一个运行在多个平台(例如多个操作系统、多个云平台)上的解释器很容易。在代码生成的情况下,您需要确保您生成的代码符合平台要求。在模型解释的情况下,解释器是一个黑匣子,只要它能在目标平台上运行,如何实现并不重要。
- 更容易部署:当使用代码生成时,您经常会看到您需要在Eclipse或Visual Studio中打开生成的代码,并构建它来创建最终的应用程序。在模型解释的情况下,您只需启动解释器并将模型放入其中。代码不再是必要的了。因此,对领域专家来说, 部署和运行应用程序比仅仅建模要容易得多。
- 更容易升级和缩放:更改解释器并用相同的模型重新启动它更容易。您不必使用更新的生成器再次生成代码。缩放也是如此:缩放应用程序意味着初始化解释器的更多实例,执行相同的模型。尤其是在云环境中,这可以给你带来优势。
- 它更安全:例如,在云平台上,你只需要上传你的模型,就不需要访问文件系统或其他系统资源。只有解释器中的代码可以访问系统库。解释器在基础设施之上提供了一个额外的层,下面的一切都被抽象掉了。这本质上是平台即服务(PaaS)的想法。
- 它比代码生成更灵活:基于模板的代码生成是有限制的。在这种情况下,您将需要帮助文件来扩展基于模板的代码生成的可能性。在这种情况下,解释器可能不那么复杂,通常需要更少的代码来完成相同的结果。
- 在运行时调试模型:虽然模型在运行时可用,但可以通过在运行时遍历模型来调试模型(也就是说,您可以在模型上添加断点)。这仅适用于操作语言,而不适用于声明性语言(在那里您需要静态分析)。当可以在模型级别调试时,域专家可以调试自己的模型,并根据此调试调整应用程序的功能行为。这在使用复杂的过程或状态模型时非常有帮助。
结论
比较这两种方法的优势,我们可以得出结论,最终这完全取决于构建和/或使用模型驱动软件工厂的人员的领域、用例和技能集(或舒适性)。
当我们讨论代码生成和模型解释之间的区别时,很快就会带来更多的问题:代码生成和模型解释之间有什么区别?这两种方法之间的界限是什么?如果我们在生成代码时有一个内存文件系统呢?如果我们通过编译模型的一部分来优化我们的解释器呢?如果解释器为浏览器生成数据库结构和网络内容呢?
好了,今天的文章分享到这就结束了,要是喜欢的朋友,请点个关注哦!--我是简搭(jabdp),我为自己“带盐”,感谢大家关注。