- 浏览: 24272 次
- 性别:
- 来自: 苏州
最新评论
-
BlueMeteorolite:
哦,只有JAVA端(Cache)的设计。兴趣不大。啥时候来个F ...
Flex + Java 中小型项目的代码结构研究(二)(如何在业务层管理你的Cache) -
raylin:
关键是Review的 Scope 很重要。大家不妨在这个话题上 ...
发个无聊的贴子,看看大家怎么看code review的 -
raylin:
andyhu1007 写道code review: 费时,费力 ...
发个无聊的贴子,看看大家怎么看code review的 -
mindxw:
younggun 写道xuby 写道什么pair/review ...
发个无聊的贴子,看看大家怎么看code review的 -
mindxw:
kimmking 写道传统的公司中,pair不可想象,
试问 ...
发个无聊的贴子,看看大家怎么看code review的
Flex Structure
前言
这两天写了一个研究Flex + Java的例子,供大家参考,这个例子主要是出于以下几点考虑的
<!---->1. <!---->系统性能和系统可维护性上的平衡(Value Object lazy load)
<!---->2. <!---->开发效率和代码可读性上的平衡(Command and CommandManager)
<!---->3. <!---->如何让Flex调用服务端的Service(AMF3, Remote Object)
<!---->4. <!---->使用Cache Framework提升我们的性能
花絮:其实做项目和生活,管理等等都是一样,做到最好是不太现实的,但要和谐,什么叫和谐?就是在成本,进度,质量等外在压力下把代码写得最好!所以我下面的例子代码也是一样,追求的是一个平衡J
<!---->一. <!---->系统性能和系统可维护性上的平衡(Value Object lazy load)
最佳性能时,系统只在网络上传输必要的数据,如显示用户清单时只传输user name和department name。
而结构最优时,传输的却是规范的数据结构。
这个时候矛盾来了
<!---->A. <!---->传输规范的数据结构。这时候必然会带上一些冗余数据,如显示用户清单时传输的UserVO,而UserVO里同时也包含了标志这个用户部门的DepartmentVO,这时就会带来不必要的数据传输,如果显示的用户清单有100条,那么这100个UserVO里面的DepartmentVO必然会带来不小的数据冗余。
<!---->B. <!---->只在网络上传输必要的数据。这时有两种方法可以做到,设计一个UserListVO,里面包含user name和department name这两样field,然后在Business Logic里组装这个UserListVO。但这种方法显然有个大的缺点,这个VO或对应的业务逻辑代码不可以共用,因为不同的地方会有不同的业务需求,比如有一个模块中会要显示用户的年龄。另一个方法就是,使用规范的数据结构,但只为这些数据结构中必要的栏位设值,如上面所说的,可以只为userVO.departmentVO.name设值,但其它栏位保持null,显然,这个VO的共用性也不好,因为我没法知道这个VO里面的栏位是否已经被设值了。
综上所说,所以我取上面两种方法的一个中间点来解决这个问题(如下图),即使用完整的数据结构来存储数据,但不是必要的数据不会被加载上来,如果要用时,可以通过Lazy Load的方式加载。如UserVO里有DepartmentVO,但在显示清单时不需要user对应的department信息,在编辑时才需要,所以我们可以在popup出用户编辑窗口的时候才在UserVO的getDepartmentVO()方法中加载相应的DepartmentVO。
请参见附件中的class diagram for data model
<!---->二. <!---->开发效率和代码可读性上的平衡(Command and CommandManager)
往往在开发的时候,标准的结构会多写很多代码,虽然结构很清晰,但老实说,对于我们的项目,好像不需要这样“清晰”,比如Cairngorm中有command, event, controller等等,这确实是一种清晰的结构,但写起来很麻烦,所以我下面设计了一种简化的结构来实现它(如下图)。
Class Diagram
请参见附件中的class diagram for command
Sequence Diagram
请参见附件中的sequence diagram for command pattern
关于Command Pattern,请参考以下的链接
http://www.javaworld.com/javaworld/jw-06-2002/jw-0628-designpatterns.html
这里,CommandManager就是那个Invoker。而com.novem.farc.command.UserSaveCommand.datagrid就是那个receiver。
Why not Cairngorm Event or Command?
我们以查找一个user为例,来看看Cairngorm是怎么调用一个Command并返回结果的。
<!---->1. <!---->创建一个CairngormEvent,并在这个Event里要有一个userId:Number的field。
<!---->2. <!---->创建一个Command,这个Command要实现两个接口,ICommand和IResponder。
<!---->3. <!---->创建一个FrontController来建立Event和Command的关连。
然后,在客户端调用的时候,书写如下的代码:
var event: EventFindUser = new EventFindUser ();
event.userId = userVO.id;
CairngormEventDispatcher.getInstance().dispatchEvent( event );
我们现在新的结构是这样实现的:
var command:CommandFindUser = new CommandFindUser();
command.userId = userVO.id;
NovemCommandManager.execute(command);
可以看出来,Cairngorm通过注册Event,并通过Event来传递输入参数,而我们自己的结构是将参数直接传递给Command,所以Cairngorm并没有给我们提供特别的方便,反而增加了不少麻烦的Event,而它提供的这种解耦,也并不实在。
Why not Cairngorm Model Locator?
Cairngorm Model Locator提供的其实是一种静态全局变量。
那么,谁都可以来改变这个Model Locator中的值,这显然是一个很危险的事。
如果大家也和我一样认为Cairngorm Model Locator就是一种静态全局变量的话,我想我在这里不用说得太多,只要去查一下静态全局变量的好处坏处就可以了。
<!---->三. <!---->如何让Flex调用服务端的Service(AMF3, Remote Object)
暂且假定,我们的项目使用的Remote Object方式去访问服务端
Why not Cairngorm Delegate?
老规矩,我们先来看看Cairngorm是怎么来调用服务端的
<!---->1. <!---->在service.xml里添加配置项<mx:RemoteObject/>
<!---->2. <!---->创建Delegate.as,并为RemoteObject添加对应的方法(这里需要为每个服务端对象都创建对应的Delegate和方法,工作量不但不小,而且很烦哦)
再来看看我们的写法吧:
1.在ServiceFactory里添加需要调用的Service和method的名字常量
2.调用方法
ServiceFactory.getService(ServiceFactory.USER_BIZ)
.callService(ServiceFactory.USER_BIZ_INSERT, [newVO], this.result);
<!---->四. <!---->使用Cache Framework提升我们的性能
有空再做哦……
但主要的思路是使用第三方的Cache工具在业务层做Cache
评论
--管理员的分割线--
JavaEye禁止在论坛留邮箱,请用站内短信
太大了,我发邮件给你,告诉我,你的邮箱吧
--管理员的分割线--
JavaEye禁止在论坛留邮箱,请用站内短信
{
var responder:LazyLoaderResponder;
if(departmentVO == null && !isNaN(departmentId))
{
responder = new LazyLoaderResponder(this, "departmentVO");
ServiceFactory.getService(ServiceFactory.DEPARTMENT_BIZ).callServiceWithResponder(ServiceFactory.DEPARTMENT_BIZ_LOAD, [departmentId], responder);
}
return departmentVO;
}
But you still have a "return departmentVO" to Return a object from your function. This is null object if you call this method.
it is impossible to RETURN departmentVO in Asyc function.
That is my point.
anyway your LazyLoaderResponder looks clean
Could you post your LazyLoaderResponder ?
Thanks
这个问题问得非常好,我也确实遇到这个问题,但经过测试后,没有发现问题
我在server端的load department方法里加了一个Thread.sleep(10000); 测下来没有问题
另外,我有一个疑惑还没有来得及研究,那就是,如果我的datagrid只有一条记录,为什么我的label function会被调用4次,两次departmentVO为null,两次是有值的
LazyLoaderResponder的代码
package com.xxxxx.common.responder { import mx.controls.Alert; import mx.rpc.IResponder; public class LazyLoaderResponder implements IResponder { private var _target : Object; private var _fieldName : String; public function LazyLoaderResponder(target:Object, fieldName:String) { _target = target; _fieldName = fieldName; } public function result( data : Object ) : void { _target[_fieldName] = data; } public function fault( info : Object ) : void { Alert.show("Lazy load "+_target+"."+_fieldName+" failed!"); } } }
I guess it is ur datgrid has more than 1 column, u can try to cut ur column to see if u get less call for ur lable function
仍然有4次调用的,并且不幸的是,有两次都会去server端拿值,这个比较麻烦
我后面再研究研究这个问题,看看到底是哪里派发了四次这个事件
{
var responder:LazyLoaderResponder;
if(departmentVO == null && !isNaN(departmentId))
{
responder = new LazyLoaderResponder(this, "departmentVO");
ServiceFactory.getService(ServiceFactory.DEPARTMENT_BIZ).callServiceWithResponder(ServiceFactory.DEPARTMENT_BIZ_LOAD, [departmentId], responder);
}
return departmentVO;
}
But you still have a "return departmentVO" to Return a object from your function. This is null object if you call this method.
it is impossible to RETURN departmentVO in Asyc function.
That is my point.
anyway your LazyLoaderResponder looks clean
Could you post your LazyLoaderResponder ?
Thanks
这个问题问得非常好,我也确实遇到这个问题,但经过测试后,没有发现问题
我在server端的load department方法里加了一个Thread.sleep(10000); 测下来没有问题
另外,我有一个疑惑还没有来得及研究,那就是,如果我的datagrid只有一条记录,为什么我的label function会被调用4次,两次departmentVO为null,两次是有值的
LazyLoaderResponder的代码
package com.xxxxx.common.responder { import mx.controls.Alert; import mx.rpc.IResponder; public class LazyLoaderResponder implements IResponder { private var _target : Object; private var _fieldName : String; public function LazyLoaderResponder(target:Object, fieldName:String) { _target = target; _fieldName = fieldName; } public function result( data : Object ) : void { _target[_fieldName] = data; } public function fault( info : Object ) : void { Alert.show("Lazy load "+_target+"."+_fieldName+" failed!"); } } }
I guess it is ur datgrid has more than 1 column, u can try to cut ur column to see if u get less call for ur lable function
{
var responder:LazyLoaderResponder;
if(departmentVO == null && !isNaN(departmentId))
{
responder = new LazyLoaderResponder(this, "departmentVO");
ServiceFactory.getService(ServiceFactory.DEPARTMENT_BIZ).callServiceWithResponder(ServiceFactory.DEPARTMENT_BIZ_LOAD, [departmentId], responder);
}
return departmentVO;
}
But you still have a "return departmentVO" to Return a object from your function. This is null object if you call this method.
it is impossible to RETURN departmentVO in Asyc function.
That is my point.
anyway your LazyLoaderResponder looks clean
Could you post your LazyLoaderResponder ?
Thanks
这个问题问得非常好,我也确实遇到这个问题,但经过测试后,没有发现问题
我在server端的load department方法里加了一个Thread.sleep(10000); 测下来没有问题
另外,我有一个疑惑还没有来得及研究,那就是,如果我的datagrid只有一条记录,为什么我的label function会被调用4次,两次departmentVO为null,两次是有值的
LazyLoaderResponder的代码
package com.xxxxx.common.responder { import mx.controls.Alert; import mx.rpc.IResponder; public class LazyLoaderResponder implements IResponder { private var _target : Object; private var _fieldName : String; public function LazyLoaderResponder(target:Object, fieldName:String) { _target = target; _fieldName = fieldName; } public function result( data : Object ) : void { _target[_fieldName] = data; } public function fault( info : Object ) : void { Alert.show("Lazy load "+_target+"."+_fieldName+" failed!"); } } }
{
var responder:LazyLoaderResponder;
if(departmentVO == null && !isNaN(departmentId))
{
responder = new LazyLoaderResponder(this, "departmentVO");
ServiceFactory.getService(ServiceFactory.DEPARTMENT_BIZ).callServiceWithResponder(ServiceFactory.DEPARTMENT_BIZ_LOAD, [departmentId], responder);
}
return departmentVO;
}
But you still have a "return departmentVO" to Return a object from your function. This is null object if you call this method.
it is impossible to RETURN departmentVO in Asyc function.
That is my point.
anyway your LazyLoaderResponder looks clean
Could you post your LazyLoaderResponder ?
Thanks
这一点我倒也曾经和你一样担心过这个问题,但Flex其实给我提供了一个data binding的功能,所以如果我们并不需要同步响应的时候,就让它异步好啦
当响应从Server端返回时,在它的result方法里改变页面component所binding的对象的值,Flex会帮你做自动的更新
Flex给我提供的data binding的功能确实好用,但是按照上面的实现,我们所提供的getXXXX方法API的语义就不稳定了,再一定程度上会造成使用者的混乱,可能需要加强团度的培训,以使所有成员都必须清楚地认识到这一点。
你这一点算是说到我心里去了
这也是我遇到的一个问题之一,也还没有再做深入的研究,有这方面的经验分享一下吗?
这是我的UserVO.as中的代码
[Bindable] public var departmentVO : DepartmentVO; //todo //why cannot use "get departmentVO()", and bind userVO.departmentVO.name to datagrid public function getDepartmentVO():DepartmentVO { var responder:LazyLoaderResponder; if(departmentVO == null && !isNaN(departmentId)) { responder = new LazyLoaderResponder(this, "departmentVO"); ServiceFactory.getService(ServiceFactory.DEPARTMENT_BIZ).callServiceWithResponder(ServiceFactory.DEPARTMENT_BIZ_LOAD, [departmentId], responder); } return departmentVO; }
首先感谢你分享思路,说实话,我也刚开始这方面的工作,还没有深入研究,如果有好的实践一定与大家分享。
It is impossible to use
"function getDepartmentVO():DepartmentVO "
to get the return DepartmentVO
Because you use Remote Object!
Generally the Sychronize way you can use
function getDepartmentVO():DepartmentVO {
dosmothing;
return DepartmentVO ;
}
But ASycronize way you cant do this
it should be :
[Bindable]
var returnVO:DepartmentVO;
function getDepartmentVO():void{
myservice.getVOByRemoterObject();
the RemoteObject.addListener("getDepartment", theDepartmentVOHandler);
}
function theDepartmentVOHandler(event Resultevent){
returnVO = event.casttoDepartmentVO;
}
it is impossible to getDepartmentVO() directly
Please take a look at following two lines
responder = new LazyLoaderResponder(this, "departmentVO"); ServiceFactory.getService(ServiceFactory.DEPARTMENT_BIZ).callServiceWithResponder(ServiceFactory.DEPARTMENT_BIZ_LOAD, [departmentId], responder);
LazyLoaderResponder is the event handler
It's the same solution you provide
这一点我倒也曾经和你一样担心过这个问题,但Flex其实给我提供了一个data binding的功能,所以如果我们并不需要同步响应的时候,就让它异步好啦
当响应从Server端返回时,在它的result方法里改变页面component所binding的对象的值,Flex会帮你做自动的更新
Flex给我提供的data binding的功能确实好用,但是按照上面的实现,我们所提供的getXXXX方法API的语义就不稳定了,再一定程度上会造成使用者的混乱,可能需要加强团度的培训,以使所有成员都必须清楚地认识到这一点。
你这一点算是说到我心里去了
这也是我遇到的一个问题之一,也还没有再做深入的研究,有这方面的经验分享一下吗?
这是我的UserVO.as中的代码
[Bindable] public var departmentVO : DepartmentVO; //todo //why cannot use "get departmentVO()", and bind userVO.departmentVO.name to datagrid public function getDepartmentVO():DepartmentVO { var responder:LazyLoaderResponder; if(departmentVO == null && !isNaN(departmentId)) { responder = new LazyLoaderResponder(this, "departmentVO"); ServiceFactory.getService(ServiceFactory.DEPARTMENT_BIZ).callServiceWithResponder(ServiceFactory.DEPARTMENT_BIZ_LOAD, [departmentId], responder); } return departmentVO; }
首先感谢你分享思路,说实话,我也刚开始这方面的工作,还没有深入研究,如果有好的实践一定与大家分享。
It is impossible to use
"function getDepartmentVO():DepartmentVO "
to get the return DepartmentVO
Because you use Remote Object!
Generally the Sychronize way you can use
function getDepartmentVO():DepartmentVO {
dosmothing;
return DepartmentVO ;
}
But ASycronize way you cant do this
it should be :
[Bindable]
var returnVO:DepartmentVO;
function getDepartmentVO():void{
myservice.getVOByRemoterObject();
the RemoteObject.addListener("getDepartment", theDepartmentVOHandler);
}
function theDepartmentVOHandler(event Resultevent){
returnVO = event.casttoDepartmentVO;
}
it is impossible to getDepartmentVO() directly
这一点我倒也曾经和你一样担心过这个问题,但Flex其实给我提供了一个data binding的功能,所以如果我们并不需要同步响应的时候,就让它异步好啦
当响应从Server端返回时,在它的result方法里改变页面component所binding的对象的值,Flex会帮你做自动的更新
Flex给我提供的data binding的功能确实好用,但是按照上面的实现,我们所提供的getXXXX方法API的语义就不稳定了,再一定程度上会造成使用者的混乱,可能需要加强团度的培训,以使所有成员都必须清楚地认识到这一点。
你这一点算是说到我心里去了
这也是我遇到的一个问题之一,也还没有再做深入的研究,有这方面的经验分享一下吗?
这是我的UserVO.as中的代码
[Bindable] public var departmentVO : DepartmentVO; //todo //why cannot use "get departmentVO()", and bind userVO.departmentVO.name to datagrid public function getDepartmentVO():DepartmentVO { var responder:LazyLoaderResponder; if(departmentVO == null && !isNaN(departmentId)) { responder = new LazyLoaderResponder(this, "departmentVO"); ServiceFactory.getService(ServiceFactory.DEPARTMENT_BIZ).callServiceWithResponder(ServiceFactory.DEPARTMENT_BIZ_LOAD, [departmentId], responder); } return departmentVO; }
你对哪一个知识点感兴趣,我放上来和大家共享
或者后面有时间的话,我整理一下,放些代码上来
蛮好的啊
其实就是fds的免费版
flex+bds的研究已经告一段落
现在在用flex+bds尝试写一个网游的demo
More on RPC in Adobe Flex Applications with AMF, BlazeDS, and/or GraniteDS
http://www.infoq.com/news/2007/12/more-on-rpc-in-flex-with-amf;jsessionid=C357C8E63A2DE1D89B645B2616D45F31
BlazeBench: Why you want AMF and BlazeDS
http://www.jamesward.org/wordpress/2007/12/12/blazebench-why-you-want-amf-and-blazeds/
这一点我倒也曾经和你一样担心过这个问题,但Flex其实给我提供了一个data binding的功能,所以如果我们并不需要同步响应的时候,就让它异步好啦
当响应从Server端返回时,在它的result方法里改变页面component所binding的对象的值,Flex会帮你做自动的更新
LZ研究过否?
当时,我用amf2时,3还是beta。
Remote Object是Flex与Server端交互性能最高的一种方法,同时也最符合我们的代码编写习惯,只是FDS费用不少,而GDS又不算太成熟,麻烦~~~
这是它新的Spec
http://download.macromedia.com/pub/labs/amf/amf3_spec_121207.pdf
它的反序列化的性能好像不是太好,但不好到什么程度倒是没作具体的研究,如果有朋友有研究数据的话,希望能分享一下
LZ研究过否?
当时,我用amf2时,3还是beta。
发表评论
-
发个无聊的贴子,看看大家怎么看code review的
2008-06-16 15:33 3394最近公司在搞流程改进 ... -
我们是否可以正面回答这些提问?
2008-05-19 15:19 949今天看了很多同学讨论公司管理和项目管理的贴子,我就想把我一直在 ... -
八褂贴:大家还是坚守Java阵营吧,仍然排名第一呢
2008-03-04 09:42 1141大家还是坚守Java阵营吧,仍然排名第一呢 http://ww ... -
Flex + Java 中小型项目的代码结构研究(二)(如何在业务层管理你的Cache)
2008-02-20 14:20 2552Flex Structure 2 如何在业务层管理你的Cac ...
相关推荐
此外,还可以学习到如何在实际项目中运用面向对象编程原则和设计模式,以及如何组织和管理代码结构。对于初学者来说,这是一个很好的实践项目,可以帮助他们提升技能,并理解Web应用开发的基本流程。
3. "bbs项目.rar":这是论坛项目的主要源代码压缩包,解压后应该包含Flex和Java的源文件,以及相关的配置和数据库文件,是研究项目核心功能和结构的关键。 4. "小型企业管理系统.rar":虽然不是直接与BBS项目相关,...
- **新建项目**:创建一个新的Flex项目,用于GIS应用开发。 - **使用地图**:集成地图服务,如Google Maps API,展示地图信息。 - **地图使用范围设置**:定义地图的显示范围和层级。 - **添加工具栏**:提供地图...
第二种方法则更有利于提高开发效率,尤其是在中小型项目中优势明显;第三种方法适用于已有Java Web基础的项目,通过添加Flex组件实现功能升级。无论哪种方式,合理的配置和良好的实践都是实现高效开发的关键。
在本案例中,我们遇到了一个关于使用Java和Flex的小型示例项目的问题,该问题导致了404错误,这通常意味着服务器无法找到请求的资源。通过分析描述,我们可以推断出这个问题可能是由于版本不兼容性造成的。 Java是...
Flex + Java 中小型项目的代码结构研究 关于开发STRUTS+SPRING+Hibernate生成器的提议! 为何代码生成器都要这么智能呢? 推荐圈子: flex 更多相关推荐 Pomer是几个无聊的人利用业余时间做的希望不是无聊的一个...
这种设计方式简洁明了,适用于小型项目或学习案例。 ```sql CREATE DATABASE userdb; USE userdb; CREATE TABLE userinfo ( id INT(10) NOT NULL AUTO_INCREMENT, username VARCHAR(20), password VARCHAR(20), ...
Flex IOC(Inversion of Control,控制反转)框架是ActionScript编程中的一个重要概念,它通过将对象的创建和管理从应用程序的主体部分分离出来,提高了代码的可重用性和可测试性。在本示例中,我们将探讨四个常用的...
6. **文件结构**:虽然未提供具体的文件内容,但"firstFlext"可能是项目根目录,其中包含SWF(Flex编译出的可执行文件)、AS或MXML源代码、资源配置、库文件以及与Java后端交互的代理类等。 7. **运行与调试**:在...
综上所述,"Flex_JSON_XML.zip_flex"这个压缩包中的示例很可能包含了如何在Flex客户端和Java服务器之间设置XML和JSON数据交换的步骤、代码示例和可能的配置文件。Flex应用通过HTTP请求发送JSON或XML数据,Java服务器...
- 当项目达到一定规模时,引入MVC框架(如Cairngorm)可以帮助更好地组织代码结构,遵循MVC设计模式,使得项目更加模块化,易于扩展和维护。 4. **咔嚓FrontController的Cairngorm** - 在Cairngorm基础上进一步...
为了实现在线浏览,通常会使用Java Applet,这是一个嵌入在HTML页面中的小型Java应用程序。Applet可以与JavaScript交互,接收用户的操作,并处理PDF的动态加载和页面翻转。然而,由于现代浏览器的安全限制和对Flash...
2. **Cairngorm框架**:在Flex中,项目采用了Cairngorm框架,这是一个轻量级的MVC模式实现,有利于组织和管理代码,特别适合小型系统的开发。Cairngorm包括控制器、服务代理、模型、视图和命令等组件,它们协同工作...
在Adobe Flex Builder 3中,开发富互联网应用程序(RIA)时,经常需要在不同组件之间交换数据或参数。这是构建动态、交互式用户界面的关键环节。本教程将深入探讨Flex中组件之间的参数传递机制,帮助你更好地理解和...
Cairngorm是一个流行的Flex应用程序架构,它采用了MVC设计模式,有助于更好地组织代码结构,提高开发效率。 2. **数据持久化**:选择了MyBatis(Ibatis)作为数据持久化框架,它可以实现动态SQL查询,简化复杂的...
Java和Flash是两种在Web开发中广泛使用的技术,它们各自有着独特的优势,但在某些场景下,需要进行跨平台的交互,比如游戏开发、富互联网应用(RIA)等。本资料"java_and_flash.rar"主要探讨的就是Java和Flash之间的...
Decagon是一款由Albert-Flex开发的简单游戏引擎,它完全使用Java编程语言编写,并且构建在OpenJFX框架之上。OpenJFX是JavaFX的一部分,是Oracle为Java平台提供的一个现代、高性能的用户界面(UI)工具包,用于构建...
J2EE还包括EJB(Enterprise JavaBeans)、JNDI(Java Naming and Directory Interface)、RMI(Remote Method Invocation)、JMS(Java Message Service)、JAVA IDL、JTS、JTA、JAVAMAIL、JAF、Log4j、JUnit、...