高效率的超大规模Flex开发

Adobe Flex开发与传统的Web开发有很多不同之处。正确的理解和利用这些不同之处,可以帮助我们创建更丰富的用户体验,也可以反过来增加网站的可用性以及浏览和更新速度。Flex还提供了大量的组件和技术库来让Web开发更加轻松——它提供的强大工具要远远超过传统Web 2.0中的异步JavaScript和XML(Ajax)应用。此外,Adobe公司最近发布的Adobe Flash Builder 4 beta(以前叫Adobe Flex Builder)中提供了许多新的和改进的工具,他们可以用来开发大规模的Flex应用程序。Flash Builder 4着重于提高开发人员的生产力以及设计人员和开发人员的工作流。

Flex开发中的关键要素之一是使用模块和运行时共享库(Runtime Shared Libraries,RSLs),这些模块和库可以方便系统不同部分的并行开发以及客户端上高效的内存管理等等。另外一个关键要素是使用Sprint BlazeDS集成,它大大简化了后台不同技术服务器端的开发和集成,如使用Java消息服务(JMS)和Spring安全进行的通信。

以下是Flex开发中的一些关键要素:

  • 利用Flex的不同之处。了解为什么Flex开发与传统Web开发有所不同,并利用那些不同之处让应用程序从中获益。
  • Flex模块。了解Flex模块以及怎样模块化Flex开发和部署。使用Flex模块来解耦项目中的不同层次。
  • 了解反模式和模式。 预先了解正确的应用程序反模式,这样你可以按照正确的架构模式实现优秀的设计。
  • 使用Spring BlazeDS集成项目简化开发。使用Spring BlazeDS 集成项目简化Java服务器集成。
  • 有效地设计。与设计团队紧密合作,充分利用Flex和Adobe Flash的优势。
  • 测试. 预先计划测试。

是什么让Web开发与Flex有所不同?

与传统Web应用程序不同,Flex应用程序开发更像传统的桌面应用开发。例如,整个应用程序会被下载到客户端——这是一个庞大的下载,而且取决于应用程序如何组织。当然,有许多方法可以优化这个过程,例如使用组件库或将工程分解成各个模块。

这套方法与传统的超文本标记语言(Hypertext Markup Language,HTML)编写的应用程序不一样——即使它是用Ajax开发的。一个HTML的Web站点通常可以划分成不同的页面,以使得下载量非常小。并且即使使用Ajax,下载量还是相对较小,因为大部分Ajax库本身就相对较小。使用这种方法可以让单个页面的下载量比整个应用程序更小。

Flex与传统Web应用程序开发的另外一个不同之处在于,状态主要在客户端上维护。这超出了在Web应用程序上使用Ajax控件,因为后者一般只在Web浏览器上维护少量的客户端状态。而现在,应用程序中的所有状态都在局部变量中进行维护。

如果你还不太熟悉Flex的话,另外一个不同之处可能对于你来说是一个挑战。Flex使用了一个高度的事件驱动编程风格,主要原因是Adobe Flash Player是单线程的,因此任何需要长时间运行的调用都需要注册一个回调函数。单线程对于图形化用户界面(GUI)开发来说是有利的,因为它不存在死锁或者一个线程窃取所有CPU周期,从而保持了GUI的响应。单线程还使得开发更加简单,因为你不需要处理多线程编程。(还记得在Swing中处理线程的噩梦吗?)

Flex中用以处理事件的主要机制是函数指针,或者作为函数参数进行传递的闭包。这些指针可以是用户为了某个异步事件结束时发生的事件或者提醒而注册的。(函数指针对于Java程序员来说很有挑战,因为核心Java语言还不支持闭包。)

Flex模块至关重要

Flex提供了一些选项可以将应用程序划分成模块,包括创建库以及主应用程序的子模块。通过将项目设计成层次化的形式,开发和编译都可以在单个的分支中进行。

模块化Flex项目的主要好处在于,这么做可以优化客户端上下载和启动的时间。应用程序的一小部分可以预先下载到客户端,而剩下的部分可以在后端按需很进行加载。此外,模块还可以被加载和卸载,以减少客户端上的内存占用量。

模块化Flex项目的另一个主要好处是,它可以让开发过程更容易模块化。它允许开发人员在不同的模块和库上进行工作以避免开发团队的死锁发生。

然而构建大型Flex应用程序的一个挑战之处在于,编译过程所花的时间要比大部分程序员熟悉的Java编译时间要慢很多。重新编译一个大型Flex应用程序可以花上好几分钟。想要优化这个过程,你可以创建分离的库并且只编译你当前工作的应用程序部分。

一种方法是采用SWC文件形式的库。SWC是Flex中使用的主要存档格式,它有点类似于Java中的Java存档(JAR)文件。你可以使用SWC档案来完成一些工作:

  • 组件库。 组件库是一个SWC文件,它包含Flex应用程序中使用的类和其他资源。
  • 主题。主题定义了应用程序的观感。它包含主题所需的资源(例如图片文件和字体),以及定义这些资源如何被使用在应用程序中的层叠样式表(Cascading Style Sheet,CSS) 。
  • 资源包。这些都是本地化的属性文件和Adobe ActionScript类集。

有两种方法可以在项目中添加SWC文件:要么静态地连接它们,这种情况下它们会编译进你的项目;要么把它们当做运行时共享库(RSL,Runtime Shared Library )来使用。使用多个RSL的好处在于它们可以被分开下载和缓存到客户端上。此外,如果客户端有多个模块的话,它们还可以共享同样的RSL。

你还可以将主应用程序进行模块化。一种方式是采用Flex模块;另一种是使用子应用程序。子应用程序的好处在于它们独立于主应用程序进行开发和测试。

注意当编译模块和库时,Flex并不像Java一样层次地遍历整个树。相反它只编译链接到主应用程序中的部分。这种方式会使得模块和库的开发非常微妙,因为你可能注意不到某个文件被链入了。当进行库开发的时候,有必要定义哪些文件会被包含。

库具有相对直接的可被利用的优势。本质上你是向Flex模块管理器传递了想要加载模块的URL。

    protected function getModuleFromServer(url:String, onSuccess:Function) :void
    {
       var module:IModuleInfo = ModuleManager.getModule(url);
           module.addEventListener(ModuleEvent.READY, loadModuleSuccessHandler);
            module.load();
    }

    public function loadModuleSuccessHandler(moduleEvent:ModuleEvent) :void {
        var module:IModuleInfo = moduleEvent.module;
	  .... handle initializing the module
    }

像这样进行模块加载的有趣之处在于你可以指定另一个URL来加载这个模块——例如,在某个故障情况下,客户端丢失了与主服务器的连接。这时客户端可以继续从另外一个URL中加载模块,以维护重要的业务功能。

让应用程序轻松地开发和测试

通过适当地激活View栈(Stack),你可以用单个URL轻松地访问应用程序的任何点——这一功能拥有超越单纯可用性上的优势。除此之外它还使得应用程序上的工作变得很轻松。一个常见的错误发生在你改动部分应用程序,而这个应用程序需要在好几个屏幕和样式中进行导航。如果你不得不为每一处改动而手工进行导航时,这个过程将非常耗时。取而代之,我们可以使用一个固定的URL来访问应用程序的不同部分,这将大大减轻开发中的痛苦并且加速整个过程。相同的模式同样可以让应用程序变得很容易测试,因为应用程序单个部分可以通过URL来访问和测试。

在Flex中,有两种方法可以将视图栈构建到应用程序中。一种方法是使用状态(states),而另一种方法则是使用一个ViewStack组件(ViewStack.mxml)。视图栈只是用来显示对象的栈:这些对象可以是一个包装简单的表格或是一个复杂组件的画布(canvas )。使用视图栈的好处在于你可以通过在代码中设置当前的子组件来轻松的操作它们。例如 myViewStack.selectedChild=accountInfo 将会设置视图栈去显示accoutInfo视图。这个功能可以让你在测试和开发中轻松地操作视图栈。

客户端架构:反模式

在软件编程中,会有一个通用的范式来定义软件开发中的反模式和模式。模式是解决常见问题的重复解决方案;反模式则是不熟悉语言的程序员最会发生的常见错误。定义好Flex中的模式和反模式后,我将会展示一些新手Flex程序员常犯的错误,然后再展示一些Flex编程开发的最佳实践。

这些实践可以帮助项目在增长为大规模的过程中,避免常见的错误。第一个通用的反模式是将所有的MXML视图放在根包中。这么做的好处不是很明显,因为你可以将MXML文件放入到包中,并且通过它们的名字空间(由于实际的包的名字可能没有在文件中指定)进行引用。其实MXML文件是根据其所在的目录结构来放入包当中的。因此将MXML文件放入到根包中等价于不将它们放入任何包中,这样做会使一个大型项目变得一团糟。

举一个例子,Flex商店示例不仅将主应用程序文件放入到根包中,还将主页,商品页和支持页(HomeView.mxml, ProductsView.mxml, SupportView..mxml)都放入根包中。这个过程和把所有根目录中的视图包放入一个Java包中比较类似。

开发人员在创建第一个应用程序时常常会碰到一个问题:那就是如何用视图来捆绑住应用程序模型。一个通用的反模式是在类之间传递模型或者在调用视图前设置模型。反模式的一个例子——也来自于Flex商店——即在主应用程序中将目录传递进ProductsView。

<ProductsView id="pView" label="Products" catalog="{catalog}" 

这段代码在小的例子中可以正常工作,但是随着应用程序逐渐变大,它会带来一些问题,如层之间的紧耦合,以及很难开发和测试。另外一个问题是当同样的数据需要在应用程序不同部分显示时,这些数据需要分开地传递给每一个组件。首先,这看起来似乎不是一个问题,但是试想下如果尝试模拟每一个传递和使用数据的实例,结果会怎样。

客户端架构:推荐模式

多年来众多的Flex架构和框架已经被开发出来。最有前景的一种方法使用了一个像Swiz一样的轻量级依赖注入框架,并用它来划分项目结构。你可以在Swiz中定义类似于Spring中的应用程序bean,并将它们注入到应用程序中的不同部分。一个典型的应用程序框架会包含一个中心类,这个类会定义服务怎样组合在一起——例如,ClientBeans.mxml 类为应用程序声明了通用的模型和控制器:

<model:StoreModel id=”storeModel” />

然后View类连接上控制器:

[Autowire(bean="storeModel")] 
[Bindable] 
public var storeModel: StoreModel; 

对于控制器和其他通用组件,你也可以这么做。用这种方式组织项目结构有一些优势。一个优势在于它可以让模拟服务轻松地植入控制器,以促进开发和测试。另外一个优势在于它能够除去和客户端架构不同层之间的耦合性。

一个精心设计的主视图状态有助于实现前面提到的可用性和可测试性目标。视图栈的思想是让应用程序中的任何视图可以通过单个URL进行访问。除此之外,视图栈的参数需用通过通用控制器传入,这个通用控制器能够让你在应用程序中各个地方使用通用的URL和必要的参数来访问期望的视图。

一个Flex架构示例:重构View Store

作为架构的一个示例,让我们先看看怎样将http://www.adobe.com/devnet/flex/samples/flex_store/ 上的Flex Sotre的例子进行重构。

首先,将主源代码移动到子目录中。在这个例子中,我将所有的资源,产品视图,以及样例目录移动到了flexstore/src/flex中并将其作为源代码主目录。我还把所有的MXML和CSS文件移动到了这个目录中。

接下去,将三个主视图类移动到视图文件夹中。在src/flex目录下创建一个com/anvilflex/view目录。将 HomeView.mxml,ProductsView.mxml以及SupportView.mxml文件放入到这个目录中。为此,你必须对 flexstore.mxml做出如下改动:

  • 在<mx:Application>标签中加入xmlns:view="com.anvilflex.view.*" 。
  • 将视图变为使用<view>标签(因此<HomeView>将变成<view:HomeView ... />)。

将Product.as类移动到分开的域文件夹中——com/anvilflex/view。为此,你必须修复Product类的import 语句,并删除Product单词的最后一个字母。接下去,按住Ctrl-空格键来使用自动完成功能,它同样也可以为Product类加入正确的 import语句。

最后,引入ProductControl来管理产品页面和结算间的过渡。

使用Spring BlazeDS集成简化Java开发

Spring BlazeDS集成项目大大简化了与客户端交互的Java服务端代码开发。在最新发布的项目中,团队成员可以实现核心的配置文件,如web.xml以及Flex服务配置文件。接下去,团队人员需要简单地了解一下如何在他们的类中增添适当的标注来将它们作为服务展现给BlazeDS。举个简单的例子,你可以将Product服务类展现为一个远程服务:

	@Service("productService")
	@RemotingDestination(channels={"my-amf"})
	public class ProductDAO {

	@Autowired
	public ProductDAO() {
		//... initialize the ProductDao class
	}

	@RemotingInclude
	public Product findProductName(int id) {
		Product product = database.findProduct(id);
		return product.name;
	}

在这个例子中,我将ProductDAO类声明为了远程服务,它可以通过使用productService进行调用。单个方法可以使用 @RemotingInclude将其展现为远程方法。其实这些方法都会作为远程服务展示给BlazeDS,其中Flex可以通过远程对象调用远程服务。

与图形设计团队一起工作

刚开始的Flex项目中一个常见的问题是,确保图形设计团队了解Flex中可以做什么。Flex为很多有趣的设计提供了可能性:图形设计团队需要了解Flex中可以做什么,以及Flex怎样来表示一个基础设计转变。

通常情况下,碰到的问题是,图形设计团队用一些像Adobe Photoshop的工具创建了一个模拟。尽管设计看起来非常好,但是它与工作中的应用程序还相距甚远。整个设计将不得不削减并且颜色和字体都得与应用程序的CSS相匹配。根据设计的复杂度,自定义的Flex组件也需要被创建。这些组件可能是需要自定义皮肤的按钮,也可能是定义了一系列新功能集合的组件。困难之处在于设计和实现之间变得极其耗时,设计人员需要搞清楚什么是可能的并从设计中实现这些变化。每一次迭代都会变得更加复杂。

幸运地是,Adobe已经引入了一个新的工具来改进这个过程,这个工具就是Flash Catalyst。它可以让类似Photoshop这样工具产生的艺术品能够轻松地转变为可用的原型。它还可以创建一个原型的GUI并最终应用到应用程序中。通过使用此工具,设计人员可以更快地遍历他们的设计,从而使该组织能更有效地调整设计,以满足其要求。

单元及功能测试

Flex开发中有两种主要的方法来测试一个应用程序。第一个是使用funit或者fluint的功能测试。这个方法可以进行服务以及控制器的测试。第二个方法是功能测试,它可以测试与GUI间的实际交互。功能测试可以使用像Mercury一样的商业工具,或者像FlexMoneky一样的开源工具。

两种类型测试的关键是要在松耦合层创建可以独立测试的代码。例如可以通过将默认捆绑改变为使用模拟服务,来轻松地修改服务。

总结

使用Spring BlazeDS集成的Flex为大规模企业应用程序提供了一系列卓越的技术。开发人员的挑战在于设计模块化,易调试,可扩展的架构。这里的可扩展,我指的不仅仅是软件,还包括开发过程。解决这些挑战可以帮助项目成功,并为组织带来一个更高的投资回报率。

查看英文原文:Super-sized Flex Development—Without the Extra Calories


译者介绍:曹如进,计算机软件与理论专业硕士研究生,主要研究方向包括算法设计与分析,语义网。目前对函数式编程语言,富客户端开发比较感兴趣。InfoQ中文站内容团队,尤其是架构、SOA和Ruby社区需要您的参与,有意者请邮件至editors【AT】cn.infoq.com

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Flex布局是一种用来为盒状模型提供最大灵活性的布局方式。它是移动端开发中非常重要的布局方式,被广泛应用于80%以上的移动端开发中。与rem媒体查询结合使用,可以说是移动端开发的主流布局方式。 Flex布局的原理是通过给父容器添加flex属性来控制子项目的位置和排列方式。当我们将父容器设置为flex布局后,子元素的float、clear和vertical-align属性将失效。Flex容器中的子元素自动成为容器成员,称为Flex项目。 要实现Flex布局,只需要为父容器添加display:flex;属性即可。通过设置不同的flex属性值,可以实现不同的布局效果。例如,设置flex-direction: row;可以使子项目横向排列,而设置flex-direction: column;则可以使子项目纵向排列。 总之,Flex布局是一种弹性的、灵活的布局方式,适用于移动端开发,并可以与rem媒体查询结合使用,是移动端开发中的主流布局方式。它通过给父容器添加flex属性来控制子项目的位置和排列方式,为开发者提供了更大的布局自由度。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [移动端之flex布局](https://blog.csdn.net/yexiangCSDN/article/details/116591641)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值