立体数据模型
立体数据模型
立体数据模型是Dorado中全新的、最为核心的概念。
- 什么叫立体数据模型?
- 为什么需要引入立体数据模型?
- 怎么实现立体数据模型?
什么叫立体数据模型?
Dorado主张数据和表现的分离,将界面上的数据抽象为专门的数据模型,成为一个独立的子系统。下面我们从数据流转的角度分析一下WEB应用中的数据处理过程。看下图: Web应用的运行过程就是对数据进行处理的过程,上图我们分析的就是从数据库出发到浏览器转一圈,最后通过ORM业务逻辑处理重新保存到数据库的这么一个过程。 我们先分析从数据库到浏览器:首先从数据开始,以目前最常用的开发模式分析,例如我们使用Hibernate,那么这些数据就会被ORM处理机制转换为通过一堆JavaBean描述的对象,我们称它们为领域对象模型(DomainObject),之后领域对象可能会经过业务逻辑的组装,重新拼装或改写,变成一种全新的格式,也有可能形式上没有什么变化,但是作用上已经发生了很大的变化,这些对象我们叫视图数据对象。这些对象是为前台提供服务的。之后这些ViewObject通过HTTP传输,被response到浏览器中,成为浏览器前端所有表达的数据。 再来看从浏览器到数据库:ViewObject输出到浏览器之后,这些数据被展示给客户,由用户做各种操作,可能改写其中的部分信息,最后它们会被提交到服务端,并被转换为ViewObject。之后服务端要抽取这些ViewObject中的信息组装为ORM中所需要的领域对象,再持久化到数据库中。 平面数据和立体数据 要进一步分析前面的数据处理,我们以平面数据和立体数据来概括数据在前述过程中的两种数据载体形式。 概念:
- 平面数据:通过键值来表达数据与数据间的关系。例如关系型数据库中的数据。每一条数据都是独立的,它们之间的关系是通过外键值指向另外一个数据的主键值。
- 立体数据:通过引用来表达数据与数据间的关系。例如通过Hibernate获得的领域模型数据。如我们拿到一个部门对象,部门对象内部还包含所有的雇员对象。
以数据载体形式的角度再度观察 根据这平面数据和立体数据的概念,我们将前面WEB应用中的数据处理过程的图,进行着色区分这两种数据,其中的立体数据被标以蓝色
整个过程充斥着平面到立体,立体到平面,平面到立体的恶性循环,整个过程非常不流畅。这也是传统WEB开发中相对比较麻烦和复杂的一个重要原因。在关系数据库到DomainObject端的相互转换我们尚可以依靠Hibernate这些相对成熟的ORM工具帮助我们以较小的代价完成转换工作,但是在Java端到浏览器端立体到平面,平面到立体的转换过程中却需要我们完全靠自己的手工完成。 对数据形式进行一些归纳 通过上面的分析,我们对数据形式进行一些归纳: 数据的本质是立体的,现实生活的检验我们知道对象之间都是引用的关系;
- 但是保存在数据库中的数据是平面的,关系型数据库的好处是有利于存储和检索;
- ORM把数据库中的平面数据映射成立体的;
- XML、JSON数据可以方便的描述较简单立体数据,它可以描述数据与数据之间的关系,但又局限性:它可以描述树状的数据,但是无法描述网状的数据,所幸日常开发中一般不会遇到网状的页面展现和表达形式;
- 网页Form中的数据是平面的;
- 在进行运算时,处理立体数据比处理平面数据容易,这是无容置疑的;
- Dorado5的Dataset是平面的(如果你用过Dorado5的话,就很容易想明白);
为什么需要引入立体数据模型?
为什么需要引入立体数据模型?根据前面的分析,其实我们不难看出如下两点:
- 由于数据的本质是立体的,因此当界面越能展现和处理这种立体关系时,它对用户友好程度就越高。
- Hibernate(ORM)的使用经验告诉我们,平面数据和立体数据进行互转时需要付出很大的代价。
综合以上两点,我们需要在Client端提供立体数据模型以提高界面的友好度、同时改善应用数据处理过程的流畅性。即将下图红框中的部分变为立体数据模型: 我们将上图再简化一下,就总结为如下图: 从左边平面DataSet到右面立体DataSet就是我们的目标。
怎么实现立体数据模型?
首先进一步了解两个概念: 数据载体
- 用于封装和承载数据的对象,通常由数据实体和数据实体集合这两种对象构成。
- 数据实体是指一个拥有一到n个属性的对象。在Java中通常表现为POJO Bean或Map;在Javascript中通常表现为JSON对象。
- 数据实体集合用于管理0到N个相似的数据实体。在Java中通常表现为List/Set;在Javascript中通常表现为Array。
数据集
- 数据集是指那些根据业务逻辑或编程的需要提取出来的一堆数据。
- 一个数据集的所有数据往往在逻辑上具有很强的相关性。比如当我们开发一个部门信息的维护界面时,会提取出某部门及其中所有雇员的信息作为一个数据集。
Dorado中的数据载体 Dorado在Server端不提供专用的数据载体对象,而是直接使用POJO Bean/Map以及List/Set来作为数据载体。
- 事实上,处于状态管理等需要Dorado会动态代理(Cglib或Javassist)对原始的数据载体进行一个功能增强,只是大多数情况下开发员不需要也不会注意到这一点。
- 这一做法可以在很大程度上简化Dorado与用户的业务逻辑层对接的难度。Dorado在Client端提供了专用的数据载体Entity/EntityList,他们的用法非常类似于JSON/Array。同时,Dorado也支持直接以普通的JSON/Array最为数据载体。
- 之所以要在Client端提供了专用的数据载体,是因为Dorado需要为数据载体添加很多诸如异步数据装载、状态管理、翻页、管理当前记录、数据校验等功能。
Dorado的数据集——DataSet Dorado中提供了DataSet作为数据集的描述,DataSet主要的生命周期在Client端。相对Dorado5而言,Dorado中DataSet的功能被极大的弱化了。其最重要的用途就是为其管理那堆数据赋予一个ID,以便于数据感知控件能够找到这些数据。另外DataSet不再局限于二维表结构数据,而是可以支持非常自由的数据形式:
- 数据实体的集合
- 单个的数据实体
- 数据实体构成的树状结构
- 甚至是一个简单的字符串-
一个稍复杂的数据集场景
想象如下这样一个人事组织架构的场景。 这是一个部门组织树,顶级节点下包含三个子部门,其中第一个部门下有三个员工,第三个部门下又包含了两个子部门,另外这个部门的内部还有三个员工。如果我们采用平面数据模型(包括Dorado5),无论通过1个还是多个Dataset都无法实现这样的数据模型。而Dorado用一个DataSet就实现了。 我们将上图转换为下图: 其中Department拥有一个自关联关系,另外还有一个Employee的聚合关系。 如果采用立体数据模型开发的时候,如果你能很容易的将上图快速的转换为一颗树形结构,将会对你的开发带来很多好处:更快速的设计和开发。
立体数据模型带来的新问题
问题1: 如何对模型中的数据实体进行进一步的描述? 例如上面的部门对象,其中既有子部门又有员工集合,我们无法简单的按照平面数据模型的那种定义方式,定义其中各个属性的校验规则、数据类型、显示格式等等。解决的办法是我们在Dorado中引入全新的概念——DataType,这个对象我们将在后面的章节详细介绍。 问题2:如何实现与数据感知控件的绑定? 在平面数据模型中,数据绑定比较简单,比如Dorado5中我们将一个Grid与一个DataSet一绑定,就可以直接展示其中的数据了,应为其中的DataSet就是一个二维表。但是Dorado中就不能这么做了,例如我们之前的数据模型: 如果页面上有一个Grid,用来显示员工信息,但是上图中我们如何让Grid显示第一个Department下的员工,或者我们要显示第三个Department下对应的员工。为了解决这个问题,我们需要再引入一个全新的概念——DataPath,后续章节将详细介绍。 问题3:如何对管理当前记录? 在Dorao5中每一个Grid都有当前记录的概念,但是在Dorado中由于采用立体数据结构,如上面的组织结构图中的第三个部门中,相对部门来说当前部门是指红色框中的部门,而当前员工是指下面红框中的员工。从这儿我们能看出在Dorado中当前记录的概念已经比Dorado5中更为丰富,一个DataSet拥有多个当前记录,其中的每一个集合都需要管理各自的当前记录。
更多建议: