• home > webfront > engineer > Architecture >

    XX Driven:数据驱动/模型驱动/领域驱动/元数据驱动/DSL

    Author:zhoulujun Date:

    XX Driven是软件工程领域的常见黑话之一,翻译过来就是某某驱动,替换一下XX,我们就得到了数据驱动、模型驱动、领域驱动、元数据驱动、DS

    XX Driven是软件工程领域的常见黑话之一,翻译过来就是某某驱动,替换一下XX,我们就得到了数据驱动、模型驱动、领域驱动、元数据驱动、DSL驱动等等这一大堆的驱动。

    在软件开发中,"驱动"这个词的使用其实表达了一种理念:以某种特定的因素作为主导,推动整个开发过程。这通常意味着我们把某个特定的目标或原则放在首位,并根据这个目标或原则来指导我们的设计和决策

    比如

    • 测试驱动开发,我们先写测试,然后再写能通过这些测试的代码,测试在这里起到了"驱动"的作用;

    • 职责驱动设计,是对象的职责在"驱动"我们的设计决策。

    • 数据驱动开发(Data-Driven Development)讨论在数据功能中定义处理策略

    • 事件驱动开发(Event-Driven Programming)讨论在基于事件的程序中定义处理策略

    • 领域驱动设计(Domain-Driven Design,简称 DDD)谈论通过使用通用语言来解决领域问题

    通过这样的方式,我们可以确保我们的焦点始终保持在最重要的事情上,从而提高我们工作的效率和质量。

    这些不同的驱动之间有什么区别?

    领域驱动

    DDD 是 Domain-Driven Design 的缩写,是 Eric Evans 于2004 年提出的一种软件设计方法和理念。

    具体可以阅读:https://domain-driven-design.org/zh/ddd-concept-reference.html

    其主要的思想是,利用确定的业务模型来指导业务与应用的设计和实现。主张开发人员与业务人员持续地沟通和模型的持续迭代式演化,以保证业务模型与代码实现的一致性,从而实现有效管理业务复杂度,优化软件设计的目的。

    领域驱动,就是业务驱动,实现就是:业务建模。

    本质逻辑是:识别边界,分而治之!

    以领域专家的角度设计软件实体

    比如说,如果你要设计一个约课软件,这个软件工程师就会与领域专家沟通,设立这个领域的实体和实体之间的关系和规则。

    实体清单:

    1. 老师

    2. 学生

    3. 课程

    实体关系:

    1. 课程有一个老师和多个学生。

    2. 课程有时间和地点

    3. 老师和学生都有姓名

    在这里,没有说课程在软件中是如何具体实现的,比如它是一个object还是一个map都没关系,只要它依然符合领域要求即可。

    例如,请假系统解决的是人力工时的问题,属于人力资源领域,对口的是HR部门;费用报销系统解决的是员工和公司之间的财务问题,属于财务领域,对口的是财务部门;电商平台解决的是网上购物问题,属于电商领域。可以看出,每个软件系统本质上都解决了特定的问题,属于某一个特定领域,实现了同样的核心业务功能来解决该领域中核心的业务需求。

    所以你这里就会发现ddd的好处就是利用了真实世界的领域变化比代码变化来的慢很多的一种现象,把代码逻辑梳理清楚。不管事后你用了oop还是fp还是从单体换成微服务,你的代码梳理的时候以这个领域的逻辑去梳理去测试就会容易很多。

    2.png

    领域建模,推荐阅读:《什么是DDD(领域驱动设计)? 这是我见过最容易理解的一篇关于DDD 的文章了

    模型驱动

    MDA 是由国际对象管理组织(OMG,Object Management Group)于2001年7月提出的基于MDD形式化后的模型驱动架构。

    为了实现MDA的三大目标:轻便可移植性、互操作性和可重用性,采用了模型和技术分离的架构设计

    对于所有的 MD*概念,我们并没有通用的定义。我自己的(非正式)定义如下:

    • 模型驱动工程(Model-driven engineering,MDE):任何一种软件工程过程,其中模型起着基础性的作用并驱动着工程任务。

    • 模型驱动开发(Model-driven development,MDD):MDE 应用于正向工程,即用于软件开发的模型驱动。

    • MDA 是 OMG(Object Management Group,对象管理组) 对 MDD 的特定设想,因此依赖于 OMG 标准的使用。

    • 基于模型的工程/开发:前面各个概念的软版本。在 MBE 过程中,软件模型扮演着重要的角色,尽管它们不一定是工程/开发的关键工件(即它们不“驱动”过程)。

    基于高度业务模型驱动开发MDD,通过使用高度抽象的领域业务模型作为构件,完成代码转换实现或各种模型驱动引擎配置支撑,降低开发成本,应对复杂需求变更。其基本思想是让开发中心从编程转移到高级别抽象中去,通过模型转成代码或其他构件来驱动部分或全部的自动化开发。它主要为了解决软件的两个根本危机:复杂性和变更能力

    使用一定的建模标准(UML、MOF、XMI等)构建描述应用程序或集成系统的业务功能和行为的模型,这些模型独立于具体平台并且和实现具体业务功能和行为的特定技术代码分离,从而实现了业务和应用程序逻辑与底层平台技术的分离,这种分离也带来了应用程序的核心与技术变化周期的隔离。系统的业务部分和技术部分都可以各自进化而互不影响 - 业务逻辑响应业务需求,技术部分按业务需要利用新的技术开发。

    上图为MDA 结构示意图。最左侧为OMG提出的架构理论,其次是 MDA 的核心技术:MOF ( Meta Object Facility ,元对象设施)、 CWM (Common Warehouse Metamodel ,公共数据仓库元模型)和 UML . MDA 的主要工作就是要把基于这些技术建立的PIM 转换到不同的中间件平台上,得到对应的 PSM .PSM中给出的是目前主要针对的实现平台:CORBA 、 XML 、JAVA 、 Web Services 和 .NET .显然,随着技术的发展,这个列表将不断扩充。最后是基于PSM平台相关模型在公共服务及垂直领域等组件或应用中进行模型驱动开发。

    模型驱动软件开发,也可以成为MDA开发,就是基于UML进行软件开发的分析设计建模,然后通过所建模型生成开发代码框架,或者可运行代码。

    对比传统的软件开发过程,不是一上来就是编码,而是要先完成分析设计建模

    MDA提倡以模型为中心,设计模型驱动代码开发,理论、方法、工具都已经有支持的。

    4.png

    这种开发模式对开发人员的要求比较高,需要掌握UML建模规范,掌握软件开发中分析设计方法,掌握软件架构,这样才能很好的应用MDA模式去实现软件开发。

    模型驱动测试可以在软件开发周期的各个阶段中应用,包括需求分析、设计、实现和验证等阶段。在需求分析阶段,可以使用模型来建立系统的需求模型,以辅助需求验证和分析。在设计阶段,可以利用模型来生成测试用例,从而验证设计的正确性和完整性。在实现阶段,模型驱动测试可以帮助测试团队快速构建和执行测试,以验证软件实现是否符合规格和预期行为。在验证阶段,模型驱动测试可以与其他测试方法相结合,以确保软件的功能和性能达到用户期望的水平。


    模型驱动VS领域驱动

    • 焦点差异

      • DDD关注于深入理解业务领域并将业务模型贯穿于软件设计及开发的全过程;

      • MDD关注于通过高层次的抽象模型简化软件设计和自动化软件生产。

    • 方法论和工具

      • DDD是一套方法论,提供了一系列实践和模式帮助开发者构建响应复杂业务需求的软件系统;

      • MDD则更多依赖于工具和技术,通过模型和自动化工具来提高软件开发的效率和质量。

    • 实现方式

      • DDD通过团队成员之间的深入沟通、领域模型的创建和维护实现;

      • MDD则通过创建软件模型、使用特定工具自动转换模型为代码来实现。

    不难看出MDA说的是整体的软件架构设计使用的是模型驱动;而在软件开发的过程中,对不同领域的业务需求进行分析、抽象建模和技术框架分层所常用的分析方法就是DDD整个软件的开发活动就称之为MDD

    总之,领域驱动设计关注于业务领域的理解和建模,而模型驱动设计关注于技术实现和代码生成。两者在实际应用中可以相互结合,以实现更高效、可维护的软件系统。

    MDD-MDF

    整个的模型驱动开发的目的就是为了解决软件的复杂性和变更能力,从而达到软件编程工业化产出的目的。

    传统的瀑布式开发流程如下图,每一个需求的产生都需要进行需求分析、设计、编码、测试等一系列流程

    模型驱动框架的开发流程如下图

    对比上面两图可以了解到模型驱动的优势在于不用为每个需求定制化的编码,而是通过高度抽象化的模型映射到具体的业务元数据上来实现需求功能;这样大大减少了编码的重复工作,同时也提高了软件的可变更性。


    数据驱动

    数据驱动可以看作是由数据来决定。

    所谓的驱动本质上就是在某个抽象层次上进行解释运行。比如说,我们表达逻辑的时候需要执行判断和循环,如果在我们事先实现的函数中并没有直接表达具体什么时候判断以及什么时候循环,而是根据外部传入的某种数据来决定,那么这就看作是某种形式的数据驱动。

    数据驱动核心出发点是相对于程序逻辑,人类更擅长于处理数据

    很多设计思路背后的原理其实都是相通的,隐含在数据驱动编程背后的实现思想包括:

    • 控制复杂度。通过把程序逻辑的复杂度转移到人类更容易处理的数据中来,从而达到控制复杂度的目标。

    • 隔离变化。像上面的例子,每个消息处理的逻辑是不变的,但是消息可能是变化的,那就把容易变化的消息和不容易变化的逻辑分离。

    • 机制和策略的分离。和第二点很像,本书中很多地方提到了机制和策略。上例中,我的理解,机制就是消息的处理逻辑,策略就是不同的消息处理:

      v2-11ec670285cfea7620dbf4e2a7ddadfb_720w.webp


    使用数据驱动的前提,在于将页面内容抽象为数据表达。基于抽象后的数据,这些数据会发生怎样的变化、又是如何被改变的,这些便是数据驱动的关注点

    数据驱动和事件驱动的最大差异是开发的视角。

    • 事件驱动会关注于“操作”和“响应”,基于流程实现编码。

    • 数据驱动则会关注于“数据”和“数据的变化”,基于状态实现编码。


    基于数据模型编程

    • 基于Yang模型编程(DSL),YANG是一种语言,是用来建立数据模型的语言,可以通过定义业务数据模型,自动生成对应数据处理逻辑(比如参数校验,范围,存储方式,权限控制等),典型的数据驱动编程;

    • Linux内核DTS设备树模型,删除大量hardcode,精简内核驱动代码。

    • 基于xml,protobuf数据模型编程,界面显示,web配置逻辑,RPC微服务等;

    数据驱动思考

    • 它不是一个全新的编程模型:它只是一种设计思路,而且历史悠久,在unix/linux社区应用很多;

    • 它不同于面向对象设计中的数据:“数据驱动编程中,数据不但表示了某个对象的状态,实际上还定义了程序的流程;OO看重的是封装,而数据驱动编程看重的是编写尽可能少的代码。”

    • 数据压倒一切。如果选择了正确的数据结构并把一切组织的井井有条,正确的算法就不言自明。编程的核心是数据结构,而不是算法。——Rob Pike

    • 程序员束手无策,只有跳脱代码,直起腰,仔细思考数据才是最好的行动。表达式编程的精髓。——Fred Brooks

    • 数据比程序逻辑更易驾驭。尽可能把设计的复杂度从代码转移至数据是个好实践。——《unix编程艺术》作者。


    元数据驱动

    元数据架构侧重于元数据管理。

    在中文语境下,“元”字通常被解释为“基础的、原始的、本质的”,代表着元数据作为数据的基础属性和描述信息。它强调了元数据在数据管理和分析中的重要性和本质特征。

    在英文语境下,metadata一词中的“meta-”表示“关于、在…之后”等含义,强调了元数据是对数据的描述和说明信息。因此,英文中的“meta”与中文中的“元”不完全相同,但两者都指向元数据的重要作用和本质属性。

    • 比如图片的元数据:拍摄时间、拍摄地点、相机型号等等。

    • 比如音乐的 元数据:歌曲名称、演唱者、专辑封面等等。

    元数据是指从信息资源中抽取出来的用于说明其特征、内容的结构化的数据(如题名,版本、出版数据、相关说明,包括检索点等),用于组织、描述、检索、保存、管理信息和知识资源。

    比如,关于一本书(信息资源),我们在图书馆系统中检索可以得到如下信息

    乔布斯传图书元数据.png

    利用元数据来描述资源后,我们就可以用来做很多的事情。比如确定资源,为资源提供检索点,在不同系统之间进行数据交换。

    推荐阅读阮一峰老师的:https://www.ruanyifeng.com/blog/2007/03/metadata.html

    元数据驱动就是在设计架构时把复用细化到元数据级别,运行时根据元数据来处理数据,如对价格的范围进行校验。

    在元数据驱动的设计中,数据的处理细化到元数据级别,与具体的业务无关

    数值框模型和相应的业务规则

    元数据驱动就是这样解决了复用问题,提高了开发效率,甚至可以提供一个运营中台让运营人员自行修改元数据,从而减少开发工作量。

    Spring框架:在Java后端开发领域,Spring框架大量使用注解(一种元数据形式)来配置和管理对象依赖,比如@Autowired注解用于自动注入依赖,@Transactional用于声明事务管理等等。

    Entity Framework(EF):.NET平台的Entity Framework使用特定的数据注解来描述模型与数据库之间的映射关系,这些注解允许开发者以几乎纯粹的C#代码的形式来操作数据库。

    Angular中使用装饰器(Decorators)来定义元数据。例如,@Component装饰器用于定义Angular组件,@Injectable装饰器用于定义一个服务

    • 读取元数据:在Angular应用启动时,Angular框架会解析这些装饰器中定义的元数据,根据这些元数据创建应用的组件树、注入所需的服务等。

    • 应用元数据:基于解析出的元数据,Angular框架会动态地创建视图、绑定数据、监听事件等,从而实现响应式UI。

    通过元数据,程序能够在运行时根据这些描述信息来动态调整自身行为,提高了程序的灵活性和可扩展性。



    数据驱动VS元数据驱动

    数据驱动的强调利用数据来指导决策制定和行为。在数据驱动的系统中,操作和决策基于数据分析的结果进行,这意味着数据是推动所有主要决策和动作的中心。

    元数据驱动侧重于利用元数据来增强系统的灵活性和可配置性(重于使用元数据来定义或影响程序行为),实现快速适应新要求而无需重写代码。元数据是关于数据的数据,它描述了数据的结构、含义和管理信息。元数据驱动的系统通过使用元数据来驱动系统行为、配置和自定义能力,从而使系统更灵活、可扩展。


    xx驱动总结:


    从某种意义上说,所有的程序都是数据驱动的。因为二进制代码确实就是一种数据,它驱动通用的图灵机实现所有可能的计算(图灵完备)。只不过一般情况下我们说的数据驱动是通过自定义的某种形式的数据来驱动特定的业务逻辑(仅能解决某些特定业务问题的计算模型),而不是驱动通用的图灵机计算模型。每当我们通过一组函数隐式的定义一个特定的计算模型,它可以根据传入的参数数据执行不同的逻辑处理过程,而且这组参数数据可以脱离我们的函数被独立的理解(在语义层面构成某种独立性和完整性),就相当于引入一种新的数据驱动。而我们一般的开发都是面向通用图灵机模型,所以我们不说它是数据驱动而已。

    换句话说,数据驱动 = 领域驱动 = 元数据驱动 = 模型驱动 = DSL,这些概念的本质是一样的,本质上就是需要建立某种特定领域内的、非通用的逻辑模型而已。

    但是在实际使用场景中,这些概念所强调的重点也有所不同。

    • 模型驱动往往强调模型的技术中立性,同样的模型表达可以对应多种不同的具体实现。例如模型驱动架构(MDA)区分出了平台无关模型(PIM)和平台相关模型(PSM)。也有些场景会强调模型的可视化设计,模型可能被保存为二进制形式,无法被直接理解

    • DSL一般强调领域特定逻辑的文本表达形式可以直观的阅读、编写DSL文本,不一定会为DSL配备对应的可视化编辑工具。(Nop平台根据可逆计算原理,强调DSL文本和可视化编辑不过是同一模型信息的两种信息等价的展现形式,可以在两者之间自动建立双向可逆转换,自动根据某种设计器定义生成对应的可视化设计器,也就是说并不需要手工为每一个DSL都特殊编写对应的设计工具,这项工作可以统一实现,具体做法参见nop-idea-plugin插件)

    • 元数据驱动在目前的实践中一般只包含数据结构和数据类型定义。元数据号称是描述数据的数据,所以它往往被看作是程序语言中类型概念的一种扩展表达形式,例如数据库中表结构定义是针对表数据的元数据。很多的DSL都包含完整的逻辑函数定义以及自定义函数、外部函数库等逻辑抽象机制,而元数据的实践中一般这些动态逻辑的支持都比较弱。此外,将DSL解释为描述数据的数据也会让一般人感到困惑。

    • 领域驱动强调的是我们在业务表达时所使用的概念要尽量贴近用户所理解的领域概念,而不是程序员所熟悉的技术概念,类似于我们要定义一种针对当前业务领域的DSL(领域特定语言)。但是在实践中,真正定义一种概念完备的语言需要花费很高的成本,而且真正的语言要求具有丰富的语法规则,各类语法要素具有丰富的可组合模式,相对来说很少有人能够有能力进行组合模式的抽象。所以,在实践中,领域驱动中的所谓领域语言往往退化为一组领域专用的词汇表(术语表),然后这些概念的组合是通过少量流程函数以很模糊的方式进行串接,很少有人系统化的去考虑概念之间组合规则的完备性等。(所谓的语言是由词汇和语法组合规则来共同定义的,而领域驱动往往只有简单领域词汇和少量拍脑袋定义的服务函数)。

    • 数据驱动则是以数据为中心,通过接收事件触发和更新数据状态的方式来实现功能。数据驱动原则上包含元数据驱动、只不过在一般人的概念中程序是由程序员编写的,而数据是由客户录入的,是客户可以理解并且需要客户进行理解,并继而进行管理的。所以,数据驱动一般需要把数据整理成客户容易理解的形式,并且在操作层面尽量简化。



    参看文章:

    数据驱动开发和领域驱动开发有什么区别,如何选择? - canonical的回答 - 知乎

    一顿操作猛如虎 “模型驱动开发”了解一下 https://zhuanlan.zhihu.com/p/73609064












    转载本站文章《XX Driven:数据驱动/模型驱动/领域驱动/元数据驱动/DSL》,
    请注明出处:https://www.zhoulujun.cn/html/webfront/engineer/Architecture/9080.html