2.2 互联网架构作为最佳实践为何失效

如果把互联网架构比作社会主义,Oinone就是也要做有中国特色的社会主义,才能符合国情。

随着业务和生态的发展,企业对效率、性能、体验和智能化等方面的要求越来越高,但很多企业的系统面临着严重的系统架构落后和系统间割裂等问题,这些问题导致原有系统在业务发展下面临着效率和性能的双重挑战。与此同时,互联网平台的技术水平远远领先于传统企业系统,但是是否可以直接将互联网架构照搬到企业数字化转型中呢?显然,这是不合适的,因为互联网架构在企业数字化转型中面临着许多水土不服的问题。本章节将结合互联网中台架构的发展,分析这些问题的原因。

借鉴互联网中台理念

我们要先看互联网架构的发展,是如何一步步到今天提的中台架构概念的,每一步又解决了什么具体问题,我们以阿里架构变迁史为例来看下(如下图2-2所示):

2.2 互联网架构作为最佳实践为何失效

图2-2 阿里架构变迁史

在2009年,淘宝上线了五彩石项目,这标志着淘宝从单体应用向服务化应用的时代迈出了一步。那么,淘宝为什么要开发五彩石项目呢?因为当时淘宝面临两个非常严峻的问题,一个是性能问题,数据库连接不足,数据库成为了瓶颈;另一个是效率问题,当时淘宝有百余个研发人员,但核心系统只有一套测试、预发、线上环境,导致研发需求排队等待。在开始五彩石项目之前,淘宝还做了千岛湖项目,用来验证服务化架构的可行性,将用户中心独立出来。随后,淘宝开启了五彩石项目,目标是通过增加人力来提升效率,通过增加机器来提升性能。

随着淘宝的业务发展,他们又面临了一个问题:各个服务之间有很多重复的建设,效率低下。为了解决这个问题,淘宝开始从服务化转向平台化,并创立了“共享业务事业部”,将重复建设的公共业务分配给这个事业部,以避免成本浪费。这些公共业务包括商品平台、交易平台和结算平台等。平台化的目标是规避服务化没有规划导致的重复建设问题。

但是随着业务的快速发展,淘宝变成了一个拥有几十个事业部的巨型企业,而这带来了新的问题:效率问题。例如,如果需要在一个业务线上做出改动,需要与十几个平台进行沟通,这是非常低效的。同时,对于一个平台来说,需要面对来自不同事业部的需求,这需要平台研发人员具备理解和抽象所有业务线需求的能力,这让平台研发人员感觉回到了单体应用时代,所有的需求都要排队,即使增加人力也无法提高效率。这个问题主要表现在交易平台上。

为了解决这个问题,淘宝提出了中台的概念,中台是在一套规范下建立的,让具有专业技能的团队自主决策业务系统发展的平台。中台的目标是弱化平台的业务特性,提供通用能力。简而言之,就是将“共享业务”中的“业务”两个字去掉,只提供通用能力的平台

我们将每个阶段的核心目标总结为一句话:

  1. 从单体到服务:通过增加人员和机器来提高效率和性能;

  2. 从服务化到平台化:解决服务化阶段因缺乏规划而导致的重复建设问题;

  3. 平台化到中台化:在一套规范下,让各业务团队自行决定业务系统发展,适用于多个业务线或多个场景应用的独立发展。

类似地,在企业数字化转型过程中,也面临着类似的问题:

  1. 随着企业业务在线化,对系统性能和稳定性提出了更高的要求,但由于内部系统之间的割裂,导致很多重复建设。因此,我们需要进行服务化和平台化;

  2. 没有一个供应商能够解决企业所有的商业场景问题,所以需要多个供应商共同参与。我们可以将供应商类比为各业务线,在一套规范下让供应商或业务线自行决定业务系统的发展。

然而,阿里的中台架构方案并不能直接照搬到企业中。因为阿里的中台架构采用了平台共建模式,即让业务线基于平台设计的规范共同开发。这本质上还是平台主导模式,对企业来说历史包袱较大。在企业中,让不同背景的研发一起共建交易或商品平台是非常复杂的事情。平台化已经足够复杂,再加上共建会导致企业架构的负载过重,这对企业来说就不再是赋能,而是“内耗”。

互联网中台架构在企业实践中遇到的问题

在1.3《Oinone的生态思考》一文中,《与中台的渊源》部分提到,在阿里云为企业提供数字化项目时,客户经常会对以下三个问题提出质疑,这些问题非常突出:

1我们听说你们具备敏捷响应能力,但为什么改动需求如此缓慢?不仅所需时间更长,而且成本更高?

2我们听说你们有能力中心,但为什么当我们引入新供应商或开发新场景时,前期建立的能力中心无法支持我们?

3我们听说你们的性能很好,但为什么我们需要投入更多的物理资源来支持项目?

在探讨互联网架构的适用性时,我想提出以下两个问题:

1企业应用程序的性能问题是否与互联网平台公司遇到的性能问题相同?

2企业应用程序的开发效率问题是否与互联网平台公司遇到的效率问题相同?

通过比较企业和互联网之间的差异,我们可以了解水土不服的核心原因。

企业 互联网
企业IT组织能力无法与数字化转型的速度匹配,缺乏足够的人才支持。为了提高开发效率,企业需要寻找工具和技术来降低开发难度,同时提高个人开发效率 互联网企业拥有众多优秀的人才,需要解决团队协作和知识共享的问题,即协同开发的效率。
企业无法制定并主导技术规范,这导致了能力复用的不足。为了提高效率和减少开发成本,企业需要建立统一的技术规范和标准,以便能力复用和组织协同。 互联网企业可以自定义技术规范,因此能力复用更易于保障。
企业往往当前业务量相对小,期望数字化建设能打动业务发展,对业务发展的预期比较高,所以企业的诉求是即满足当下成本效应又能兼顾未来对发展预期 互联网企业起步时的系统目标负载就高,通常会忽略资源起步门槛的问题,当然也可以通过自动扩容、云计算等方式来解决初期的负载问题。

表2-1从企业与互联网的对比,看水土不服的核心原因

我们可以看到企业和互联网架构在很多方面存在着不同的需求和问题。因此,在提供数字化服务时,Oinone需要注意与企业的组织能力进行匹配,并根据企业自身的特性来提供在线化的服务能力。这就像在社会主义制度下需要有中国特色一样,Oinone也需要有适合中国企业的特色。

Oinone社区 作者:史, 昂原创文章,如若转载,请注明出处:https://doc.oinone.top/oio4/9217.html

访问Oinone官网:https://www.oinone.top获取数式Oinone低代码应用平台体验

(0)
史, 昂的头像史, 昂数式管理员
上一篇 2024年5月23日 am10:05
下一篇 2024年5月23日 am10:07

相关推荐

  • 4.1.8 函数之事务管理

    一、事务管理介绍 函数Function支持事务字段为isTransaction(默认为false),事务传播行为propagationBehavior(默认PROPAGATION_SUPPORTS),事务隔离级别isolationLevel(默认使用数据库默认的事务隔离级别),所以不会默认为函数添加事务。另外事务配置提供全局配置。 平台事务管理兼容Spring声明式与编程式事务,支持多数据源事务管理。事务管理中多数据源嵌套独立事务,不会造成死锁风险。使用多数据源或分表操作,不会导致脏读。如果需要多数据源分布式事务,请使用PamirsTransational分布式事务管理方案(@PamirsTransational(enableXa=true))。分布式事务一般用于量小的跨模块配置管理场景 使用方式 声明式事务,使用@PamirsTransactional注解在需要事务管理的类或方法上标注。在非无代码场景下,与@Transactional注解功能一致。 编程式事务,使用PamirsTransactionTemplate即可。在非无代码场景下,与TransactionTemplate功能一致。 配置式事务,使用TxConfig模型在模块安装时初始化存储事务配置数据。 事务特性 原子性 (atomicity):强调事务的不可分割. 一致性 (consistency):事务的执行的前后数据的完整性保持一致. 隔离性 (isolation):一个事务执行的过程中,不应该受到其他事务的干扰 持久性(durability) :事务一旦结束,数据就持久到数据库 事务隔离级别 事务隔离级别指的是一个事务对数据的修改与另一个并行的事务的隔离程度,当多个事务同时访问相同数据时,如果没有采取必要的隔离机制,就可能发生以下问题: 问题 描述 脏读 一个事务读到另一个事务未提交的更新数据,所谓脏读,就是指事务A读到了事务B还没有提交的数据,比如银行取钱,事务A开启事务,此时切换到事务B,事务B开启事务–>取走100元,此时切换回事务A,事务A读取的肯定是数据库里面的原始数据,因为事务B取走了100块钱,并没有提交,数据库里面的账务余额肯定还是原始余额,这就是脏读 不可重复读 在一个事务里面的操作中发现了未被操作的数据 比方说在同一个事务中先后执行两条一模一样的select语句,期间在此次事务中没有执行过任何DDL语句,但先后得到的结果不一致,这就是不可重复读 幻读 是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。 同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象 发生了幻觉一样。 表4-1-8-1 事务隔离级别 Pamirs(Spring)支持的隔离级别 隔离级别 描述 DEFAULT 使用数据库本身使用的隔离级别 ORACLE(读已提交) MySQL(可重复读) READ_UNCOMITTED 读未提交(脏读)最低的隔离级别,一切皆有可能。 READ_COMMITED 读已提交,ORACLE默认隔离级别,有不可重复读以及幻读风险。 REPEATABLE_READ 可重复读,解决不可重复读的隔离级别,但还是有幻读风险。 SERLALIZABLE 串行化,最高的事务隔离级别,不管多少事务,挨个运行完一个事务的所有子事务之后才可以执行另外一个事务里面的所有子事务,这样就解决了脏读、不可重复读和幻读的问题了 表4-1-8-2 隔离级别与描述 隔离级别 脏读可能性 不可重复读可能性 幻读可能性 加锁度 READ_UNCOMITTED 是 是 是 否 READ_COMMITED 否 是 是 否 REPEATABLE_READ 否 否 是 否 SERLALIZABLE 否 否 否 是 表4-1-8-3 隔离级别说明表 事务的传播行为 保证同一个事务中 PROPAGATION_REQUIRED 支持当前事务,如果不存在 就新建一个(默认) PROPAGATION_SUPPORTS 支持当前事务,如果不存在,就不使用事务 PROPAGATION_MANDATORY 支持当前事务,如果不存在,抛出异常 保证没有在同一个事务中 PROPAGATION_REQUIRES_NEW 如果有事务存在,挂起当前事务,创建一个新的事务 PROPAGATION_NOT_SUPPORTED 以非事务方式运行,如果有事务存在,挂起当前事务 PROPAGATION_NEVER 以非事务方式运行,如果有事务存在,抛出异常 PROPAGATION_NESTED 如果当前事务存在,则嵌套事务执行 A中嵌套B事务,嵌套PROPAGATION_REQUIRES_NEW方法勿与A在同类中。 异常状态 PROPAGATION_REQUIRES_NEW (两个独立事务) PROPAGATION_NESTED (B的事务嵌套在A的事务中) PROPAGATION_REQUIRED (同一个事务) A抛异常 B正常 A回滚,B正常提交 A与B一起回滚 A与B一起回滚 A正常 B抛异常 1.如果A中捕获B的异常,并没有继续向上抛异常,则B先回滚,A再正常提交; 2.如果A未捕获B的异常,默认则会将B的异常向上抛,则B先回滚,A再回滚 B先回滚,A再正常提交 A与B一起回滚 A抛异常B抛异常 B先回滚,A再回滚 A与B一起回滚 A与B一起回滚 A正常 B正常 B先提交,A再提交 A与B一起提交 A与B一起提交 表4-1-8-4 事务传播行为 二、声明式事务(举例) Step1 修改PetShopBatchUpdateAction 用@PamirsTransactional或者@Transactional注解来声明事务,PamirsTransactional跟Spring的Transactional区别在于PamirsTransactional支持多库事务,但此多库事务为非严格的分布式多库事务,之所以选择这个方案,原因如下 a. 不损害任何性能。 b. 事务保障率超过4个9 c. 经过阿里的大厂验证,特别是在阿里的结算平台中得到了很好的验证 @PamirsTransactional更多配置项请详见4.1.7【函数之元数据详解】一文,自己多试试。同时@PamirsTransactional百分百兼容@Transactional @Action(displayName = "确定",bindingType = ViewTypeEnum.FORM,contextType = ActionContextTypeEnum.SINGLE) @PamirsTransactional //@Transactional public PetShopBatchUpdate conform(PetShopBatchUpdate data){ if(data.getPetShopList() == null || data.getPetShopList().size()==0){ throw PamirsException.construct(DemoExpEnumerate.PET_SHOP_BATCH_UPDATE_SHOPLIST_IS_NULL).errThrow(); } List<PetShopProxy> proxyList = data.getPetShopList(); for(PetShopProxy petShopProxy:proxyList){ petShopProxy.setDataStatus(data.getDataStatus()); } new PetShopProxy().updateBatch(proxyList); throw PamirsException.construct(DemoExpEnumerate.SYSTEM_ERROR).errThrow(); // return data; } 图4-1-8-1 修改PetShopBatchUpdateAction Step2 重启看效果 进入店铺管理列表页,选择记录点击【批量更新数据状态】按钮,修改记录的数据状态为【未启用】,提交看效果。期望效果为:提示系统异常,数据修改失败 图4-1-8-2 数据状态显示已启用 图4-1-8-3 批量更新数据状态…

    2024年5月23日
    1.1K00
  • 模型

    1. 模型介绍 Oinone低代码设计器是采用模型驱动的方式来设计应用,数据、数据都在模型,在模型设计器的模型管理模块,通过可视化配置的方式为用户提供快速设计模型的功能。 模型是对应用中所需要描述的实体进行必要的简化,并用适当的变现形式或规则把它的主要特征描述出来所得到的系统模仿品。模型由元信息、字段、数据管理器和自定义函数构成。 2. 操作模式 为了满足有无研发背景知识的不同用户使用需求,在模型设计器中,支持切换操作模式,包含专家模式和经典模式。经典模式功能基础且完善,操作交互简单易理解,适用于非研发用户;专家模式下模型的设计能力更高,有经典模式下的所有功能,相比于经典模式,功能更多,适用于一般有研发知识基础的用户。 比如在添加模型时,经典模式下可以创建的模型类型有:存储模型、传输模型,专家模式下,在此基础上还可以创建抽象模型和代理模型。 3. 分组管理 当模型过多时,可以自定义添加15个分组,将模型进行归类管理。点击「全部」展开所有分组,展开后,分组右侧可以管理分组。 3.1 管理分组 展开分组后,点击「管理分组」,出现弹窗,在弹窗中可以修改分组名称、添加分组、删除分组。 3.2 添加分组 操作「+模型分组」,可以直接输入分组名称后回车以添加一个新分组,或快捷选择其他应用使用的分组。最多添加15个分组。 3.3 修改分组 双击分组标签,即可对已有分组进行名称的修改。若分组在其他应用也使用,则在其他应用内,该分组名称也同步变化。 3.4 删除分组 点击分组标签右侧的“X”按钮,即为删除分组,但分组下如果有模型或者分组有被其他应用使用,则分组无法删除。 4. 模型管理 4.1 管理模式 在模型管理中,有两种管理模式,分别是图管理模式和列表管理模式。(下文简称图模式、表模式) 可以根据不同的使用场景,切换管理模式: 图管理模式下,模型操作区展示当前模型和与当前模型有直接关联关系的模型关系图,可以在关注模型关联关系时使用; 列表管理模式下,展示更多更详细的模型信息、字段信息,且左侧可快速切换不同模型,可以在关注模型基础信息时使用; 4.2 筛选 4.2.1 图模式筛选 在图模式下,顶部进行应用/模块、模型类型、分组的筛选,依此向下可以搜索或展开当前筛选条件下的模型列表,切换模型后在模型操作区将展示另一模型的信息。为了更大程度保留图模式下的模型展示区域,模型列表默认不会展示,点击搜索行的任意筛选项,即可展开模型列表。 4.2.2 表模式筛选 在表模式下,顶部和图模式一致,都是应用/模块、模型类型、分组的筛选,模型操作区左侧会直接展示模型列表。 4.2.3 重置筛选 图模式和表模式下,右侧都有重置筛选的选项。如果点击“重置筛选”按钮,则将筛选栏恢复到进入页面时的选项。 4.3 模型分组 模型新增成功后,默认无所属分组,每个模型可以设置所属分组,设置后通过分组进行筛选时,模型即展示在所属分组下。 4.3.1 图模式设置分组 图模式下为模型设置分组,点击模型信息顶部第一个「模型分组」操作图标,点击后设置或修改分组。 4.3.2 表模式设置分组 表模式下为模型设置分组,点击模型信息右上角第一个操作「模型分组」,点击后设置或修改分组。 4.4 继承关系 查看模型的继承关系,点击展示跟当前模型有父子关系的模型关系图。 页面初始状态只展示一层父模型与一层子模型,父模型顶部和子模型底部有“展示更多”按钮,点击展示更多再向上或向下加载一层。连线的顶部展示“收起”按钮,点击“收起”按钮收起子模型。 点击非当前模型,会打开新窗口,链接跳转到点击模型的模型设计器页面,新页面满足点击模型的筛选条件; 支持设置显示比例,缩放模型关系图; 支持最大化全屏展示。 4.4.1 图模式继承关系 4.4.2 表模式继承关系 4.5 查看引用关系 当删除模型时,如果模型有被其他设计器引用使用,则无法被删除。删除失败时会弹出“该模型仍在使用中,无法删除模型”的提示,并且可以点击「查看模型引用」,进而展示引用的详细信息。 引用包括五种:模型引用、页面引用、逻辑引用、流程引用、图表引用。 每种关系通过列表展示,列表项为链接(链接到对应的设计页面),内容为对应名称。例如,存在引用关系的流程的列表项显示的是流程的名称。列表项链接到对应流程的设计页面。 4.6 导入模型 导入模型的添加模型的一种方式,下载导入模板后在Excel中按照规则填写模型信息,成功导入后即添加模型成功。 点击「导入模型」后,可在弹窗中下载导入模板、上传导入文件、查看导入说明。 4.6.1 下载导入模板 下载导入模板时,会根据当前的操作模式不同,下载到的模板也不同。 在经典模型下,下载的导入模板中需要填写的模型信息基础、数量少、易懂。 在专家模型下,下载的导入模板中需要填写的模型信息丰富、数量多、专业。 4.6.2 查看导入说明 导入说明中描述了导入模板中各项内容的含义、填写规则等,有助于用户正确填写导入文件。在经典模式或专家模式下点击「导入说明」后,分别弹出两种操作模式下的导入说明。 4.6.3 导入上传 导入文件正确填写后,在弹窗中选择Excel文件,或将Excel直接拖入弹窗中的文件上传区域。Excel文件仅支持三种格式:.xlsx .xls .xlsm。 4.7 添加模型 点击「添加模型」,出现模型信息填写的弹窗,弹窗中包括:模型名称、模型类型、父模型。填写并保存成功后,模型即创建成功。 4.7.1 模型类型 专家模式下支持创建4种类型的模型:存储模型、传输模型、抽象模型、代理模型;经典模式下支持创建2种类型的模型:存储模型、传输模型。 存储模型:用于存储数据的模型,生成前后端交互协议、数据表、数据构造器和数据管理器。 抽象模型:用于配置多个子模型的公用字段和函数的模型,不会生成前后端交互协议、数据表、数据构造器和数据管理器。 传输模型:用于数据传输的模型,生成前后端交互协议和数据构造器,不生成数据表和数据管理器。 代理模型:用于以代理的方式扩展存储模型的模型,可以在存储模型的基础上增加传输字段和函数,与被代理的存储模型共用相同的数据管理器。 4.7.2 选择父模型 添加模型时,需要选择父模型,其中,经典模式下,无需且不展示父模型;专家模式下,必须选择父模型。 存储模型的父模型,默认是“基础存储模型”,可选项为可见的抽象模型和存储模型。 传输模型的父模型,默认是“基础存储模型”,可选项为可见的传输模型。 抽象模型的父模型,默认是“基础存储模型”,可选项为可见的抽象模型。 代理模型的父模型,无默认值,可选项为可见的存储模型和代理模型。 4.8 编辑模型 创建成功的模型,可以对其进行编辑,但只有部分信息支持编辑。 4.8.1 图模式编辑模型 图模式下,点击模型标题右侧的「编辑模型」按钮,即可在右侧弹出的抽屉中编辑模型信息。 4.8.2 表模式编辑模型 表模式下,点击模型信息标题右侧的「编辑模型」按钮,下方模型信息中可以被编辑修改的字段即由只读变为可编辑。 4.9 隐藏/可见模型 对于暂时不使用的模型,可以进行隐藏(隐藏后可再设置可见)的操作。 在其他设计器需要选择模型使用时,隐藏的模型将不被展示。对隐藏的模型再次操作可见后,即可选择到。 4.9.1 图模式隐藏/可见模型 图模式下,展开模型列表,模型列表中每个模型所在行的右侧,可点击隐藏/可见图标,以隐藏/可见该模型。 可见的模型常规展示,无特殊标识;隐藏后的模型在列表中将置灰展示。 4.9.1 表模式隐藏/可见模型 表模式下,模型信息左侧的模型列表中每个模型所在行的右侧,可点击隐藏/可见图标,以隐藏/可见该模型。 可见的模型常规展示,无特殊标识;隐藏后的模型在列表中将置灰展示。 4.10 删除模型 不再使用模型可以进行删除,删除时需要确保模型没有被其他设计器引用。删除成功后的模型将不在列表展示,且不可恢复,请谨慎操作。 4.10.1 图模式删除模型 图模式下,展开模型列表,模型列表中每个模型所在行的右侧,可点击删除图标,以删除该模型。 4.10.2 表模式删除模型 表模式下,模型信息左侧的模型列表中每个模型所在行的右侧,可点击删除图标,以删除该模型。 4.10.3 存在引用关系 如果删除的模型存在引用关系,则无法删除,并提示模型仍在使用。点击提示中的「查看模型引用」,可以查看这个模型引用情况。 5. 字段管理 在模型中,可以对字段进行增删改查等基础管理操作。 5.1 添加字段 每个模型中可以添加多个字段,手动添加的字段都为自定义字段。点击「添加字段」,右侧出现字段信息填写的抽屉,抽屉中包括:字段名称、字段业务类型、存储类型、长度(部分业务类型的字段无长度设置)。填写并保存成功后,字段即创建成功。 5.1.1 图模式添加字段 5.1.2 表模式添加字段 5.1.3 字段业务类型 添加字段时,支持设置16种基础类型的字段、支持设置4种关系类型字段。 基础类型:用户ID、整数、浮点数、金额、布尔型、文本、多行文本、富文本、日期时间、年份、日期、时间、数据字典、键值对、手机、邮箱; 字段为数据字典时需要选择一个数据字典。 关系类型:一对一、多对一、一对多、多对多 字段为关系类型字段时需要选择关联的模型。 5.1.4 多值字段 多值字段表示该字段可以存储或传输多个该业务类型的数据,非多值字段只能存储或传输单个该业务类型的数据。 5.1.5 存储类型 设置字段的存储类型:存储字段、传输字段 存储字段:用于查询和存储字段 传输字段:仅用于数据的组装与存储 5.2 编辑字段 创建成功的字段,可以对其进行编辑,但只有部分信息支持编辑。 字段长度和精度只能由小往大改,不能由大往小改。 关联关系的关联模型、关联字段、关系字段、中间模型,中间关系字段、中间关联字段、支持关联查询不可修改。 5.2.1 图模式编辑字段 图模式下,点击字段列表所在行右侧的「编辑字段」按钮,即可在右侧弹出的抽屉中编辑字段信息。 5.2.2 表模式编辑字段 表模式下,点击模型信息标题右侧的「编辑模型」按钮,下方模型中的字段都可以被展开编辑。 5.3 隐藏/可见字段 对于暂时不使用的字段,可以进行隐藏(隐藏后可再设置可见)的操作。 在其他设计器需要选择字段使用时,隐藏的字段将不被展示。对隐藏的字段再次操作可见后,即可选择到。 5.3.1 表模式隐藏/可见字段 表模式下,编辑模型时,字段所在行右侧可以操作隐藏/可见。 可见的字段常规展示,无特殊标识;隐藏的字段在列表中将置灰展示。 5.4 删除字段…

    2024年6月20日
    1.5K00
  • 3.3.2 模型的类型

    本文会介绍不同类型模型以及其简单的应用场景,方便大家理解不同类型模型的用途 模型分为元模型和业务模型。元数据是指描述应用程序运行所必需的数据、规则和逻辑的数据集;元模型是指用于描述内核元数据的一套模式集合;业务模型是指用于描述业务应用元数据的一套模式集合。 元模型分为模块域、模型域和函数域三个域。域的划分规则是根据元模型定义数据关联关系的离散性来判断,离散程度越小越聚集到一个域。在4.1.4【模块元数据详解】一文中介绍的ModuleDefinition就是元模型。而我们在开发中涉及的就是业务模型 一、模型类型 抽象模型:往往是提供公共能力和字段的模型,它本身不会直接用于构建协议和基础设施(如表结构等)。 传输模型:用于表现层和应用层之间的数据交互,本身不会存储,没有默认的数据管理器,只有数据构造器。 存储模型:存储模型用于定义数据表结构和数据的增删改查(数据管理器)功能,是直接与连接器进行交互的数据容器。 代理模型:用于代理存储模型的数据管理器能力的同时,扩展出非存储数据信息的交互功能的模型。 二、模型定义种类 模型定义就是模型描述,不同定义类型,代表计算描述模型的元数据的规则不同 静态模型定义:模型元数据不持久化、不进行模型定义的计算(默认值、主键、继承、关联关系) 静态计算模型定义:模型元数据不持久化但初始化时进行模型定义计算获得最终的模型定义 动态模型定义:模型元数据持久化且初始化时进行模型定义计算获得最终的模型定义 静态模型定义需要使用@Model.Static进行注解;静态计算模型定义使用@Model.Static(compute=true)进行注解;动态模型定义不注解@Model.Static注解。 三、安装与更新 使用@Model.model来配置模型的不可变更编码。模型一旦安装,无法在对该模型编码值进行修改,之后的模型配置更新会依据该编码进行查找并更新;如果仍然修改该注解的配置值,则系统会将该模型识别为新模型,存储模型会创建新的数据库表,而原表将会rename为废弃表。 如果模型配置了@Base注解,表明在【oinone的设计器】中该模型配置不可变更;如果字段配置了@Base注解,表明在【oinone的设计器】中该字段配置不可变更。 四、基础配置 模型基类 所有的模型都需要继承以下模型中的一种,来表明模型的类型,同时继承以下模型的默认数据管理器(详见3.3.3模型的数据管理器一节)。 继承BaseModel,构建存储模型,默认无id属性。 继承BaseRelation,构建多对多关系模型,默认无id属性。 继承TransientModel,构建临时模型(传输模型),临时模型没有数据管理器,也没有id属性。 继承EnhanceModel,构建数据源为ElasticSearch的增强模型。 快捷继承 继承IdModel,构建主键为id的模型。继承IdModel的模型会数据管理器会增加queryById方法(根据id查询单条记录) 继承CodeModel,构建带有唯一编码code的主键为id的模型。可以使用@Model.Code注解配置编码生成规则。也可以直接覆盖CodeModel的generateCode方法或者自定义新增的前置扩展点自定义编码生成逻辑。继承CodeModel的模型会数据管理器会增加queryByCode方法(根据唯一编码查询单条记录) 继承VersionModel,构建带有乐观锁,唯一编码code且主键为id的模型。 继承IdRelation,构建主键为id的多对多关系模型。 模型继承关系图 图3-3-2-1 模型继承关系图 AbstractModel抽象基类是包含createDate创建时间、writeDate更新时间、createUid创建用户ID、writeUid更新用户ID、aggs聚合结果和activePks批量主键列表等基础字段的抽象模型。 TransientModel传输模型抽象基类是所有传输模型的基类,传输模型不存储,没有数据管理器。 TransientRelation传输关系模型是所有传输关系模型的基类,传输关系模型不存储,用于承载多对多关系,没有数据管理器。 BaseModel存储模型基类提供数据管理器功能,数据模型主键可以不是ID。 IdModel带id模型抽象基类,在BaseModel数据管理器基础之上提供根据ID查询、更新、删除数据的功能。 BaseRelation关系模型抽象基类用于承载多对多关系,是多对多关系的中间模型,数据模型主键可以不是ID。 IdRelation带id关系模型抽象基类,在BaseRelation数据管理器基础之上提供根据ID查询、更新、删除数据的功能。 CodeModel带code模型抽象基类,提供按配置生成业务唯一编码功能,根据code查询、更新、删除数据的功能。 EnhanceModel增强模型,提供全文检索能力。此模型会在4.1.25【框架之搜索引擎】一文中展开介绍。 五、抽象模型(举例) 抽象模型本身不会直接用于构建协议和基础设施(如表结构等),而是通过继承的机制供子模型复用其字段和函数。子模型可以是所有类型的模型。 比如demo模块要管理的一些公共模型字段,我们可以建一个AbstractDemoIdModel和AbstractDemoCodeModel,demo模块中的实体模型就可以继承它们。我们来为demo模块的模型统一增加一个数据状态这么一个字段,用做数据的生效与失效管理。 Step1 引入DataStatusEnum类 pamirs-demo-api的pom.xml包增加依赖,便于引入DataStatusEnum类,当然也可以自己建,这里只是oinone提供了统一的数据记录状态的枚举,以及相应的通用方法,这边就直接引入 <dependency> <groupId>pro.shushi.pamirs.core</groupId> <artifactId>pamirs-core-common</artifactId> </dependency> 图3-3-2-2 引入通用类库 Step2 修改DemoModule DataStatusEnum枚举类本身也会做为数据字典,以元数据的方式被管理起来,当一个模块依赖另一个模块的元数据相关对象,则需要改模块的模块依赖定义。为DemoModule增加CommonModule的依赖注解 package pro.shushi.pamirs.demo.api; import org.springframework.stereotype.Component; import pro.shushi.pamirs.boot.base.ux.annotation.action.UxRoute; import pro.shushi.pamirs.boot.base.ux.annotation.navigator.UxHomepage; import pro.shushi.pamirs.core.common.CommonModule; import pro.shushi.pamirs.demo.api.model.PetShop; import pro.shushi.pamirs.meta.annotation.Module; import pro.shushi.pamirs.meta.base.PamirsModule; import pro.shushi.pamirs.meta.common.constants.ModuleConstants; @Component @Module( name = DemoModule.MODULE_NAME, displayName = "oinoneDemo工程", version = "1.0.0", dependencies = {ModuleConstants.MODULE_BASE, CommonModule.MODULE_MODULE} ) @Module.module(DemoModule.MODULE_MODULE) @Module.Advanced(selfBuilt = true, application = true) @UxHomepage(@UxRoute(PetShop.MODEL_MODEL)) public class DemoModule implements PamirsModule { public static final String MODULE_MODULE = "demo_core"; public static final String MODULE_NAME = "DemoCore"; @Override public String[] packagePrefix() { return new String[]{ "pro.shushi.pamirs.demo"}; } } 图3-3-2-3 定义模块依赖 Step3 新建AbstractDemoCodeModel和AbstractDemoIdModel 并新增AbstractDemoIdModel和AbstractDemoCodeModel分别继承IdModel和CodeModel,实现IDataStatus接口不是必须的,刚好DataStatus有配套的通用逻辑,暂时也先加进去,具体使用会在本文的【代理模型】这段介绍 package pro.shushi.pamirs.demo.api.model; import pro.shushi.pamirs.core.common.behavior.IDataStatus; import pro.shushi.pamirs.core.common.enmu.DataStatusEnum; import pro.shushi.pamirs.meta.annotation.Field; import pro.shushi.pamirs.meta.annotation.Model; import pro.shushi.pamirs.meta.annotation.sys.Base; import pro.shushi.pamirs.meta.base.common.CodeModel; import pro.shushi.pamirs.meta.enmu.ModelTypeEnum; @Base @Model.model(AbstractDemoCodeModel.MODEL_MODEL) @Model.Advanced(type = ModelTypeEnum.ABSTRACT) @Model(displayName = "AbstractDemoCodeModel") public abstract class AbstractDemoCodeModel extends CodeModel implements IDataStatus { public static final String MODEL_MODEL="demo.AbstractDemoCodeModel"; @Base @Field.Enum @Field(displayName = "数据状态",defaultValue = "DISABLED",required =…

    2024年5月23日
    1.7K00
  • 4.1.15 框架之网关协议

    一、多端协议 协议内容格式 请求头 头信息 headerMap "sec-fetch-mode" -> "cors" "content-length" -> "482" "sec-fetch-site" -> "none" "accept-language" -> "zh-CN,zh;q=0.9" "cookie" -> "pamirs_uc_session_id=241af6a1dbba41a4b35afc96ddf15915" "origin" -> "chrome-extension://flnheeellpciglgpaodhkhmapeljopja" "accept" -> "application/json" "host" -> "127.0.0.1:8090" "connection" -> "keep-alive" "content-type" -> "application/json" "accept-encoding" -> "gzip, deflate, br" "user-agent" -> "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.192 Safari/537.36" "sec-fetch-dest" -> "empty" 图4-1-15-1 头信息 headerMap 请求地址 requestUrl 例如 http://127.0.0.1:8090/pamirs/DemoCore?scene=redirectListPage HTTP参数键值对 parameterMap url中queryString在服务端最终会转化为参数键值对。 请求体格式 请求体格式采用GraphQL协议。请求体格式分为API请求和上下文变量。以商品的test接口为例,请求格式如下。 API请求格式 query{ petShopProxyQuery { queryPage(page: {currentPage: 1, size: 1}, queryWrapper: {rsql: "(1==1)"}) { content { income id code creater { id nickname } relatedShopName shopName petTalents { id name } items { id itemName } } size totalPages totalElements } } } 图4-1-15-2 API请求格式 上下文变量 variables 请求策略requestStrategy 名称 类型 说明 checkStrategy CheckStrategyEnum 校验策略:RETURN_WHEN_COMPLETED -?全部校验完成再返回结果RETURN_WHEN_ERROR -?校验错误即返回结果 msgLevel InformationLevelEnum 消息级别:DEBUG("debug", "调试", "调试"),INFO("info", "信息", "信息"),WARN("warn", "警告", "警告"),SUCCESS("success", "成功", "成功"),ERROR("error", "错误", "错误")不设置,则只返回错误消息;上方消息级别清单,越往下级别越高。只有消息的级别高于或等于该设定级别才返回,否则会被过滤。 onlyValidate Boolean 只校验不提交数据 表4-1-15-1 请求策略requestStrategy 上下文变量式例如下。 { "requestStrategy": { "checkStrategy": "RETURN_WHEN_COMPLETED", "msgLevel":"INFO" } } 图4-1-15-3 上下文变量式例 响应体格式 协议响应内容包括data、extensions和errors三部分,extensions和errors是可缺省的。data部分为业务数据返回值。应用业务层可以在extensions中添加API返回值之外的扩展信息。extensions中包含success、messages和extra三部分,success标识请求是否成功。如果业务正确处理并返回,则errors部分为空;如果业务处理返回失败,则将错误信息添加到errors中。 正确响应格式示例如下。 { "data": { "petShopProxyQuery": { "queryPage": { "content": [ { "id": "246675081504233477", "creater": { "id": "10001" }, "relatedShopName": "oinone宠物店铺001", "shopName": "oinone宠物店铺001", "petTalents": […

    Oinone 7天入门到精通 2024年5月23日
    1.1K00
  • 2.1 数字化时代软件业的另一个本质变化

    随着企业从信息化向数字化转变,软件公司提供的产品也由传统的企业管理软件向企业商业支撑软件发展。这一变化带来了许多技术上的挑战和机遇。在之前的章节中,我们提到企业的视角已经从内部管理转向业务在线和生态在线协同,这也带来了一系列新的需求。但是,我们常常会忽视这一变化所带来的对系统要求的变化。在本章中,我们将探讨这些技术上的变化,以及这些变化所带来的机遇和挑战。 图2-1 从信息化到数字化软件本质变化 在信息化时代,企业的业务围绕着内部管理效率展开,借鉴国外优秀的管理经验,企业将其管理流程固化下来,典型的例子是ERP项目。这类项目上线后往往长期稳定,不轻易更改,因此信息化时代软件的技术流派侧重于通过模型对业务进行全面支持。例如,SAP具有丰富的配置能力,将已有企业管理思想抽象到极致。其功能基本上可以通过配置来实现,因此其模型设计特别复杂。但是,我们也应该清楚地了解到,配置是面向已知问题的。在数字化时代,创新和业务迭代速度非常快,这种方法可能就不太适合了。我们知道,模型抽象是在设计时具有前瞻性的,一旦不适合,修改起来就会异常困难。 随着数字化时代的到来,企业主的关注点已经从单一企业内部管理转变为了围绕企业上下游价值链的协同展开。这种变化给企业信息化系统提出了更高的要求,例如业务需求的响应速度、系统性能和用户体验等方面。现在,企业对软件不仅是管理需求的承载,更是业务在线化的承载。传统的重模型设计软件模式已经不再适用,因为业务本身不断创新和变化。因此,数字化时代需要新的软件技术流派,这种流派必须是轻模型加上低代码技术的结合体。通过模型抽象80%的通用场景,剩余的20%个性化需求可以通过技术手段来完成。这样的设计可以让每家企业的研发人员轻松理解模型,而不像ERP模型那样异常复杂,无法进行修改。此外,配合低代码技术可以快速研发和上线。如果说配置化是面向已知问题的,那么低代码就是面向未知问题设计的。虽然低代码的概念可以追溯到上个世纪80年代,当时是为了满足企业内部部门之间有协同需求,但又没有专业软件支撑,定制化开发又不划算的辅助场景。但现在它的核心原因是企业数字化的核心场景不稳定,变化很快,每家企业都有强烈的个性化需求。因此,低代码成为解决这些问题的核心手段,数字化时代的低代码需要具备处理复杂场景的能力,而不仅仅是围绕着内部管理展开。 企业在数字化转型的过程中需要考虑到不仅是成熟的全链路业务解决方案,还要应对数字化场景的快速变化和持续创新的需求。为此,Oinone打造了一站式低代码商业支撑平台,从业务与技术两个维度来帮助企业建立开放、链接、安全的数字化平台。这将在水平和垂直两个维度上全面推动企业数字化转型。 另外,低代码的另一个好处是完成了软件本身的数字化建设。通过基于元数据设计,元数据成为软件中数据、逻辑和交互的数据,软件结合AI可以有更多的创造可能。想象一下,AI了解软件的元数据后可以自我运作,人在极少情况下才需要参与,人机交互也会发生大的改变。未来的软件交互不再需要研发提前预设,而是能够实现用户所需即所呈现的效果。作为一家帮助企业进行数字化转型的软件公司,请问您的数字化转型是否已经完成呢?

    2024年5月23日
    1.3K00

Leave a Reply

登录后才能评论