APP下载

一种改进的MVC框架在ERP系统开发中的应用

2018-09-21叶小艳李伟民

计算机技术与发展 2018年9期
关键词:窗体视图浏览器

叶小艳,张 芒,李伟民

(广州大学华软软件学院,广东 广州 510990)

0 引 言

在多终端的“互联网+”时代,如何提高系统开发效率是许多企业一直探讨的问题。经过多年的研究及尝试,前后端分离架构技术成为了许多企业的选择[1]。因为终端有Android、IOS、Web,它们有不同的展现形式,但是需要展示的数据是一样的,所以只需要后台提供接口,前端(终端)获取数据并展示出来即可,并且不同的终端需要不同的开发人员,只有前后端分离的架构最适合当前多终端的时代,因此前后端分离架构便成了趋势[2]。

传统开发协作模式有两种:一种是前端写静态页面,后端套模板[3]。静态页面可以进行本地开发,只需实现视图而不需考虑业务逻辑[4]。但因后端要套模板且浏览前端代码,过程较为复杂。另一种是前端写模板[5],但前端编写过程中过于依赖后端环境,一旦后端没完成,前端则无法操作。这两种协作方式是目前市场上大量采用的“前后端分离”技术,但这两种方式都存在问题,且没有实现真正意义上的系统整体架构的前后端分离。

文中采用改进传统的MVC框架来实现前后端分离,以此减少前后端的耦合性,提高用户体验,加快网页加载速度,降低开发和维护成本,提升效率。

1 改进的MVC框架

1.1 快速开发技术及现有架构

传统的开发模式存在需求沟通不对称、需求变更频繁、需求不明确等问题,造成项目效率低下、延期甚至失败等问题。近年来逐渐兴起的快速开发技术,则是实现以业务为驱动的智能开发。形成的各种快速开发平台是基于业务导向的设计理念,抽提所有管理系统运行的驱动共性形成的“业务驱动模型”,省去了复杂和重复的编码过程,通过对智能报表、数据维护业务控制和其他参数的管理,可以快速、高效地开发各类业务系统。简化了系统的运行机制,抽提构成系统的稳定元素和个性元素,解决各类管理类软件的构筑元素,所以这种快速开发平台既可以适用于开发任何类型管理软件,又可以大幅度提高开发效率,减少技术瓶颈。

目前国内已有的Web快速开发框架有不少,仅在MVC方面,就有struts和webwork,还有将struts和webwork统一的struts2,以及tapestry、JSF、easyJWeb[6]。权限管理框架有Spring Security,异步调用技术有AJAX、DWR,RIA技术有extjs、jQuery、FLEX、GWT等[7]。现有的Web快速开发框架功能较强,但也有开发难度大和需要的知识复杂等缺点。这样开发人员不仅要熟悉服务器端语言,还必须掌握Ajax相关的难以调试的前端技术。与此同时,现有的Web快速开发框架从不同层面解决了开发过程中的部分问题,偏重某一方面,但仍然包含有相应的模板设计和枯燥的代码段。文中旨在整合并改进现有的MVC框架,并结合现有快速开发技术平台快速搭建业务模块的优点,构建一套生态式的开发方法。

MVC模式诞生于19世纪70年代,流行至今。MVC模式,即“模型—视图—控制器”的框架技术,是将一个应用的处理流程按照这种方式进行分离[8]。这样,一个应用流程体系分为模型、视图和控制器三个核心模块,分别在系统中承担不同的功能和责任。这种框架技术使开发更加高效,代码耦合度尽量减小,使应用程序各部分的职责更加清晰。

传统MVC模式如图1所示,其缺点如下:第一,视图依赖于模型。如没有模型,视图亦无法呈现效果;第二,请求须经“控制器→模型→视图”固定流程,用户才可看到最终展现界面,过程过于复杂;第三,渲染视图的过程在服务端完成,呈现给浏览器的是带有模型的视图页面,性能无法更好地优化。

图1 传统MVC模型

1.2 改进MVC架构

为了克服这些缺点,对模型进行改进。从浏览器发送AJAX请求到控制器,服务端接受请求,然后返回JSON数据给浏览器,直接在浏览器中渲染视图[9],如图2所示。

图2 改进的MVC模型

将服务器那一端视为后端,浏览器这一端视为前端,将以上改进后的MVC模式简化为以下前后端分离模式。前端关注界面展现,后端关注业务逻辑,分工明确,职责清晰。

结合快速开发技术平台和改进后的MVC模型,构建系统开发架构[10],如图3所示。

图3 PC系统开发架构

前端窗体通过各类组件组成,形成视图层;利用规则、函数等组成规则链来对视图层进行控制,并加入实体层,规则链可以对视图层与实体层进行操作控制,使用规则链来处理数据,使用实体模型来绑定窗体里的组件。调用数据时从数据库加载到实体,通过绑定实体的窗体呈现。

2 ERP系统设计与实现

2.1 系统设计

2.1.1 系统架构

系统以ERP系统中库存、OA等模块为例,搭建基于前后端分离的系统架构,以此搭建一个具有响应式布局的SPA后台ERP管理系统。

基于图3开发架构的控制层与模型层,将视图层脱离出来,React+dva的前端技术组建系统的前端页面,并通过访问控制层公开的接口对后台进行操作,最终形成了该系统架构,如图4所示(V3指某快速开发平台)。

图4 系统架构

系统分为前后端两部分:

(1)前端向云服务器发起静态文件请求,如HTML、CSS、JS、Image等,由Nginx服务器搭建的HTTP服务会访问本地资源,得到HTML、CSS、JS、Image等文件,并返回到前端,然后展示通过浏览器编译成用户可以看到的页面。

(2)Nginx通过反向代理将V3执行系统的地址代理到80端口,比如访问http://www.mitarl.com/api时,通过反向代理后最终访问的是http://www.mitarl.com:8080/webapi/。

(3)前端通过AJAX(GET、POST)向Nginx服务器发出请求,访问V3的WebAPI接口,WebAPI通过规则链对数据进行处理,最后通过访问数据库并得到相应的数据,然后以JSON格式的数据返回到前端,前端拿到数据后对其进行处理,并展示在用户的浏览器上。

2.1.2 系统技术架构

系统技术架构如图5所示。

图5 系统技术架构

①State表示Model的状态数据;

②Action是一个带type属性指明具体行为的对象,它是View层改变State的唯一途径,通过调用dispatch方法,传递Action到Model层,根据Reducer改变State;

③异步的Action,与同步的Action在dispatch时是一样的,但是到达Model层,Model层会先根据type先触发Reducer再触发Effect;

④dispatch是一个用于触发Action的函数,可以看作是触发这个行为的方式[11];

⑤Reducer是描述如何改变数据的[12];

⑥Effect被称为副作用,dva底层引入redux-saga做异步流程控制[12],运用ES6的generator的相关概念将异步转成同步写法;

⑦Subscription订阅,然后根据条件dispatch需要的Action,可以监听路由、键盘输入等的变化;

⑧connect将React与Redux数据连通,通过映射State里面的数据,以React中props数据的方式传递给组件。

2.1.3 系统框架整合

先订阅监听浏览器的路由变化,当地址匹配成功后,会触发向服务器获取数据的异步请求,获取到数据后,对状态容器进行赋值,状态容器发生改变后映射到了对应的组件,组件就会进行渲染处理[13]。

(1)Subscriptions订阅代码。

配置(){监听路由(路由地址){如果路由地址==/home或者==/则触发getOwnerTasks方法}}

(2)Effect代码(主要处理异步请求)。

getOwnersTask(){先从state树里获取当前状态的app树下的user和Home树下的query,再创建传递给接口的数据对象,然后调用写好的service接口并传入参数。等待call的结果,判断结果是否正确,正确就put触发对应的Reducer去修改状态树}

(3)Service服务接口代码。

一个异步函数,提供给effect调用,以JSON格式的数据传递params参数到服务端接口,最终收到接口的返回数据并传递给正在等待的effect。

(4)Reducer和state树。

Reducer接收action,即put时带的参数,这里是把接口传过来的参数(todo、done两个数组)合并到当前的state树里。

(5)Connect将Redux与React连接起来。

将state树中Home节点,app节点下的isNavbar、user映射到Home组件,使得Home组件的prors属性存在这几个属性。

(6)Home组件下的Table组件。

数据源是通过state树传过来React的props属性下的todo,滚动条是根据浏览器大小决定的。使用React进行组件编写,通过dva(Redux+React-Route+Redux-saga)提供的connect组件对React和Redux进行通信,从而React组件可以获取Redux里面的store数据,React通过发送action去触发effect(异步)请求V3WebAPI接口或Reducer(同步),从而Redux改变store里面的数据,React组件的props属性绑定了Redux的store,store改变props也会改变,React组件就会自动刷新状态。

2.2 系统实现

基于篇幅,本节只介绍系统开发过程中用到的框架技术的典型示例。

2.2.1 登录功能

登录功能主要是对用户身份进行验证,核对用户输入的用户名、密码和验证码的数据合法性和一致性。登录功能采用异步请求到快速开发平台的登录构件,实现过程如下:

点击登录按钮会触发action,然后action触发effect(带*的是ES6的异步函数),接收两个参数。第一个参数:接收action传过来的数据,这里是把这个参数里面的payload拿出来;第二个参数:获取dva框架提供的两种异步方法,call是去请求service(定义请求接口,类似于Ajax)并传入payload,通过yield关键字去等待异步数据,当异步数据获取回来后,赋值给res,res里面的data就是从V3WebAPI获取过来的数据,再判断数据是否正确,如果正确则put一个Reducer,将传过来的数据对应修改store里面的数据,React再刷新组件状态。

2.2.2 流程定义功能

快速开发平台支持完整流程定义和扩展,提供高度可视化流程设计器,集流程图设计、规则定制和代码扩展、调试于一体,流程设计开发快捷高效[14]。使用iframe连通快速开发平台的窗体,使快速开发平台的窗体能在自己的系统中使用,将自己写的页面与快速开发平台的窗体结合起来。

2.2.3 组织机构管理功能

组织机构管理也是使用iframe连接快速开发平台的窗体,因为快速开发平台已经提供了一套组织机构管理的标准的窗体与规则,完全不用自己去做任何的业务编写,所以利用快速开发平台的这些窗体来对系统进行扩展。

总之,使用iframe来连接快速开发平台提供的窗体,简化系统的一些必要业务,如OA、组织机构管理等模块,可以直接引入快速开发平台的窗体来对系统进行扩展,从而节约开发时间和简化开发过程。

2.3 系统测试

2.3.1 Model层测试

Model层使用Mocha测试框架与第三方断言模块expect进行测试。Model层测试代码如下:

import expect from 'expect';//引入断言模块

import {effects} from 'dva/saga';//引入effects

import Home from '../src/models/Home';//引入需要测试的model

//Home测试用例

describe('Model的Home测试用例',()=>{

it('加载',()=>{expect(Home).toExist();});

describe('测试reducers',()=>{

it('getOwnerTasksReducer',()=>{

const reducers=Home.reducers;

const reducer=reducers.getOwnerTaskReducer;

const state={

todo:[],

done:[],

};

expect(reducer(state,

{payload:{todo:[{id:1,state:'Running'}],done:[{id:2,state:'Complete'}]}})

)

.toEqual({ todo:[{ id:1, state:'Runing'}],done:[{ id:2, state:'Complete' }]});

});

});

describe('测试effects',()=>{

it('getOwnerTasks',()=> {

const{call,put}=effects;

const sagas=Home.effects;

const saga={sagas.getOwnerTasks;

const generator=saga({type:.'Home/getOwnerTasks'},{call,put});

let next=generator.next();

//访问接口成功后,接口会返回是否成功的参数,正常情况下是返回成功

expect(next.value).toEqual({ success: true });

});

});

});

Model层需要测试的是Reducer与Effect,Reducer是普通函数,并且是纯函数,职责单一,对于固定输入,就有固定输出,所以很容易测试。Effect的测试主要是验证这件事是否发起了对某个服务的调用,这个服务是否在执行,无关本模块的正确性。一个Effect实际上是转化为同步逻辑的测试,因为它是一个generator函数,只需对这个Effect一路next,就能跑完整个逻辑。

2.3.2 表现层测试

表现层主要是React组件,利用Enzyme库结合mocha与expect断言,去测试React组件的虚拟DOM创建情况、虚拟DOM的渲染情况等。表现层测试代码如下:

import React from 'react';

import{shallow,mount,render} from 'enzyme';

import Home from '../../src/routes/Home';

import MinimzeCard from '../../src/components/common/MinimzeCard'

describe('Home测试虚拟DOM',function(){

it('Home下的第一个MinimzeCard的title属性是待办',function(){

let app=shallow();

//在Home的虚拟DOM中寻找MinimzeCard组件,找到它的title属性,它的断言为待办

expect(app.find(MinimzeCard).at(@).props('titled)).to.equal('待办');

});

});

describe ('Home测试渲染情况',function (){

it('渲染Home组件,渲染出两个MinimzeCard', function(){

let app=render();

//渲染Home组件后,寻找MinimzeCard组件的长度大小,断言为2

expect(app.find(MinimzeCard).length).to.equal(2);

});

});

总体而言,使用mocha测试框架编写测试用例去测试dva框架与React框架,最终执行测试用例,并通过所有的测试用例,最后系统未发现严重的缺陷,系统业务逻辑无错误,保证了系统的完整无漏洞。

3 结束语

该系统PC端,使用某公司快速开发平台,实现以业务为驱动的智能开发,更多考虑用户的需求,实现复杂的企业级管理系统软件的开发,极大地提升了软件的开发效率和开发质量,大幅缩短了开发周期[15]。

系统移动端采用前后端分离技术以及响应式布局,并使用流行前端框架React开发了ERP系统,经过详细的设计和测试,最终实现了整个开发框架。React的组件化思想,使得系统更加模块化,更容易维护、拓展。用户可以较快地熟悉系统,可以利用PC端和移动端操作系统,从而提高工作效率,缩短开发流程。

利用快速开发技术,以业务为驱动快速开发系统,将重点放在系统更完善的功能上而非代码,结合现有移动端的开发框架,逐步完善移动端框架,并且对移动端扩展更多的功能。推广这种快速、扩展性强的框架方法,使信息系统开发更加便捷多元。

猜你喜欢

窗体视图浏览器
微软发布新Edge浏览器预览版下载换装Chrome内核
反浏览器指纹追踪
试谈Access 2007数据库在林业档案管理中的应用
基于Qt的多窗体快速并行图形绘制方法研究
视图
Y—20重型运输机多视图
SA2型76毫米车载高炮多视图
Django 框架中通用类视图的用法
浏览器
WinCE.net下图形用户界面的开发