王雁苓, 孙 利, 郭新辰, 吕学实
(1. 吉林省教育学院 教务处, 长春 130022; 2. 吉林广播电视大学, 长春 130022; 3. 东北电力大学 理学院, 吉林 吉林 132012; 4. 吉林省工商银行 科技处, 长春 130022)
现代信息管理软件采用定制开发的方法满足用户不断变化的需求, 应用字典技术是设计定制软件开发平台的关键技术. 应用字典模型的设计是把业务实体表的定义放到AD_Table和AD_Column数据库表中, 其中AD_Table主要存储业务实体表的表名(table name)信息, AD_Column存储表字段(field)的主要属性和显示逻辑[1].
使用AD技术设计的数据库逻辑上被划分成两部分: AD表和业务实体表. 业务实体表示根据业务需求定义的基础表和业务表, 是传统的数据库表; AD表保存了业务实体表的基本属性, 建立了表与显示容器、 表字段及数据类型与显示组件的对应关系, 它位于元数据层, 因而知道数据如何访问、 如何关联.
本文基于开源项目Adempiere ERP的应用字典设计[2], 提出一种应用字典三层架构模型, 并阐述了应用字典的层次结构和数据的逻辑关系, 是对应用字典技术的扩充和完善.
应用程序的发展经历了单层、 双层架构模式和MVC(模型-视图-控制逻辑)三层架构模式. 现代软件设计一般采用可定制化的方法, 满足客户多样个性化和不断发展变化的需求. 实现可定制化的有效方法是将显示属性、 数据验证规则从视图代码中分离; 将业务流程的控制属性从控制逻辑代码中分离, 与数据库中业务实体表的属性信息一并存入中央数据库中, 形成统一的属性总库, 构建应用字典. 因而应用字典的数据模型也具有三层结构: 核心AD层、 视图AD层和逻辑AD层.
核心AD层是数据库中表、 字段的基本属性集合, 包括其数据类型、 引用及验证规则等. 它为上两层的构建提供了最基本的结构信息和数据间的依赖关系、 验证及约束规则. 视图AD层描述各字段在客户端界面中的展现规则. 定制开发人员不需要编写大量的界面代码, 即可实现动态界面展示、 插入、 修改、 删除等基本数据库操作. 逻辑AD层是从应用软件中抽象出控制业务流程的各类参数, 以计算机化的表示模型存储于数据库中. 业务流程不再由编码实现, 而是采用一定的规范定制, 当业务增长引起业务流程变化时, 只需修改流程定义即可完成业务流程的再造.
应用字典的三层结构中, 核心AD层位于最底层, 它为视图AD层和逻辑AD层提供基础数据的支撑和一致的规则.
核心AD层数据库的实体关系如图1所示.
图1 核心AD层数据库的实体关系Fig.1 Entity relationship of AD core layer
表AD_Table和表AD_Column是应用字典技术最核心的两张表. 表AD_Table主要用于记录业务表的表名信息, 其中字段Name表示数据库表的逻辑名称, 一般用于显示窗体的题头; TableName表示表的名称. AD中既可以存储物理表也可以存储视图(View)[3]. 表AD_Column用于记录字段属性及显示、 控制逻辑, 其关键数据结构列于表1[4].
表AD_Column中存储的信息主要分为三类: 1) 用于显示和报表控制的逻辑信息; 2) 字段验证及合法性约束信息; 3) 表在创建时(Create table)的重要属性信息.
AD_Table和AD_Column两张表的核心作用: 两张表中保存着表、 字段的名称信息、 主键信息(IsKey)、 关联信息(IsParent)、 引用类型(AD_Reference_ID)等, 使应用程序知道如何访问数据及数据是如何关联的. 并且在表AD_Column中将ColumnName(表中字段名称)和AD_Reference_ID(引用类型)进行了绑定, 从而建立了业务实体表字段和界面中显示组件类型的映射关系. 这种映射关系是实现动态生成查询和维护画面、 动态生成统计报表、 自动生成持久化类代码的关键.
表1 表AD_Column的关键结构
最后, 核心AD层中定义了与数据自身相关的验证规则及合法性约束信息, 为视图AD层、 逻辑AD层的数据访问提供了一致的规则. 其中的关键字段设计如下.
1) AD_Reference_ID(引用类型). 该字段有两个作用: 关联数据库表字段的类型和关联界面中显示组件的类型. 表中字段的数据类型不同, 使用的显示组件也不同[5].
所有引用类型定义在表AD_Reference中, 字段(AD_Reference_ID)中保存着引用类型指向记录, 即唯一键值(primary key). 对于大数据量参数的引用类型, AD_Ref_Table表中定义参数源表的基本属性; 对于有相互关联关系的引用类型, 表AD_Val_Rule中定义引用参数的关联或控制条件[6].
2) Callout(外部程序调用). 外部程序调用就是调用存储在数据库中的一段轻量级程序代码, 即可以加载一个运行时才得知名称的类, 获悉其完整构造. 在显示组件焦点丢失时触发执行该段代码. Callout功能的设置使界面输入域具有智能、 动态的显示特点, 典型的应用表现如下:
① 加载或改变动态显示信息. 如在订单明细中, 单价、 数量和产品单位等字段使用同一个Callout, 每次数量、 单价或产品单位发生变化后, 系统自动更新总价;
② 在焦点离开时对字段数据进行合法性校验;
③ 控制字段在界面中的显示逻辑. 如在婚姻状态字段中, 如果用户选择“未婚”, 则界面中就不用出现“配偶姓名”等的输入项;
④ 移动焦点到指定显示组件.
3) 数据格式化及合法性约束. 表AD_Column中的一些字段控制数据的显示格式及合法输入范围. FieldLength约束输入信息的最大长度; IsMandatory约束字段必须输入, 不可为空; ValueMin和ValueMax两个字段约束输入值的范围; VFormat为输入值格式描述, 可以限制输入空格、 只字母、 大小写、 只数字等.
4) IsParent(外键关联). 业务实体表中两张表具有父子关系, 从父表到子表是一对多的数量关系, 因此子表中每条记录包含父表的主键标识, 该标识不需客户输入, 在客户界面中由父窗体向子窗体自动传递. AD中使用字段AD_Column.IsParent定义这种关联. 系统自动获取父表同名字段值存入子表[7].
视图AD层位于核心AD层上, 是客户界面的抽象描述. 该层主要解决软件系统的功能导航主菜单定制产生, 动态生成客户界面显示窗体, 动态生成统计报表, 支持用户编程实现的功能模块配置到主菜单. 主要由表AD_Menu,AD _Form,AD_Task和AD_process支撑. 实体关系如图2所示[8].
图2 视图AD层的实体关系Fig.2 Entity relationship of AD view layer
表AD_Menu主要用于保存应用系统主菜单信息表, 它与AD_Window,AD_Form,AD_Task,AD_Porcess是一对一的关系, Action_ID字段保存上述4张表的主键标识. 表AD_Window存储动态生存维护窗体的属性信息, AD_Window在客户界面上表现为一个显示容器, 其中可放置多个(或一个)功能相关的Tab面板. 表AD_Form和表AD_Task定义用户编码生成的窗体信息并执行操作系统命令, 这两个接口模块可将用户编程实现的功能模块配置到系统中统一管理, 增强了系统的适应性. 表AD_Process存储了动态生成统计报表的属性信息.
如图2所示, 表AD_Tab,AD_Field和AD_FieldGroup构建了动态维护界面的数据模型. 应用程序依据该模型, 动态产生与用户交互的界面. 在客户界面中, 表AD_Tab表现为一个Tab面板. 一个Tab只能对应一个数据库中业务实体表, 因此AD_Tab和AD_Table是一对一关系, 多个功能相关的Tab放入一个窗体容器中, 一个Tab中可以包含另一个Tab, 所以表AD_Tab有递归关系. 具有主从关系的表在窗体中以页签缩进的形式表现其层次关系, 在表AD_Tab中以字段TabLevel数值大小标识. 表AD_Field的结构依赖核心层的表AD_Column, 是业务表字段在显示界面中显示属性的描述, 主要包括显示域的位置、 显示域的长度等信息. 多个Field放在一个Tab中, 构成一个业务实体表的维护画面.
表AD_Process,AD_RepoatView及实线框内的表构建了动态统计报表的数据模型(图2). 报表数据来源于业务实体表, 格式定义在AD字典中. 数据来源跨多张业务表获取时, 定义逻辑视图表(View)将多张业务表联接(Join), 视图表描述在AD_RepoatView中. 表AD_ printFormat描述了打印报表的样式及字段的打印格式, 其中: AD_Paper定义打印纸属性; AD_PrintColor及AD_PrintFont 定义打印字体、 字号和颜色属性. AD_printFormat Item定义视图中每个打印字段的打印属性, 它依赖于核心层表AD_Column中的字段定义.
逻辑AD层是对业务控制流程的抽象描述, 是将业务流程计算机化的表示模型. 该层数据模型的设计得益于工作流管理联盟(WFMC)的工作流管理系统参考模型[9-10], 它将现实世界中的业务流程抽象成动作、 路由和参与者3个对象. 动作又称为活动, 是构成业务流程的基本单元, 主要反映完成业务流程所需计算机执行的操作. 动作可以由人负责执行, 也可以由系统自动判断执行. 路由决定了动作的执行顺序, 它的基本结构有: 顺序执行、 并行执行、 选择执行和循环执行. 通过基本结构的组合搭配, 可延伸出更多的路由结构. 参与者是具备一定工作能力的人、 机器或应用程序, 它能执行特定任务, 参与动作的执行, 完成流程执行工作[11]. 业务流程数据模型如图3所示.
图3 逻辑AD层的实体关系Fig.3 Entity relationship of AD controler layer
表AD_WorkFlow存储流程的唯一标识, 用主键AD_WorkFlow_ID表示一个流程的定义. 工作流根据其应用场景划分成如下3种类型.
1) 标准工作流: 是提供给用户一步步执行任务的步骤指南. 该系列的任务包括配置在表AD_WINDOW中的窗体, 表AD_FORM中的表单, 表AD_PROCESS中的报表打印等功能模块. 用户可以通过系统主菜单访问预定义的标准工作流.
2) 单据流转工作流: 系统中的所有单据(采购申请单、 报销单等)都可以自动使用工作流, 它基于表信息配置. 本文在AD_workFlow中设计AD_Table_ID字段, 就是要实现如果任何涉及到AD_Table_ID指向表的活动, 则将激活这个单据流程工作.
3) 单据值工作流: 当用户保存单据数据或系统自动更新单据中某个字段时, 系统有一个可监控字段条件值的机制, 当某条件满足(为“真”)时, 即触发单据值工作流执行. 为了实现单据值工作流, 在表AD_Workflow中设计DocValueLogic字段定义触发条件.
业务流程的动作被映射到AD_WF_Node节点表中, 一个业务流程由多个动作构成, 因此表AD_WorkFlow到表AD_WF_Node是一对多的关系. 在一个流程节点描述中必须有一个开始节点, AD_WorkFlow.AD_WF_Node_ID就指向该开始节点. 此外, 它还包括如下类型的节点.
1) 等待节点(wait): 该节点指定在系统执行下一个节点前等待时间;
2) 用户选择节点(user choice): 该节点请求用户交互;
3) 用户操作节点(user Action): 该节点也需要用户, 用户可以打开AD_Window_ID指向的窗体, AD_Foem_ID指向的表单, AD_Task_ID指向的任务和AD_Process_ID指向的报表;
4) 自动过程节点(Automatic processes): 该节点自动执行, 不需要用户交互.
路由被抽象成节点间的变迁条件, 它被存储在表AD_WF_NodeNext中. 字段AD_WF_Node_ID和AD_WF_Next_ID标识一个节点到另一个节点的变迁, 字段Condition描述了变迁的条件. 基本的路由结构实现方法如下.
1) 顺序执行: 当一个节点有且只有一个下个节点时, 流程按预定义步骤依次执行;
2) 选择执行: 当一个节点有多个下个节点时, Condition字段决定了流程的路由选择;
3) 并发执行: 当一个节点有多个条件相同的下个节点时, 这些节点会并发执行;
4) 循环执行: 当满足某条件时, AD_WF_Next_ID指向前面循环开始节点. 当条件不满足时, 指向退出循环节点.
表AD_WF_Node的字段AD_WF_Responsible_ID指向动作的参与者. 参与者可以是某个用户, 也可以是某类人(角色或组织). 参与者与节点绑定, 可以为流程中每个动作指定参与人.
逻辑AD层实现了业务流程的描述与程序代码分离, 在传统的编程模式下, 代码逻辑结构反映了业务流程的执行步骤, 程序设计人员不仅需要具备编程技能, 还要熟悉业务流程. 这种将业务流程从代码中独立出来, 通过配置完成业务流程的描述, 降低了开发难度, 加速了开发进程.
综上所述, 应用字典是实现信息管理软件可定制化的关键技术[12]. 将显示属性、 业务控制逻辑属性及数据库的基本属性从程序代码中分离出来构成应用字典, 从而增强了程序代码的通用性和动态性, 是缩短开发周期、 降低开发成本、 增强系统运行稳定性的有效方法.
[1] SU Hao. Application Dictionary Technology Research [J]. Natural Science Journal of Southwest University for Nationalities, 2008, 34(4): 868-870. (苏浩. 应用字典技术的研究 [J]. 西南民族大学学报: 自然科学版, 2008, 34(4): 868-870.)
[2] Adempiere Community. Adempiere ERP Open-Source Software (Version 370LTS) [EP/OL]. 2011-09-01. http://www.adempiere.org/site.
[3] Adempiere Community. Adempiere Development Community Wiki [EB/OL]. 2012-01-10. http://www.adempiere.com/Adempiere_Development_Community_Wiki.
[4] Adempiere Team. Table_of_Contents [EB/OL]. 2012-07-23. http://www.adempiere.com/index.php/Table_of_Contents.
[5] Openbravo Community. Openbravo ERP Developers Guide [EB/OL]. 2011-08-11. http://wiki.openbravo.com/wiki/ERP_2.50: Developers_Guide.
[6] Adempiere Team. Application Dictionary [EB/OL]. 2011-12-21. http://www.adempiere.com/Table_and_Column#Table_and_Column.
[7] Adempiere Community. Adempiere ERP Documentation [EB/OL]. 2012-02-16. http://www.adempiere.com/Adempiere_ERP.
[8] Bayn Cahya Pamungkas. ADempiere 3.4 ERP Solutions [M]. Birmingham: Packt Publishing, 2009.
[9] Adempiere Team. Application Dictionary Layers [EB/OL]. 2011-01-01. http://www.adempiere.com/Application_Dictionary_Layers.
[10] Adempiere Team. Workflow [EB/OL]. 2011-12-22. http://www.adempiere.com/Workflow.
[11] 侯志松. 工作流管理系统开发实录——基于JBoss jBPM实现 [M]. 北京: 中国铁道出版社, 2010: 69-107.
[12] Adempiere Team. ADempiere Rapid Development [EB/OL]. 2011-02-27. http://www.adempiere.com/ADempiere_Rapid_Development.