前言
已第二次使用AngluarsJS来进行业务开发.虽然队友们对此报有一些情绪与意见.认为比较难用,主要集中在性能方面的考虑.但是我却认为我们从根本上改变了整个前端开发的模式.更多引出了许多前的系统设计方案.起码从开发来说,开发效率,代码可维护性,简易性,条理性都有本质上的提升.
其中AngluarsJS提供了在前端MVC分层的可行性.(其实未必一定使用AngluarJS,只要能让项目以MVC的模式分层则可)改变以往使用jQuery之类的库时,大量的业务代码与业务逻辑代码有着高度的耦合.基本上每个页面的js代码只服务一个业务,无法有效的进行复用业务内容.然而这些情况已经被AngluarJS改变,通过框架提供的Service服务,IOC,Controller,数据双向绑定等,已经可以有效的划分业务代码与操作逻辑,其实也就是MVC,由此业务代码可以独立编写,带出了很多专于某业务的业务代码.
最终,在前端已有MVC框架情况下(常规来说不叫MVC,准确地应是MV*,但这里先此当作MVC来进行讨论),我想直接将这种思路发展得更极限与彻底:服务端是一个可以持久化的json对象,前端仅需要与持久化json对象进行交互。
思路说明
将服务端抽象成一个持久化Json对象存储器.前端通过ajax来对持久化对象来进行操作,包括增加,修改,删除,查询等方式。
服务端操作则是通过对前端对象操作事件的一观察者,并且所有的输出直接返回给前端,而与前端一样,都是是持久化对象。
最终是将数据模型(MODEL)向前移,前端可直接访问。
最终是将数据模型(MODEL)向前移,前端可直接访问。
详细说明
上文可能觉得比较难理解。现在详细说说。
以往开发会在服务端定义若干个服务接口,调用具体业务的接口方法,返回对应的结果数据。各方法间是独立的。每个接口都会定义一套具体的参数。返回结果的具体形式,各结果具体的意义是什么。严格说,这种写法属于接口驱动型,或是业务方法驱动型。
然而现在模式不同, 不是独立地提供接口,而是直接提供一个对象,准确地说是一个虚似的json对象。服务端说明这个对象中各成员变量的意义则可。
分析实例
在微博平台中
功能1:一个用户向一微博进行评论。
功能2:收藏一个微博。
前端面向接口做法
定义一个评论接口:
ResponsesetCommentInTwitter(LongTwitterId, String context);
方法会定义一个微信的id,与文档的参数。然而为了灵活调整参数,会定义如下方法
ResponsesetCommentInTwitter(CommentAddForm commentAddForm);
通过CommentAddForm类来封装需要提交的参数,如果需要增加参数而直接在Form类里头增加成员。
如果需要增加功能话,则服务端需要增加业务方法
例如现在需要增加用户收藏微博功能,则需要如下
Response collectTwitter(Long twId);
这里参数就比较简单,但是需要服务端增加对应的方法。
*前端面向对象的做法
假设现在服务端的存储数据结构如下:
{ twitters:{ "1":{ context: "我快没有水啦,各位赶紧给我加水!!!", createTime:"2015-12-01", comments:{ "1":{ context:"你是个水桶?", createUser:{$ref:"user.1"}, createTime:"2015-12-01" }, "2":{ context:"头脑里头是有水的", createUser:{$ref:"user.3"}, createTime:"2015-12-01" } } } } users:{ "1":{ account:"zhengmx", email:"tooze2003@163.com", nickname:"代码牧", favor:{ "1":{$ref:'twitters.1'} }, createTime:"2015-12-01" }, "3":{ account:"yangsl", email:"xxys@163.com", nickname:"杨圣琳", favor:{}, createTime:"2015-12-01" } } $login:{ curUser:{$ref:'users.3'} } }
例如现在增加评论,则可以在前端js代码如下操作:
var twitter = ...//传入微博对象,假设id为1 var twitterComment = { context:"的确是一个大水桶" } //传入的微博评论内容 var objSer = ObjService.getService(); //提到与服务端对象对接的封装方法,简化前端的使用 //用户提交评论 objSer.push(twitters_id+'.comments',twitterComment,function(resp){ console.info('resp',resp);//将返回结果打印。 } );
此时服务端数据如下:
"twitters.1":{ context: "我快没有水啦,各位赶紧给我加水!!!", createTime:"2015-12-01", comments:{ "1":{ context:"你是个水桶?", createUser:{$ref:"user.1"}, createTime:"2015-12-01" }, "2":{ context:"头脑里头是有水的", createUser:{$ref:"user.3"}, createTime:"2015-12-01" }, "3":{ context:"的确是一个大水桶", createUser:{$ref:"user.3"}, createTime:"2015-12-01" } } }
//收藏一个微博 objSer.push('$login.curUser.favor',twitter,function(resp){ console.info('resp',resp);//将返回结果打印。 } );
此时服务端数据如下:
"usesr.3":{ account:"yangsl", email:"xxys@163.com", nickname:"杨圣琳", favor:{ "1":{$ref:'twitters.1'} }, createTime:"2015-12-01" }
实例分析
通过后者来开发的话,服务端则不需要增加接口。也就是说,前端基本上可以直接操作数据库(json对象),不需要后端程序编写加入评论,收藏业务。
在当前场景下,直接操作当前用户的信息,不需要做统计类的信息数据时,可以直接操作业务对象, 在前端进行业务方法的编写。
其中配合AngluarJS,可以将大量方法以Service的方式进行封装。
如TwitterService,UserService。
而Controller则负责将数据分解,将Service的返回的数据转成对应的VO对象。此时可以大量减少前后端之间的代码开发,前端开发时可以直接考虑数据模型的对称,不需要太多地与后端接口进行沟通与对接。如果需要简单修改代码时,只需要更新前端代码,将对应的js代码更换则可,不需要重新布署服务端代码。
整体模式梳理
服务通过抽象出一个可以持久化的实体对象,前端可以直接操作对象,通过此来保存,查询数据。通过设置对象来建立数据之间的关系。
通过AngluarJS等框加,可以在前端对部份业务方法进行封装。
一些业务方法并非都是在前端开发,部分业务方法实则在服务端编写,而编写是围绕抽象的对象进行操作,通过监听的操作来实现后端的业务。
后端不直接向前端提供业务方法,而是通过对象的操作来向前端反馈信息。而后端的逻辑最终输出也是设入对象中,然后供前端进读取。
其实此架构方案并非说完全不需要后端代码,而是将一部份后端业务逻辑代码往后移,放在实体的后端,不直接与前端交互。
原模式:
js -> Action -> Service -> DAO -> DB(数据库)
现在型式:
js -> Obj <-> Listen(Service)
前端后端代码结合例子:
用户登录:
前端代码:
var = loginInfo{ curUsr: { account:"zhengmx", password:"123456" } }; objServer.push('login.',loginInfo,function(resp){ $scope.loginMsg = resp.data.loginMsg; if(resp.data.loginCode==1){//登录成功 page.toIndex();//跳首页 }else{ } });
后端代码:
//监听某个对象的写入,业务完成成将输出写入对象中,而非直接返回给前端,此方法与前端无保直接交互 @ListenSet(id="login");//注解代表的是监听set入login.curUser的动作,而非直接提供一个接口方法 public Obj login(Obj rt, Obj newValue, Obj oldValue){ List<Obj> rs = rt.find("users.name="+newValue.get("curUser.account")+"&users.password="+newValue.get("curUser.password")); if(rs.size()>1){ newValue.get("curUser").ref(rs.get(0));//将新值置为引用持久化对象中用户的对象。 login.put("sessionid", WebConf.getSession());//取得session,其实会通过cookie将session传送到浏览器中。 login.put("loginCode",1); login.put("loginMsg","登录成功"); }else{ login.put("loginCode",2); login.put("loginMsg","登录不成功"); } return newValue;//返回的是前端set入的对象,而是不响应的对象. }
响应数据如下:
$login:{ curUser:{$ref:'users.3'} sessionid:"D092A8DE4ED756EDFEAFE04F038B4086", loginCode:1, loginMsg:"登录成功" }
服务端提供的服务汇总
服务端仅提供对持久化对象的编辑,查询操作。
编辑包括:
set:对指定的id位置直接赋值。
push:新增对象,其中由服务端来生成key值。
get:通过id得到需要的对象。
find:通过查询表达式查询对象。
理论上这些方法基本与业务无关,因为在性能优化上可以针对这些方法优化,主要都是走key/value的方式,与减少了后端的业务逻辑处理。因此在性能上会有较大提升。
持久化对象的设计
持久化对象的数据结构为json,一个服务则仅提供一个对象,此对象称为根,简称为rt。
对象的id为对象相对于
如果一个字段是引用其他对象,则使用{$ref:"objectid"}
后端js化
以上例子的监听方法是java代码。为了进一步轻量化系统开发的负担。则可以将监听方法js化。
开发者使用js写好监听方法后,事件触发时调用js代码,传入对应的dom对象。其中包括有rt对象。
登录后端代码改写成js后如下:
var $listen_login = function(rt,newValue,oldValue,webConf){ var rs = rt.find("users.name="+newValue.get("curUser.account")+"&users.password="+newValue.get("curUser.password")); if(rs.length>1){ newValue.curUser=rs[0];//将新值置为引用持久化对象中用户的对象。 login.sessionid= weConf.session);//取得session,其实会通过cookie将session传送到浏览器中。 login.loginCode=1; login.loginMsg="登录成功"; }else{ login.loginCode=2; login.loginMsg="登录不成功"; } return newValue;//返回的是前端set入的对象,而是不响应的对象. }
js化后,修改业务无需更去重启服务端,适合需要快速迭代开发的模式,尽早地将功能上线,而不需要走冗长的升级程序,编译等。
数据权限方案
<待编写>
架构优势
提高前端的业务范围开发能力,减少服务端的复杂性。
缓存优化难度减少,服务端性能可以快速得升,得更加轻量。
升级系统成本减少,部份业务可以不需要重新升级程序,时改时生效。
适用场景分析
操作的数据简单,针对当用户数据操作较多,且不需要提交大量数据;
用户对实时应响要求高,操作反馈多,逻辑复杂。
功能更新频繁,迭代次数高;
事务要求较少;
无做大量统计的统计操作;
数据模型无需要大量互相引用;。
不适用场景
大量实时统计需求;
对事务要求较高;
权限要求细度高;
前端设备差,兼容要求高。
结语
目前这个思路还未得到充份的实践与验证,也是小弟在近段时间开发过程中想到的一些决解方案。
这种方案更多地偏像于基mongodb这种NoSQL模式的开发。然而仅仅是"像",mongodb数据库与理想中的Model的目标实现有一定的距离,在业务数据管理时并非一个较好的解决方案。
从这种思路来开发程序时,只是思路转改过来,开发企业级的业务管理系统的效率会非常的高,更多时间都是集中在前端用户体验,与业务流程上的考虑,轻量的服务端开发,更少了去考虑关系数据与服务端之间的交互,更少地去关心实体模型结构,更少地去定义接口,从而减少接口定义带来额外的沟通成本。
如果需要某某数据,则在前端代码增加需要的成员,有种“你要我就马上给你的感觉”。
后续我会对这个思路涉及到的代码不段时间,找出对应的实现方案,会开发出一个样例项目放在github中。
如果对此有兴趣,可以评论,可以私信我,更多地交流。
相关推荐
总的来说,通过Rose实例构造银行业务模型,我们可以清晰地了解银行系统的业务流程、参与者角色、业务规则以及需求管理,为系统的开发和维护提供了一套完整的蓝图。这个过程强调了业务逻辑的明确性、系统需求的全面性...
通过与客户的深入沟通,了解其具体需求,并结合业务流程,将系统功能细分,确保后续的设计和开发工作能够有的放矢。 为了更好地展现系统的需求,通常会绘制用例图(Use Case Diagram)。用例图是一种图形化的表示...
为了顺应“以账户为中心”向“以客户为中心”的转变趋势,并构建适应未来发展需求的信息系统,国有银行需要加快信息系统开发节奏,统一数据标准、工作流程标准和报文标准,突破传统架构的局限,促进核心业务的发展,...
4. **程式自动生成**:基于定义的交易和数据模型,自动生成相应的程序代码,大大减少了开发时间和成本。 5. **交易控制**:实现对交易的实时监控和管理,确保业务流程的顺畅和安全。 6. **通讯定义**:定义与外部...
系统架构共分为五个层次:终端设备层、网络通信层、前置解析层、数据层和应用层。终端设备层包含水、气、热表计,它们通过通信模块与智能电表或集中器连接。网络通信层负责数据传输,前置解析层解析不同表计的通信...
3. 应用系统架构:应用系统架构支持业务发展,定义了应用系统的层次结构,如渠道接入、综合前置、综合业务、管理信息系统和决策支持等。这种架构有助于应用集成和新产品开发,降低因系统不兼容带来的风险。 4. 系统...
FEA 的五大参考模型是指绩效参考模型(PRM)、业务参考模型(BRM)、服务参考模型(SRM)、技术参考模型(TRM)和数据参考模型(DRM)。 1. 绩效参考模型(PRM) 绩效参考模型是衡量政府工作绩效的标准模型。它...
数据库设计是系统实现的重要环节,包括概念数据模型(CDM)和物理数据模型(PDM)的设计,最终创建数据库表和视图。 应用程序编码阶段,根据前面的模型和设计,开发者开始编写代码实现系统功能。在整个开发过程中,...
XX银行的核心系统设计文档主要涵盖了该股份制银行的系统架构、功能目标以及实施策略,旨在为初学者提供一个传统核心银行系统的参考模型。以下是详细的知识点解析: 1. **引言**: - 作用:核心系统是银行的命脉,...
软件开发遵循软件工程原则,以保证系统的功能性和可靠性,采用J2EE体系的B/S/S三层架构,基于人力资源和社会保障应用系统技术支撑框架,强调参数化和组件化设计,以实现功能的可扩展性和灵活性。 在安全方面,系统...
数据模型设计的目的是设计系统所需的概念数据模型和物理数据模型。这一阶段涉及与数据库设计人员的紧密合作,以确保数据持久化机制的有效实现。 #### 九、业务构件设计 最后,业务构件设计阶段的目的是对业务构件...
3. **数据迁移**: 是指将企业现有的业务数据从旧版系统转移到新版系统的过程,旨在确保数据的一致性和完整性。 4. **动态建模平台**: 用友NC产品的一个核心组件,支持企业根据自身需求灵活定制业务模型,实现个性化...
6. **业务应用扩展**:开发对应业务应用和系统接口。 7. **硬件扩容**:增加独立的前置机和任务调度硬件设备,保持原有业务应用不受影响。 **业务架构** 1. **档案管理**:自动同步营销系统中的客户、设备和参数...
在IT行业中,尤其是在JavaEE应用开发中,前置知识是构建高效、可维护的软件系统的基础。本文将深入探讨JavaEE分层模型以及Servlet的相关概念,这些都是进行Web开发时不可或缺的知识点。 首先,让我们来理解JavaEE...
2. 采集系统功能扩展:扩展前置解析协议,调整数据表结构,开发新的业务应用和接口,以适应四表合一的需求。 3. 硬件扩容:为避免影响原有业务,增设独立的前置服务器和任务调度服务器,以处理新增的四表合一数据流...
新一代电能量自动化平台系统由六个子系统构成,包括前置机子系统、平台子系统、图形子系统、接口和报表子系统、业务处理子系统以及高级应用子系统。前置机子系统负责通过多种通信方式(如PSTN、GPRS等)与终端通讯,...
- **1.1.1 软件架构的定义:** 软件架构是指一个软件系统的主要结构组件、它们之间的关系以及指导这些组件设计和实现的原则。 - **1.1.2 软件架构师的角色:** - 定义系统的整体架构; - 协调开发团队以确保架构的...
在实际操作中,应避免过度依赖特定技术(如存储过程),确保团队间的良好沟通,同时根据业务需求选择合适的架构,如J2EE、分布式EJB或消息队列系统。对于数据库管理,适时采取主从复制、分片等策略以应对高并发和大...