`
peterwei
  • 浏览: 249555 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

集中式Controller设计 PK 分开式Controller设计

阅读更多
一、引子
   昨天另外一个team的A过来找我们组的B,谈论通用flex分页的东西(A负责通用分页,我们所有人都是集成一下他的东西)。集成未果,A对B一陈狠批,说什么你怎么这样做,以后后来的人怎么维护等等。B说,怎么可能,我写的注释很清楚,不可能等等。由于涉及到双方的代码改动,B搬出C(也就是我,我是B的头)说:我和C讨论过的,可以采用某某设计等等,于是引出此文。ps:批B相当于批C
二、背景
   项目中采用flex+puremvc+blazeDS+spring+hibernate+cxf等技术。我们的争论点在于puremvc中的controller设计。puremvc中的v对应mediator类,c对应command类,m对应vo,通过proxy,用blazeds统一调用分布式的spring应用。不了解的可以自行了解,或者无需了解,因为我们今天的是问题是controller的设计问题(command类)。
三、问题
   我们一般在controller设计中有两种方法,一种是集中式设计,一种是分开式设计。flex的command自然也是这样。看看实际的例子,代码不一定对,能看明白就ok.
1.分开式设计:
先看看AddCutoverComand.as(Cutover就是网络割接,联通公司的一种业务类型)
package com.xx.controller
{
	import com.xx.model.CutoverProxy;
	import com.xx.ApplicationFacade;
	import com.xx.model.vo.CutoverVO;
	import org.puremvc.as3.interfaces.INotification;
	import org.puremvc.as3.patterns.command.SimpleCommand;
	import mx.rpc.IResponder;
	import mx.rpc.events.FaultEvent;
	
	import org.puremvc.as3.interfaces.ICommand;
	
	public class AddCutoverCommand extends SimpleCommand
	{
		override public function execute( note:INotification ) : void	
		{
			var cutoverProxy:CutoverProxy = new CutoverProxy();
			
			cutoverProxy.addCutover();
			
			sendNotification(ApplicationFacade.ADD_CUTOVER);			
		}
	}
}

然后自然的有
ModifyCutoverCommand.as,ViewCutoverCommand.as,DeleteCutoverCommand.as,QueryCutoverCommand.as,PublishCutoverCommand.as,ReplyCutoverCommand.as
等controller类。
2.我们再来看看集中式的设计:
CutoverCommand.as
package com.xx.controller
{
	import com.xx.model.CutoverProxy;
	import com.xx.ApplicationFacade;
	import com.xx.model.vo.CutoverVO;
	import org.puremvc.as3.interfaces.INotification;
	import org.puremvc.as3.patterns.command.SimpleCommand;
	import mx.rpc.IResponder;
	import mx.rpc.events.FaultEvent;
	
	import org.puremvc.as3.interfaces.ICommand;
	
	public class CutoverCommand extends SimpleCommand
	{
		var cutoverProxy:CutoverProxy = new CutoverProxy();
		override public function execute( note:INotification ) : void	
		{
			if(type=="add"){
			    addCutover(note);
                            }else if(type=="publish"){
                               publish(note);
                            }
                            //很多 if else
					
		}

                   void addCutover(...){}
                   void viewCutover(...){}
                   void publish(...){}
                   //other method

                   sendNotification(ApplicationFacade.SOME_CONSTANTS);
  	}
}

这样的结果呢就是只有一个该业务相关的Command(Controller)

四、回顾争议的引子
   争论的原因是B用的是集中式的controller设计,而A写的通用flex分页只支持分开式的command设计。谁妥协就要改动代码。最后自然是我维护B,我给出了改动的办法:
原来的分页集成代码是:
sendNotification(ApplicationFacade.SOME_CONSTANTS,Pagination);

actionscript支持动态参数,最后加了个type的参数,分页自然ok了。
sendNotification(ApplicationFacade.SOME_CONSTANTS,Pagination,type);

最后A改动量很少,只加了一个页面的属性,B不用修改代码,原先用分开式Controller设计的同事也不用修改代码。

五、不清楚puremvc
    ok,你不想看puremvc这些东西,那么想想看我们用过的struts,webwork,springmvc等框架的Controller是不是也有同样的问题。
如分开式设计的AddAction.java,DeleteAction.java,ViewAction.java
集中式设计的BizAction.java

六、我的观点
   Struts,Webwork,SpringMVC的项目我之前都有涉及过,我一律用统一式Controller设计,都是一个业务对应一个Controller,里面有自身的一些增删改查的方法。所以我的观点是很明确的,用集中式的设计。
我的理解是:
1.从语义上,Controller做控制的,只是转发一下请求到后台业务类,并不会有太多的操作,犯一着每个method,就新建一个action or command之类的东西。
2.从基于业务角色的角度出发,一个业务一个Controller。
3.维护方面,以后查看修改也方便,不用打开N多类,只在一个类里查看就行。
4.一个method,一个Controller,我觉得设计粒度太细。
5.最后,我就是喜欢集中式Controller设计。


欢迎不同观点的人拍砖,请给出你的理由和想法,谢绝谩骂,哈哈。在碰撞中进步

分享到:
评论
23 楼 东吴周郎 2010-09-20  
好好学习,天天想上
22 楼 peterwei 2010-09-20  
lewisw 写道
pengliren 写道
这个貌似你们在开发前的时候 没有沟通好造成的 跟设计没什么关系啊



说的太好了, 准, 狠, 猛

如果单从这个引子,以及出现问题的原因,你的说法完全正确。
21 楼 lewisw 2010-09-20  
pengliren 写道
这个貌似你们在开发前的时候 没有沟通好造成的 跟设计没什么关系啊



说的太好了, 准, 狠, 猛

是集中还是分散,或许只是一个粒度的把握,我们要考虑的实际问题可能很多,如果按Gof, 到时候EditController名称类就会几十几百个,我要找通过ctrl + shift + t 或者 ctrl + n 去找, 眼都要看花了, 当然你不一定这样命名, 不过我想问题总会有的。 如果都集中, 当你一个业务类有大量复杂的操作时, 你会发现你那个类里面有很多, 你这个类将变的很难维护, 我们可能可以按某一角度进行分散几个不彻底的controller.
20 楼 peterwei 2010-09-20  
ray_linn 写道
倾向分开,不喜欢集中。

分开 ----》 新业务增加新代码
集中-----》 新业务修改旧代码

从各方面来说,对已经稳定运行的代码越不去触及就越好。

你说的新业务是指方法级别的吗?如果是指新功能,新业务,新模块,那我俩的观点是一样的。如果你是指method级别的分开,那我俩就不是同一战线上的。
19 楼 peterwei 2010-09-20  
webee 写道
和楼主的意见一致,集中一个更好。至于,分页为何与这个有关,没仔细看,分页原理无非是数据加page信息,无论在哪里,都一样。分页参数少不了!

分页只是引子,和本主题没有必然联系。
18 楼 peterwei 2010-09-20  
soci 写道
我这里是按照功能模块分开,分配到人后自己维护自己的action就好了,如果集中的话多人维护一个源码版本上会经常冲突

你也没看仔细。
17 楼 peterwei 2010-09-20  
jieyuan_cg 写道
peterwei 写道
jieyuan_cg 写道
如果从GoF设计模式来说,显然集中式的controller违背了开闭原则。
如果是集中式,你每增加一个方法,都要去改变contoller的代码结构。
如果是分散式,就没有这个问题,扩展多少方法都可以支持。

Software entities should be open for extension, but closed for modification,这个就是开闭原则,你说的有一定道理。但我们不要一切唯gof是从。你说的问题在struts2及springmvc3上已经不是问题,只需简单的添加方法就行,exexute的type判断都不用了。
说说puremvc,我们项目中,我不从事flex的一线开发,不知道能不能也像springmvc3,struts2一样的通过配置文件和框架内部处理来解决type判断的问题。
以目前的情况来看,如果采用集中式,那么ApplicationFacade.as中只需注册一个CutoverCommand.as.以后修改的只是CutoverCommand.as.如果采用分开式,那么需要新添加新的Command.as,然后修改ApplicationFacade.as,添加新的注册。所以代码改动不可避免。那么我们来假设puremvc改进后,能支持不用修改ApplicationFacade.as就能动态注册新的Command.as了,type的判断自然也不会再用了。(或许puremvc已经支持,我们还没用到而已,有知道的通知一声)

flex不太懂,不过,你这样设计也未偿不可。感觉,跟springmvc的contoller有相似之处。在springmvc中,你可以给某个app写一个controller,在里面处理所有的请求。但这样总感觉别扭,不利于维护。我们采用的方式就是在一个app中,每个模块有自己的controller,但模块的controller里面可以处理这个模块所有的请求方法,呵呵。这样,如果以后扩展模块,直接再新建一个controller就可以了。
其实,开闭也分粒度。controller这个层次开闭就挺好,如果在方法层面再去开闭,那可能就不合适了。

你没看仔细,我俩的用法其实是一样的。我说的集中式,并不指整个应用的集中式(我们当然不去做框架应该做的事情,像strtus2框架,肯定是整个应用有一个集中式的分发Controller的),而是针对特定的业务,也就是你说的模块,复杂的模块的话,可能还再细分不同的controller.我指的分开式设计,就是你指的方法级别的,我认为是不必要的,你也持这样的观点。
如这样:
UserController.java,CutoverController.java,OtherBizController.java
16 楼 webee 2010-09-20  
和楼主的意见一致,集中一个更好。至于,分页为何与这个有关,没仔细看,分页原理无非是数据加page信息,无论在哪里,都一样。分页参数少不了!
15 楼 gwpking8419 2010-09-20  
集中也好,分布也好,没有固定的模式,适时而用,用到恰如其分是最好的
14 楼 chenlixun 2010-09-20  
抽象不变与变化的, 分离变化.

不变的是你的调用控制.
变化的是具体的业务调用.
做到对扩展开放,对修改关闭.

这个你懂的.
13 楼 jieyuan_cg 2010-09-20  
ray_linn 写道
倾向分开,不喜欢集中。

分开 ----》 新业务增加新代码
集中-----》 新业务修改旧代码

从各方面来说,对已经稳定运行的代码越不去触及就越好。

嗯,赞成ray_linn。不过,看他们的情况,好像还不太像springmvc,struts这样的框架。每个方法都新写一个.as文件,感觉还真有点多。
12 楼 ray_linn 2010-09-20  
倾向分开,不喜欢集中。

分开 ----》 新业务增加新代码
集中-----》 新业务修改旧代码

从各方面来说,对已经稳定运行的代码越不去触及就越好。
11 楼 soci 2010-09-20  
我这里是按照功能模块分开,分配到人后自己维护自己的action就好了,如果集中的话多人维护一个源码版本上会经常冲突
10 楼 jieyuan_cg 2010-09-20  
peterwei 写道
jieyuan_cg 写道
如果从GoF设计模式来说,显然集中式的controller违背了开闭原则。
如果是集中式,你每增加一个方法,都要去改变contoller的代码结构。
如果是分散式,就没有这个问题,扩展多少方法都可以支持。

Software entities should be open for extension, but closed for modification,这个就是开闭原则,你说的有一定道理。但我们不要一切唯gof是从。你说的问题在struts2及springmvc3上已经不是问题,只需简单的添加方法就行,exexute的type判断都不用了。
说说puremvc,我们项目中,我不从事flex的一线开发,不知道能不能也像springmvc3,struts2一样的通过配置文件和框架内部处理来解决type判断的问题。
以目前的情况来看,如果采用集中式,那么ApplicationFacade.as中只需注册一个CutoverCommand.as.以后修改的只是CutoverCommand.as.如果采用分开式,那么需要新添加新的Command.as,然后修改ApplicationFacade.as,添加新的注册。所以代码改动不可避免。那么我们来假设puremvc改进后,能支持不用修改ApplicationFacade.as就能动态注册新的Command.as了,type的判断自然也不会再用了。(或许puremvc已经支持,我们还没用到而已,有知道的通知一声)

flex不太懂,不过,你这样设计也未偿不可。感觉,跟springmvc的contoller有相似之处。在springmvc中,你可以给某个app写一个controller,在里面处理所有的请求。但这样总感觉别扭,不利于维护。我们采用的方式就是在一个app中,每个模块有自己的controller,但模块的controller里面可以处理这个模块所有的请求方法,呵呵。这样,如果以后扩展模块,直接再新建一个controller就可以了。
其实,开闭也分粒度。controller这个层次开闭就挺好,如果在方法层面再去开闭,那可能就不合适了。
9 楼 peterwei 2010-09-20  
jieyuan_cg 写道
如果从GoF设计模式来说,显然集中式的controller违背了开闭原则。
如果是集中式,你每增加一个方法,都要去改变contoller的代码结构。
如果是分散式,就没有这个问题,扩展多少方法都可以支持。

Software entities should be open for extension, but closed for modification,这个就是开闭原则,你说的有一定道理。但我们不要一切唯gof是从。你说的问题在struts2及springmvc3上已经不是问题,只需简单的添加方法就行,exexute的type判断都不用了。
说说puremvc,我们项目中,我不从事flex的一线开发,不知道能不能也像springmvc3,struts2一样的通过配置文件和框架内部处理来解决type判断的问题。
以目前的情况来看,如果采用集中式,那么ApplicationFacade.as中只需注册一个CutoverCommand.as.以后修改的只是CutoverCommand.as.如果采用分开式,那么需要新添加新的Command.as,然后修改ApplicationFacade.as,添加新的注册。所以代码改动不可避免。那么我们来假设puremvc改进后,能支持不用修改ApplicationFacade.as就能动态注册新的Command.as了,type的判断自然也不会再用了。(或许puremvc已经支持,我们还没用到而已,有知道的通知一声)
8 楼 pengliren 2010-09-20  
这个貌似你们在开发前的时候 没有沟通好造成的 跟设计没什么关系啊
7 楼 jieyuan_cg 2010-09-20  
如果从GoF设计模式来说,显然集中式的controller违背了开闭原则。
如果是集中式,你每增加一个方法,都要去改变contoller的代码结构。
如果是分散式,就没有这个问题,扩展多少方法都可以支持。
6 楼 peterwei 2010-09-20  
lewisw 写道
看看webwork, struts2, 有默认的execute方法(就是分散), 也可以指定(就可以多个方法了,就是集中),springmvc也一样有分散的abstractcontroller, 也有multicontroller支持集中, 这些大框架设计的时候都考虑了两种情况,说明分散和集中差别不会太大,起码说明A对B的指责是不对的,B的设计没什么不对。就我个人而言,我也比较喜欢集中的。

就现在的struts2还有spring3中的springmvc来说,通过通配符还有注解的方式,用集中的方式已经非常方便,我想现在几乎已经没有人用分开式Controller设计了。因为一个业务类一个Controller就足以胜任。
5 楼 peterwei 2010-09-20  
young_suse 写道
我们的项目用的是cairngorm,也是一套MVC的框架。官方推荐的是一个方法一个Command,就像你们同事A的想法一样。
不过我们觉得这样的话产生的类太多了。但是又没有类似于Struts DispatchAction,即通过配置,一个Action处理多个method功能。于是就采用了在一个Command中,通过type,用switch语句来处理不同分支。
这样我们就通过业务模块来划分Command,维护起来也挺方便的。

哈哈,cairngorm是一套adobe官方推出的比较重量级的产品,被我们用puremvc改造中。
4 楼 young_suse 2010-09-19  
我们的项目用的是cairngorm,也是一套MVC的框架。官方推荐的是一个方法一个Command,就像你们同事A的想法一样。
不过我们觉得这样的话产生的类太多了。但是又没有类似于Struts DispatchAction,即通过配置,一个Action处理多个method功能。于是就采用了在一个Command中,通过type,用switch语句来处理不同分支。
这样我们就通过业务模块来划分Command,维护起来也挺方便的。

相关推荐

    基于CAN总线的智能车控制系统的设计.pdf

    集中式设计将主控、循迹、驱动等功能集成在同一块电路板上,适合于简单任务和数据通信量小的应用场景。然而,随着智能车竞赛的复杂度增加,这种设计方式的局限性逐渐显现,如实时性、可靠性和可扩展性不足。 ...

    PLC 上位软件在电厂自控系统中的应用方案.pdf

    WINCC的特性包括强大的HMI(Human Machine Interface)系统,内置SQL服务器的归档系统,以及支持IEC 61131的集中式工程系统。此外,其灵活的现场总线集成、报警设置、数据存档和报表设计功能,以及对C脚本的支持,...

    AD域、DNS分离+额外域控制器安装-及主域控制器损坏解决方法.doc

    通过AD,可以实现集中式的身份验证、授权和资源管理。当主域控制器(PDC,Primary Domain Controller)损坏时,备份域控制器(BDC,Backup Domain Controller)可以接管服务,确保服务连续性。 2. DNS分离:在AD...

    分享代码了ios的项目代码

    5. **Model-View-Controller (MVC)**:iOS开发中广泛采用的设计模式,它将数据(Model)、视图(View)和控制逻辑(Controller)分开,使得代码更易于管理和维护。 6. **网络通信**:由于项目名为“YiChatTest”,...

    vue学习文档.pdf

    而 Vuex 是 Vue.js 应用的状态管理模式,它集中式存储管理应用所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。 在构建实际应用时,Vue.js 也具备与第三方库或已有项目整合的能力,这使得在...

    搜索链接深度学习网址导航系统 v0.0.16(jsp)-jspurl.zip

    【搜索链接】深度学习网址导航系统 v0.0.16(jsp) 是一个基于JSP技术构建的网络应用,旨在为用户提供一个集中式的深度学习资源检索平台。这个系统允许用户方便地查找、收藏和分享关于深度学习的各种在线资源,如教程...

    tacacs.net安装文件

    **TACACS(Terminal Access Controller Access Control System)网络服务是一种集中式身份验证、授权和会计(AAA,Authentication, Authorization, and Accounting)协议,主要用于网络设备的管理。它为网络管理员...

    思科ACS认证服务器安装文件

    1. **ACS(Cisco Adaptive Security Appliance)**:ACS全称为思科适应性安全设备,实际上它是一种集中式的网络访问控制解决方案。它的主要功能是提供身份验证、授权和审计服务,以确保只有经过身份验证的用户和设备...

    基于python的自动化测试框架在Scrum开发模式中的应用

    Scrum是一种流行的敏捷开发框架,采用增量式的迭代开发过程。一个完整的开发周期被细分为多个短周期(称为Sprint),每个Sprint周期通常为2到4周,旨在每个迭代结束时都能交付潜在可交付的产品增量。然而,要在每个...

    spring 控制反转和依赖注入.docx

    1. Spring Core:主要模块(组件),BeanFactory,是创建 JavaBean 的工厂,使用 IOC 模式,通过 ID 赋值,将应用程序的配置和依赖性的规范,与实际的应用代码分开。 2. Spring AOP:切面编程,将事务管理集成到...

    单片机原理与应用--习题答案

    单片机还可以被称为**嵌入式控制器(Embedded Controller)**或**微控制器(Microcontroller)**。 **1.3 单片机系统的主要组成部分** 单片机系统将以下几部分集成在一块芯片上: - **CPU**(中央处理器) - **RAM**...

    化工仪表自动化判断题.pdf

    1. 活塞式压力计的工作原理:活塞式压力计通过加砝码产生压力,压力与砝码质量和活塞面积成正比,因此题目中的第一题和第二题涉及到活塞式压力计的操作和设计规范。 2. 节流装置的安装要求:节流装置通常需要上游和...

    DamianDev03.github.io:TELE4网站

    5. **MVC(Model-View-Controller)架构**:如果项目规模较大,可能采用了MVC设计模式,将模型、视图和控制器分开,以便更好地组织代码。 6. **GitHub工作流**:作为GitHub上的项目,可能使用了版本控制、拉取请求...

    Java /JSP代码安全规范

    **2.3.1 集中式输入验证** - **统一入口**:设置一个统一的输入验证点,对所有输入数据进行验证。 - **白名单与黑名单**:推荐使用白名单策略,只接受预期的输入值。 **2.3.2 服务器端输入验证** 客户端的输入...

Global site tag (gtag.js) - Google Analytics