Ajax/REST 架构风格对于融入式 Web 应用程序的优点

Ajax 和 REST,第 1 部分

Ajax/REST 架构风格对于融入式 Web 应用程序的优点

developerWorks
文档选项
将此页作为电子邮件发送

将此页作为电子邮件发送


级别: 中级

Bill Higgins (bhiggins@us.ibm.com), Rational, IBM

2006 年 11 月 09 日

服务器端 Web 应用程序因采用富应用程序模型和交付个性化内容而具备了 融入式(immersive) 的特点,这种特点越突出,应用程序架构对 Web 架构风格 REST(Representational State Transfer)的违背就越多。这种违背会降低应用程序的可伸缩性,增加系统复杂性。通过与 REST 相互协调,Ajax 架构将使融入式 Web 应用程序消除这些负面影响,尽享 REST 那些出色的特性。

在短短 15 年中,World Wide Web 已经从一项研究实验成长为现代社会的技术支柱。最初发明 Web 的目的是使人们可以轻松发布和链接信息,现在它已经发展为软件应用程序的可行平台。但随着应用程序通过使用富应用程序模型和生成个性化内容而获得了更多的融入性,它们的架构对 Web 架构风格 REST(Representational State Transfer)的违背也越来越多。这种违背会降低应用程序的可伸缩性,增加系统复杂性。

新兴的 Ajax Web 客户机架构风格让融入式 Web 应用程序与 REST 架构风格协调一致。使它们可以尽享 REST 那些出色的特性,同时又消除了应用程序违背 REST 准则时带来的不良特性。本文将介绍为融入式 Web 应用程序成功结合 Ajax 和 REST 的方法与原因。

请访问 Ajax 技术资源中心,这是有关 Ajax 编程模型信息的一站式中心,包括很多文档、教程、论坛、blog、wiki 和新闻。任何新信息都能在这里找到。

REST:Web 架构

尽管 World Wide Web 是在数十年的相关研究基础上建立起来的,但它的有效诞生日期是 1990 年 12 月,当时 Tim Berners-Lee 完成了 Web 主要组件的工作原型:统一资源标识符(URI)、HTTP、HTML、浏览器和服务器。Web 被迅猛采用,远远超过了先驱者们的预期。在 Roy Fielding 最出名的系列文章中(请参看 参考资料),他描述了自己当时的心情:

“尽管对其成功感到兴奋不已,但是 Internet 开发者社区逐渐开始担心,Web 使用的这种快速增长,以及早期 HTTP 的一些拙劣的网络特性,会快速压倒 Internet 基础设施所能承担的容量,从而导致突然的崩塌。”

“一种架构在设计时就应该考虑到一组特性,让它可以满足甚至超越系统的需求。忽略这些特性可能会导致后期变更干扰整个架构,就像是使用一扇落地窗去取代承重墙会破坏整个建筑结构的可靠性。” —— Roy Fielding

Fielding 和其他人对 Web 架构及其是否能够足以支持各种扩展和用法重新进行了审视。这种重新审视的有形结果包括更新诸如 URI 和 HTTP 之类的一些重要标准。这种重新审视还获得了一些无形但却非常有意义的结果:为超级媒体应用程序确定了一种新的架构风格,Fielding 将其命名为 REST(Representational State Transfer)。Fielding 断言,使用且符合 REST 设计约束的 Web 上部署的组件可以充分利用 Web 的有用特性。他还警告说,违背 REST 准则的 Web 组件都将无法利用这些优点。

早期时,大部分 Web 站点和简单的 Web 应用程序实际上都是遵守 REST 准则的。但是随着融入式 Web 应用程序的日益普及,Web 应用程序架构逐渐开始背离 REST 准则了,此后因果循环,情况日益恶化。融入式服务器端 Web 架构的问题很难分析清楚,因为在使用这种架构风格的十年中,已经建立起这样一种信仰:这些问题都是 Web 应用程序架构所固有的。实际上,这并非是 Web 应用程序架构的问题。而是由服务器端 Web 应用程序架构风格所产生的问题。要打破这种偏见,我们来回顾一下整个架构是如何发展到现在这种状态的,这会很有帮助。我们将说明为什么在 Ajax 应用程序创建在商业上可行之后,过去接受的很多假设现在都不再成立了。





回页首


Web 应用程序的简史

Berners-Lee 创造了 Web,最初是将 Web 作为研究人员远程共享文档和在文档之间创建简单链接以加速知识和思想传播的一种手段。然而,URI 标准的架构特征很快实现了除静态文件之外更多内容的共享。

提供静态文档的 Web 站点

Web 上最早的内容由一些静态 HTML 文档组成,其中有很多到其他静态文档的链接,如图 1 所示:


图 1. 提供静态文档的 Web 站点
提供静态文档的 Web 站点

REST 使静态文档的检索极其高效、可伸缩,这是因为它们可以根据 URI 和最后修改日期来轻松缓存。很快开发人员就超越了静态文档的领域,开始动态文档的提供。

早期的动态 Web 应用程序

Berners-Lee 和其他人设计了 URI 标准,为资源的统一唯一标识提供支持,同时使其表示(HTML、文本等)根据 Web 客户机(通常是 Web 浏览器)和 Web 服务器之间的协商结果而变化。由于 URI 将资源标识和资源的底层存储机制区分开来,因此 Web 开发人员可以创建一些程序,使之检查 URI 语法,并动态生成文档,将预先定义的 UI 元素和动态检索的数据(通常是从关系数据库中)合并在一起,如图 2 所示。尽管这些文档是生成的,但是它们的缓存特征与静态文件的完全相同。


图 2. 以嵌入 HTML 模板代码形式提供数据库记录的 Web 站点
以嵌入 HTML 模板代码形式提供数据库记录的 Web 站点

此类早期应用程序的一个简单例子是统一目录 Web 应用程序。这种应用程序通常以如下方式工作:

  1. 用户在 Web 表单中输入名字(例如,Bill Higgins),并单击提交按钮。
  2. 表单根据输入的名字创建一个 URI,并从服务器上请求这个 URI 的内容(例如 GET http://psu.edu/Directory/Bill+Higgins)。
  3. 服务器检查这个 URI,并使用这个学生的电话号码和地址来生成一个 Web 页面。
  4. 服务器将所生成的页面发回到用户的浏览器上。

这种交互的一个重要特性是它是幂等的(idempotent),也就是说除非底层资源发生变化(例如 Bill 修改了自己的电话号码),否则同一请求的结果总是相同的。这意味着浏览器或代理服务器都可以在本地对 Bill Higgins 的文档进行缓存,只要底层资源没有发生变化,那就可以从本地缓存中检索资源,而不再需要从远程服务器检索。这种方法能提高用户感受到的响应性,并增加系统整体效率和可伸缩性。这些早期的动态 Web 应用程序可以很好地工作,将大量的信息送至用户指尖。

融入式 Web 应用程序

下一代 Web 应用程序的目标就是高度融入,提供个性化的内容和富应用程序模型。在过去十年中,Web 开发人员成功创建了这些融入式应用程序。一个非常恰当的例子是 Amazon.com 电子商务站点。当用户与 Amazon Web 应用程序进行交互时,它会创建复杂的客户页面来推荐有针对性的商品,显示浏览历史记录,并显示用户购物车中商品的价格。





回页首


融入式服务器端应用程序和 REST

融入式 Web 应用程序确实非常有用,但服务器端的融入式 Web 应用程序风格从根本上来说是不符合 REST 架构准则的。具体来说,它违背了一项关键的 REST 约束,并且没有利用 REST 最为重要的一些优点,因此又产生了一组新问题。

违背了 “无状态服务器” 约束

REST 的 “客户机-无状态-服务器” 约束禁止在服务器上保存会话状态。符合这一约束进行设计可以提高系统的可见性、可靠性和可伸缩性。但是融入式服务器端 Web 应用程序希望能够为单个用户提供大量个性化内容,因此必须在两种设计之间作出选择。第一种设计要在每个客户机请求中都发送大量状态信息,因此每个请求都完整地保留了上下文的内容,服务器是无状态的。第二种解决方案表面上来看比较简单,应用程序开发人员和中间件供应商都比较倾向于这种方法,它只是简单地发送一个用户标识,并在服务器端为这个标识关联一个 “用户会话”(如图 3 所示)。第二种设计直接违背了客户机-无状态-服务器约束。尽管它确实可以实现我们想要的用户功能(具体来说就是指个性化),但却对这个架构进行了极大的改动。


图 3. 融入式服务器端 Web 应用程序,其中包含了大量服务器端会话状态
融入式服务器端 Web 应用程序

Java™ Servlet 的 HttpSession API 正是一个此类变动的例子。HttpSession 让我们可以在状态和特定用户之间建立关联。这个 API 看起来对于开发新手非常简单。实际上,它似乎可以将任何对象保存到 HttpSession 中,并且不需要自己实现任何特定的查找逻辑就可以将这些对象取出来。但是当我们开始在 HttpSession 中放入更多对象时,就会开始注意到我们的应用服务器要占用的内存和处理资源越来越多。很快我们就确定自己需要将应用程序部署到集群环境中来应对日益增加的资源需求。然后就会认识到,要让 HttpSession 在集群环境中工作,每个对象都必须实现 Java 的 Serializable 接口,以使会话数据能够在集群环境中的服务器间传递。然后必须确定应用服务器在关机/重启过程中是否要继续维护会话数据。很快您就会质疑,违背客户机-无状态-服务器约束是否真的是一个好主意。(实际上,很多开发人员都不了解这个约束。)

使分布式缓存变为不可能

融入式服务器端 Web 应用程序的第二个严重后果在于:它实际上不能利用 REST 的第一类支持进行资源缓存。引用 Fielding 的话来说,“添加缓存约束的优点是可以部分或完全避免某些交互操作,从而可以通过减少一系列交互的平均延迟来提高效率、可伸缩性以及用户可以感受到的性能。不过这样做的代价是如果缓存中的陈旧数据与通过将请求直接发送给服务器而获得的数据有很大区别,那么缓存的可靠性就降低了。”

我们可以将融入式 Web 应用程序近似地看作一个活动实体,它会根据用户提供的新输入内容、其他人输入的新内容以及新的后台数据而不断发生变化。由于服务器必须根据多个用户与应用程序的交互来生成每个页面,因此我们实际上无法两次生成相同的文档。因此,Web 浏览器或代理服务器无法缓存服务器资源。

有几种解决方案可以用来处理资源无法缓存的问题。一种就是创建细粒度的资源在服务器端的缓存,这样服务器就可以通过预先组合好的部分来构建一个粗粒度的页面,而不是通过基本元素(HTML 和数据)从头开始一步步地构建这种页面了。但是问题依然存在:每个请求都会导致大量的服务器处理,这会损害系统的可伸缩性,还可能会对用户感受到的响应性造成负面影响。

无法提供可缓存资源的另外一个结果是:动态程度相当高的 Web 应用程序必须显式地禁止搜索引擎和其他类型的 “机器人”作出请求,因为处理这类请求的成本都非常昂贵;而在符合 REST 准则的应用程序中,只需一次性地将某个资源提供给那一类 “机器人”,然后对它们的后续访问发送一条简单的 “Not-modified” 消息即可。

不使用 Ajax 的客户端的处理

随着访问 Web 应用程序的用户越来越多,系统需要的资源也会逐渐增加。可以让服务器来处理这一切,但将需要容量更大的服务器或集群服务器(服务器端状态在集群环境中并不太适用)。但如果将处理分布到客户机上,那么每增加一名新用户,您就相当于有了一台支持部分新负载的新电脑。如果将会话状态分布到客户机上,那么就有了一个无状态的服务器 —— 这是可伸缩 Web 应用程序中令人满意的一项特性。这看上去应该是种非常明智的做法,那么为什么不按这种方法设计所有融入式 Web 应用程序呢?在 Ajax 出现之前,答案非常简单:每次用户访问一个新的 Web 页面时,应用程序状态时就会被销毁。

每次访问一个 Web 页面时,都要下载一个或一组包含内容的文件(包含在结构化信息中的数据,例如表和列表),以及影响内容外观的样式(例如,红色文本)。在 Web 浏览器中,这些信息都是作为文档对象的抽象集来查看的。下面的列表为例:

  • Ford
  • BMW
  • Toyota

浏览器会认为这个 HTML 是一个 “无序清单” 对象,其中包含了 3 个列表元素;每个列表元素都包含文本。整个文档可视为一个复杂的相关对象树。当我们从一个页面浏览到另外一个页面时,浏览器就会销毁当前页面的对象树,并为下一页创建一个新的对象树。

但是为什么要在一个负载过重的服务器上集中这么多的资源消耗呢?从理论上来说,我们什么时候可以将处理和内存需求分布到客户机呢?简单的答案是给定传统 Web 浏览器约束,这是不可行的(请参看 不使用 Ajax 的客户端处理)。但是 Ajax 架构风格使开发人员可以将处理和状态需求分布到客户机。请继续阅读,学习为什么选择使用 Ajax 风格的融入式应用程序可以继续遵循 REST 准则,并充分利用它的优势。

Ajax 和 REST

正如我们前面看到的一样,传统的服务器端 Web 应用程序将数据的标识和服务器上的动态数据元素合并在了一起,并将所构成的完整 HTML 文档返回给浏览器。Ajax 应用程序在其主要 UI 和浏览器中的主要逻辑方面有所不同;基于浏览器的应用程序代码可以在必要时获取新的服务器数据,并将这些数据织入当前页面(请参看 参考资料 中 Jesse James Garrett 有关 Ajax 的启蒙文章)。呈现和数据绑定的位置看起来可能是一个实现细节,但是这种区别会导致完全不同的架构风格。

利用有状态 Web 客户机的优点

人们通常将 Ajax 应用程序描述成无需在每次点击时彻底地刷新整页的 Web 页面。尽管这个描述非常确切,但是根本的动机在于彻底刷新整页会令用户不耐烦,从而无法获得愉快、融入式的用户体验。从架构的角度来看,整个页面全部刷新的设计甚至非常危险,这种设计使您无法选择在客户机存储应用程序状态,这可能会导致妨碍应用程序充分利用 Web 最强大的架构设计点的设计决策。

Ajax 让我们不需要进行完全刷新就可以与服务器进行交互,这一事实使有状态客户机再次成为可用选择。这一点对于动态融入式 Web 应用程序架构的可能性有深远的影响:由于应用程序资源和数据资源的绑定转换到了客户端,因此这些应用程序都可以享受这两个世界中最好的东西 —— 融入式 Web 应用程序中动态、个性化的用户体验,以及遵守 REST 准则的应用程序中简单、可伸缩的架构。

缓存 Ajax 引擎

设想一下,将 Amazon.com 彻底重新实现为一个 Ajax 应用程序 —— 一个 Web 页面可以从服务器上动态获取所有的数据。(出于商业原因,Amazon 可能并不希望这样做,不过那是其他文章讨论的话题了。)由于现在有很多 UI 和应用程序逻辑都可以在客户机而不是在服务器上运行,根据 Garrett 的说法,最初加载页面时需要下载 Amazon 的 Ajax “引擎”。这个引擎包含大量应用程序逻辑(以 JavaScript 代码实现),另外还有此后将使用从服务器上异步获取的数据填充的 UI 框架(见图 4):


图 4. 融入式 Ajax 应用程序
融入式 Ajax 应用程序

Ajax 引擎一个有趣的特征就是:尽管它包含了很多应用程序逻辑和表示框架元素,但是如果经过恰当的设计,它可以不包含任何业务数据或个性化内容。应用程序和表示都冻结在部署时。在典型的 Web 环境中,应用程序资源可能 6 个月才会变更一次。这意味着负责隔离应用程序资源和数据资源的 Ajax 引擎是高度可缓存的。

Dojo Toolkit 就是一个很好的例子(请参看 参考资料)。Dojo 提供了构建时工具来创建一个包含所有应用程序逻辑、表示和风格的压缩 JavaScript 文件。由于它终究只是一个文件,因此 Web 浏览器可以对其进行缓存,这意味着我们第二次访问启用 Dojo 的 Web 应用程序时,很可能就会从浏览器缓存中加载 Ajax,而不是从服务器上加载它。我们可以将这种情况与高度融入化的服务器端 Web 应用程序进行一下对比,后者每次请求都会导致大量的服务器处理,因为浏览器和网络中介不能对缓存不断变化的资源。

由于 Ajax 应用程序引擎只是一个文件,因此它也是可以使用代理缓存的。在大型的企业内部网中,只要有一名员工曾经下载过某个特定版本的应用程序的 Ajax 引擎,其他任何人都可以从内部网网关上上获取一个缓存过的拷贝。

因此对于应用程序资源来说,经过良好定义的 Ajax 应用程序引擎符合 REST 准则,与服务器端 Web 应用程序相比,它具有显著的可伸缩性优势。

缓存 Ajax 数据

用户浏览一个 Ajax Web 站点,加载 Ajax 应用程序引擎,最好是从浏览器缓存中加载的,否则就从本地代理服务器加载。那么对于业务数据来说情况如何呢?由于应用程序逻辑和状态都在浏览器上驻留并执行,因此应用程序与服务器的交互就与传统 Web 应用程序的方式有很大的不同。不需要获取混合的内容页面,只需要获取业务数据即可。

现在回到 Amazon.com 的例子上来,假设我们点击了一个链接,要查看有关设计模式的一本书籍。在 Amazon.com 目前的应用程序中,链接点击操作会发送很多标识所请求的资源的信息。它还会发送很多会话状态信息,这让服务器可以创建一个新页面,其中可以包括之前的状态(例如最近查看的内容)、个性化信息(例如您在 1999 年购买的书籍)以及实际的业务资源本身。应用程序是动态且高度个性化的 —— 但是却不能缓存,也无法伸缩(正如 Amazon 所示范的一样,这些架构问题都可以通过投入大量资金构建基础设施来克服)。现在我们考虑一下这个操作在(假想的)Ajax 版本的应用程序中的情况。对于 “最近查看的内容” 并不需要进行处理。当我们点击某个链接时,这些在页面上已经存在的信息并不会消失。有两个请求很可能会与设计模式的书籍有关:

  • /Books/0201633612(其中 0201633612 是设计模式书的 ISBN 号)
  • /PurchaseHistory/0201633612/bhiggins@us.ibm.com

第一个假定的请求会返回有关书籍的信息(作者、标题、简介等);其中并没有包含特定于用户的数据。特定于用户的数据意味着当更多用户请求相同的资源时,很可能会从 Internet 上的中间节点上来检索缓存版本,而不是从原始服务器上检索这些资源。这种特性会降低服务器和总体网络负载。另外一方面,第二个请求包含了特定于用户的信息(Bill Higgins 的购买该书的历史记录)。由于这些数据包括一些个性化信息,因此只有一名用户需要从这个 URI 中获取并缓存数据。尽管这种个性化数据并没有非个性化数据的可伸缩特性,但是重要的问题是这些信息都是直接从 URL 中获取的,因此都具有这样的正面特征:它们都不会妨碍其他可缓存的应用程序和数据资源的缓存

Ajax 和健壮性

Ajax 架构风格的另外一个优点是它可以轻松处理服务器的故障。正如我们前面介绍的一样,具有融入式用户体验的服务器端 Web 应用程序通常会在服务器上保存大量的用户会话状态。如果服务器发生了故障,会话状态就丢失了,那么用户就会体验到非常奇怪的浏览器行为(“为什么我又回到主页上来了?我的购物车中的东西都到哪里去了?”)。在采用有状态客户机和无状态服务的 Ajax 应用程序中,服务器崩溃/重新启动对于用户来说都是完全透明的,因为服务器崩溃不会影响会话状态,这些都保存在用户的浏览器中;无状态服务的行为是幂等的,可以由用户请求的内容来单独确定。

 

 
developerWorks 中国  >  Web development | Java technology  >

Ajax 和 REST,第 2 部分

应对 Ajax 软件开发的挑战

developerWorks
文档选项
将此页作为电子邮件发送

将此页作为电子邮件发送


级别: 中级

Bill Higgins (bhiggins@us.ibm.com), Rational, IBM

2006 年 12 月 18 日

Ajax 的流行程度呈爆炸式增长。老式的 Web 框架正在为支持 Ajax 而自行革新,新的纯 Ajax 框架正在开发之中,很多组织正在考虑采用 Ajax,或者已经开始了构建 Ajax 应用程序的工作。但在所有这些悸动之中,只有相当少的组织成功开发了 Ajax 应用程序。本文是分为两部分的系列文章的第二部分,本文将帮助您决定是否应在实际 IT 应用程序中使用 Ajax,旨在提高您在 Ajax 开发中取得成功的机会。

在这个共分两部分的系列文章的 第 1 部分 中,我们讨论了对于那些需要动态和个性化的用户界面,同时又要求可伸缩性的 Web 应用程序来说,Ajax/REST 架构风格可能带来的好处。给定这些需求之后,我解释了为什么相对于传统的服务器端 Web 应用程序架构风格来说,Ajax/REST 极为出色。但只有在您成功设想、规划、开发、测试和部署了 Ajax 应用程序之后,用户才能享受这些美好的运行时特性。本文说明了 Ajax/REST 应用程序的开发时特性的问题。其目标是为那些有兴趣在实际应用程序中使用 Ajax 的读者解答两个重要的问题:

  • 是否应该在自己的 IT 应用程序中使用 Ajax 技术吗?
  • 如果答案是肯定的,那么应怎样来提高成功开发和部署 Ajax 技术的机会?

Ajax/REST 架构风格的新兴给使用传统服务器端 Web 应用程序风格的组织带来了一些挑战。尽管与传统模型相比,Ajax 具有许多引人注目的架构优点,但立即全面转换成纯粹的 Ajax/REST 架构对于所有组织来说并不现实。那些缺乏 Ajax 开发技巧的组织可向现有服务器端 Web 架构逐渐、增量式地添加 Ajax 功能,从而开始采用 Ajax 技术。随着这些组织在 Ajax/REST 使用方面的经验逐步增加,他们就可以安心地尝试更有趣、更有野心的项目。

请查看 Ajax 资源中心,这是您获得 Ajax 编程模型的一站式场所,其中包含文章和教程、论坛、blog、wiki、事件和新闻。任何事件都会在这里报导。

您是否应该使用 Ajax?

Ajax 是一种由一组技术构成的架构风格。这些技术本身并没有好坏之分;它们都是中立的。只有在某些组织能够应用某种技术来解决特定的问题或满足特定的需求时,这种技术才会或多或少地有用。因此要回答 “我应该使用 Ajax 吗?” 这个问题,您必须评估自己的组织正在尝试解决的问题是什么,Ajax 可以对您实现目标提供怎样的帮助(还是根本就帮不上忙),以及您的组织是否具有项目成功所需要的恰当人员。

考虑采纳选项的范围

我们可能会纳闷,“采纳 Ajax” 到底是什么意思。要利用 Ajax,组织并不需要重新编写使用纯 Ajax/REST 架构的程序。我建议您从一些小程序入手,逐渐积累一些经验和信心,而不是直接立即采用纯粹的 Ajax/REST 架构。

采纳 Ajax 可以意味着完成一些轻量和细微的任务 —— 可能是重新实现 Web 应用程序的一个小特性,以使其更酷、更具响应性。Netflix 电影反馈特性就是这种轻量级风格的一个例子。顾客可以通过点击 1 到 5 星来快速给电影评分。每次点击会立即更新 它们的 Netflix 参数,并相应地调整推荐电影。

在采纳的整个领域内,高端采纳就是诸如 Google 的 Gmail 和 Maps 之类的应用程序,它们已经重新定义了 Web 应用程序开发的当前发展水平。这些应用程序因其众多的直观交互特性、可视化效果和根据用户操作和数据不断调节用户界面方面的能力而知名。

设想一下,如果您为自己的行业开发一个像 Google Maps 一样精密的程序会接受到多少正面的反应,这非常有趣。但应该现实一点。Google 可能是世界上最出色的 Web 开发组织,因此以它为基准来衡量 Ajax 的能力是非常危险的。不要忘记,Google(明智地)只有为黄金时间做好准备后才会发布自己的新应用程序,因此我们只看到了成功。可以推测,即使是 Google 的天才们偶尔也会在应用 Ajax 时失败,我们只是不知道这些失败而已。

纯 Ajax/REST 是一种新的架构风格,相对于诸如 JSP(JavaServer™ Page 技术)和 PHP 等较为成熟的 Web 应用程序风格来说,它仍然很难实现。除非提供下一代的 Web 用户经验是主要需求,而且还有世界级的 Web 开发团队,否则您的组织最好像 Netflix 一样最初 “小规模地采纳 Ajax”,而不是像 Google 一样 “大规模地采纳 Ajax”。

评估 Ajax 能为您达成目标带来怎样的帮助

问问自己,Ajax 编程风格有哪些特征使它对于您的应用程序的需求具有吸引力。您的公司正在寻找响应性更高的 UI 能提供的生产力增长点吗?您希望部署一个高度动态和个性化,又具备可伸缩性的应用程序吗?对于您的目标客户群来说,“酷” 会成为一种具有差异化优势的特性吗?所有这一切都是合理的理由,还有些其他方面的理由。关键在于,您必须能够找到一个合情合理的采纳 Ajax 的理由。下面是 Ajax 可以很好地实现的 3 种功能:

  • 响应性更好的 UI。 在传统的服务器端 Web 应用程序中,任何与服务器的交互都要求刷新页面,这意味着这中间需要 2 到 5 秒的延时,还要刷新整个页面。Ajax 使用户可以与服务器通过 “fire and forget” 的交互方式来与服务器交互:用户执行一个操作,系统可以在后台处理该任务,同时用户可以继续处理其他任务。UI 只需要更新有新信息要显示的部分即可,而不用重画整个页面。如果一切顺利,Ajax 风格的 UI 可以让用户实现并维护这种流程,从而提高用户满意度和生产力。

  • 迷人。对于那些对外的应用程序和产品来说,只实现需要实现的功能已不足以使之成为一种好产品。您的客户现在有着太多的选择。您需要一种产品来吸引用户,并使他们为之着迷。就像谚语所说的那样,“性感就是一种特质”。这并不是说需要将开发人员可以想像到的所有铃声和钟声都包含在其中 —— 看一下最低配置设计的 iPod 是如何击败那些具有 10 倍控制功能的便携式音乐播放器就能明白这个道理。问题的关键是提供一种包含众多细微特性的一流设计,帮助用户以一种轻松愉快的方式来完成自己要做的事情。

    Gmail 是一个很好的例子。从外表上来说,Gmail 只不过是另外一个基于 Web 的 e-mail 应用程序,这种技术已经存在 10 年之久了。但是 Gmail 使用 Ajax 做了一些正确的事情。您之前曾经由于意外地关闭浏览器而丢失过未发送的 e-mail 消息吗?Gmail 开发人员仔细考虑了这个问题,通过精心设计,差不多每分钟都会将未发送的消息的一份副本保存到草稿文件夹中。每次都要查找随时都会使用的 e-mail 地址是不是很烦呢?Gmail 开发人员仔细考虑了这个问题,基于以前发送的 e-mail 消息提供了一种精心设计的地址补全算法。

    “迷人” 对于外部及商业应用程序来说非常重要,但是对于内部业务应用程序来说则没这么重要。一切取决于环境。


  • 不牺牲可伸缩性的个性化。在过去的十五年中,随着传统服务器端应用程序朝着更加动态化和个性化的方向不断发展,开发人员和中间件也越来越多地向在服务器端存储大量的会话状态而努力。这种方式会推动个性化的发展,但对于可伸缩性来说却是个噩耗。正如在 第 1 部分 中所介绍的一样,Ajax 应用程序通常都是将会话状态保存到客户机端,并通过无状态的服务与服务器进行交互,这样可以获得动态性和个性化都非常好的 Web 应用程序,而不会牺牲可伸缩性。

决断

这三方面的收益会帮助您的组织取得成功吗?如果不行,那 Ajax 又提供了哪些其他特别的优势来为您的组织的成功贡献力量呢?如果您现在还找不到有说服力的具体理由来采用 Ajax,那么我建议您暂时先不要考虑 Ajax 了,直到找到这样一个理由为止。如果您的确有这样的理由,那么请继续阅读本文。





回页首


使用 Ajax 获得成功

您已经确定 Ajax 可以为组织带来一些独特的价值,这可以证明为采用这种新兴技术而冒的风险是值得的。本节将讨论如何将 Ajax 技术成功整合到我们的应用程序和软件开发过程中。在下一节中,我们将讨论在 “大规模采纳 Ajax” 技术开发时所需考虑的一些特殊事项。

从小处入手,获取经验,建立信心

对于一种有用的新兴技术,没有什么打击能比某个项目试图使用这种技术但却在众人的瞩目下失败更严重了。这通常是由于尚不具备足够的技能,却一次过快地尝试过多新东西而引起的。但是现在很难找到具有丰富 Ajax 开发经验的开发人员;这种技术还太年轻。

为了解决这个问题,开发组织应该通过在真正的项目上实施 Ajax 来逐渐积累使用 Ajax 的经验,但是先不要在关键特性上尝试这种技术。集中精力先将一些小特性部署到真实的世界中。从错误中不断学习和调整。如果试图过早地迈出一大步,那么就会给项目带来太多风险。这一步迈得越大,经过一个完整的设计/开发/测试/部署周期所需要的时间也就越长,而这是获取实践经验的关键。

这个建议更适用于那些希望 “小规模尝试 Ajax” 的组织;不过对于那些希望 “大规模采纳 Ajax” 技术的组织来说,他们也可以通过循环往复的开发方式从小处入手,正如我们在 “大规模采纳 Ajax 技术”的特殊考虑事项 一节中讨论的一样。

找到适当的人来设计 UI 和开发服务

设想一下,您的 Web 开发人员团队中有些人在过去 10 年中已成功交付了很多 PHP、Java 或 .NET 服务器端 Web 应用程序,如果他们可以顺利成长为 Ajax 专家,那的确非常令人兴奋,但是实际情况可能并非如此。尽管我们仍然在 Web 开发这个领域内工作,但是 Ajax 架构风格和支持技术需要开发人员忘却旧知识,重新学习新语言和新模式。这种转型的确 是可能的,不过需要花费一些时间。

在传统的服务器端 Web 开发中,您需要处理链接的点击和表单的提交,并使用一个完整的 HTML 页面进行响应。通常一个工作流都会跨越很多页面,因此服务器端应用程序逻辑必须维护与浏览器之间的会话。服务器必须记住整个应用程序一次次的点击,这样在用户与 Web 应用程序进行交互时,才能提供无缝的工作流。在 Ajax 世界中,我们从这个 “绿色屏幕” 模型转换成了一个真正的客户机-服务器模型,其中客户机是有状态的,而且是动态的,服务器只需要负责提供原子的无状态服务即可。这种新编程风格要求具备客户端和服务器端方面的不同技巧。

在客户端,我们需要那些在长于 CSS、JavaScript 和文档对象模型(DOM)编程的开发人员。问题是大部分开发组织都宣称 “我们具有使用 JavaScript 和 CSS 的经验”,但那往往是一些微不足道的功能,例如修饰文本和在客户端进行表单的验证。认为具有这点 JavaScript/CSS 经验的服务器端 Web 开发人员可以胜任大规模 Ajax 应用程序的工作就像是认为会开车的人就有资格 Daytona 500 赛事一样荒唐。

这也是为什么从小处入手如此重要的另外一个原因。我们的 Web 开发人员现在可能还不具备创建 Gmail 这么重量级的 Ajax 应用程序所需要的技能和经验,不过他们应该可以在现有服务器端 Web 应用程序上实现一些小规模的改进。随着时间和经验的积累,他们逐渐就可以使用 Ajax 来实现更加复杂的场景了。

在服务器端,Ajax 代表了一种转换,因为我们可以将一些不引人注目的会话管理和工作流状态从服务器上移开了。一旦我们积累了足够的经验,Ajax 风格的 “有状态客户机/无状态服务器” 更容易理解和管理,但是这种架构风格的改变需要一些新的技能。我们的服务开发人员应该很好地理解 HTTP 协议,了解 TEST 架构风格的知识,并且具备开发分布式服务的经验,例如远程方法调用(RMI)和远程过程调用(RPC)。尽管 REST 架构风格与 RPC 有一些根本性的区别,但是它们所涉及的一些非功能性的基本准则(边界安全性、网络延迟和非可靠性)都是通用的。

使用框架

DOM、CSS 和 XMLHttpRequest(XHR)“标准” 与浏览器有很大的不同。那些不希望选择现有框架来解决这些差异的开发人员可能会花费大量意料之外的时间来编写自己的信息管道代码,以便对浏览器间的不一致性进行规范化。您的信息管道代码的品质在达到目前可用框架已达到的品质之前,需要有很长一段时间。一种可行的框架是开源的 Dojo 工具包(请参看 参考资料)。

学习和使用工具

开发 Ajax 应用程序涉及两种截然不同的行为:使用 HTML/JavaScript/CSS/DOM 实现 UI 和应用程序逻辑,以及使用早已建立的服务器端平台(例如 PHP、J2EE 和 .NET)来实现服务器逻辑。在服务器端,可以使用以前一直使用的工具。在客户端,则需要学习使用一些新工具。对于希望支持的每个浏览器,都可能都需要一个不同的 Ajax 工具包。这里有一个通用工具功能的列表(请参看 参考资料 中支持两种最流行的 Web 浏览器 —— Microsoft Internet Explorer 和 Mozilla Firefox 的工具的链接):

痛苦之处

对于从 J2EE 或 .NET 方面过渡过来的开发人员来说,普遍的痛苦之一就是 JavaScript 编程语言的代码补全功能尚不成熟。这是 JavaScript 动态类型特性所决定的,另外也与 JavaScript 历史上用户群较小,没有为很好的代码补全技术培育很好的用户群这个事实有关。代码补全功能现在正在使用诸如 Aptana 之类的技术进行改进,但是在达到 Eclipse Java 开发人员或 Visual Studio C# 开发人员所习惯的程度之前,仍然有很长一段路要走。

  • 编写代码:编辑器和 IDE。 在客户机端 Ajax 开发中,我们需要编写 HTML、CSS 和 JavaScript 文件的组合。代码编辑器可以通过语法高亮显示、语法错误检查以及代码补全功能来提高我们的生产效率。

  • 检查结构:DOM 检查器。由于 Ajax Web 页面的很多可视化结构都是在用户与页面进行交互时动态创建的,因此为了探索页面实际的结构,仅仅查看源代码并不能满足要求。源代码很可能与我们所看到的 UI 根本就没有任何相似之处。我们需要在与页面进行交互时对 DOM 结构进行检查。DOM 查看器有一个很好的补足特性是 “实际源代码” 检查器,它能对 DOM 当前状态的 HTML 源代码进行反向工程,这样就可以为那些习惯查看 HTML 源代码的开发人员提供一种直观的手段来了解页面的内容。

  • 检查行为:JavaScript 调试器。在编写一些小 JavaScript 脚本来验证表单或提供少量交互能力时,大部分开发人员都可以使用简单的 alert 语句来定位问题所在。但是当您开始进行大规模 Ajax 开发时,就需要为希望支持的每种 Web 浏览器来寻找并学习一种 JavaScript 调试器。

  • 检查客户机-服务器交互:XHR 监视器。 Ajax 工具包最后一个重要的工具是 XmlHttpRequest(XHR)监视器。XHR 是一个 JavaScript 对象,它可以与服务器进行 Ajax 风格的远程通信。XHR 监视器使我们可以对请求/响应对进行监视,包括它们的头和内容。

在实际环境中进行测试

单元测试的情况怎样呢?

对于目前开发领域最前沿的敏捷开发技术,您可能会纳闷,单元测试在整个 Ajax 框架中究竟处于什么位置。在编写本文时,Ajax 世界中还没有占统治地位的单元测试框架。每个框架(例如 Dojo 或 Scriptaculous)都试图采用自己的优化单元测试框架。Michael Mahemoff 撰写的 Ajax Design Patterns 的第 19 章(请参看 参考资料)对 2006 年的单元测试状况进行了很好的总结,并讨论了各种 Ajax 框架的单元测试功能。

文档中也明确提到,如果没有开发人员的努力,Ajax 会破坏我们对 Web 站点的一些基本期望:例如,后退按钮、书签或浏览器的 “加载” 控件都有可能无法正常工作。我所给出的 “从小处入手” 的建议在这里也能提供一些帮助。只要您只使用 Ajax 来实现一些增量新特性,它们只会更新页面状态,而不会对导航或工作流造成影响,那么后退按钮和书签都不会有任何问题。但是加载时间可能会成为一个问题,尤其是当我们只在本地开发环境上进行测试时更是如此,此时网络延时并不会成为太大的制约因素。

考虑一下:在传统的 Web 应用程序中,当用户点击一个链接或提交一个表单时,即使后续页面的加载花费了 10 秒钟,它们也会从浏览器的 “加载” 控件中看到即时反馈。在 Ajax 应用程序中,点击一个可以触发 XHR 请求的控件并不会激活 “加载” 控件。只在本地开发环境上进行测试的危险在于:HTTP 请求、响应和后续的 UI 更新看起来似乎都是即时发生的,这造成了缺乏浏览器 “加载” 反馈机制貌似也不是什么问题的假象。但在产品环境中,用户距离服务器可能会有成百上千里远,缺乏这种反馈机制就可能会产生困扰并挫败他们的信心。用户可能会纳闷:“我点中这个控件了吗?让我再点一下看看。仍然什么都没有!”

遗憾的是,即使您在工程方面作出了最大的努力,网络延迟依然会存在,因此我们必须接受这个事实。假设有时用户点击控件和服务器的响应到达之间存在一些时间的滞后。当用户作出某种表示发起一个远程调用时,浏览器会提供一条即时反馈,说明它已经看到了用户的这个表示。临时禁用控件或显示一条消息说明正在发生什么,直到接收到服务器的响应并使用这些信息来更新 UI 之后才删除这条消息。网络调用是瓶颈所在;编写需要执行很长时间的 JavaScript 代码还比较困难。

问题的关键是我们需要在真实的环境中进行测试,此时这些可用性问题都很容易发现。问题发现得越早,相应进行响应的时间也就越早。

在真实环境中进行测试的另外一个方面是要确保在需要支持的每种浏览器的每个版本上进行所有的功能测试。例如,如果您声称要支持 Firefox 1.5 和 2.0 以及 Internet Explorer 6 和 7,那就需要在这些浏览器上持续进行测试。或许这是显而易见的道理,但开发人员却很容易陷入一些怀习惯:只在自己喜欢的浏览器上进行开发和测试,以后在其他浏览器上发现问题时就会需要重新修整自己的代码。





回页首


“大规模采纳 Ajax 技术” 的特殊考虑事项

尽管我们已经建议您不要去尝试创建像 Gmail 或 Google Maps 那样庞大的 Ajax 应用程序,但是有些业务或者工程代理可能会迫使您那样做。我们的第一反应是:不要这样做 —— 从小处入手,不但积累经验。但是如果立即就要构建一个纯 Ajax 应用程序,就请继续阅读本文。

关于人员

您的开发团队现在就更加重要了,因为您不是简单地使用新技术来扩展久经验证的架构,而是要采用一个全新的架构。您的团队虽然在 Ajax 方面的经验很少,但需要作出一些重要的决策 —— 这些设计决策可能会导致可怕的错误后果。

您需要一些在 JavaScript/DOM 和 CSS 方面具有丰富经验的成员。如果没有丰富 JavaScript 经验的人,就要寻找一些在其他脚本编程语言(例如 Perl、Python 或 Ruby)方面具有丰富经验的人。Lisp 或 Scheme 等功能编程语言方面的经验也会很有帮助,但经验丰富的 Lisp/Scheme 程序员可能比熟练的 JavaScript 程序员还要稀少。

不要低估良好的 CSS 对应用程序品质的重要影响。缺乏对 CSS 的深入理解可能会导致一些原本不必那样糟糕、难以维护的代码,这会使得首次或再次重写代码更加困难。

重新编写?你说什么?

规划重新编写 …… 至少两次

每当您进行新领域的开发工作时,第一次就可以做出正确决策的可能性很小。您可能会脚步蹒跚地弄出一些难经推敲、满是缺陷的设计,也可以先从小处着手,然后随着不断学习新知识并获得哪些能做哪些不能做的经验之后,再不断更新设计。

Ajax 提出了一项独特的挑战,因为用户经验和底层架构模式与服务器端的对应部分有着很大的区别。在您的 UI 中,可能会发现一些细微但有持续性影响的瑕疵:后退按钮并不能像如期工作,当用户调用远程操作时没有太多反馈,等等。遗憾的是,在具备这方面的经验并明白必须修改设计中的哪些地方以便修复这些问题之前,您很难为这些问题设计解决方案。

希望重新编写自己的应用程序的另一原因是在您获得使用 JavaScript/DOM 和 CSS 经验的同时,您会发现一些新术语和模式,它们可以带来更加简明、可读性和可维护性更好的代码。另外,随着您编写的代码越来越多,您就可以开始着手解决一些通用的问题,尽管这些问题的通用性还不足以进入第三方的框架,但却足以放入我们自己的库中,而不是到处散落于顶层的代码中。重构原来的代码从而使用新的库代码,这样从长远来看是值得的,不过需要花费一些时间,而且这种活动需要不断进行下去。您会发现,自己逐渐进入了框架领域,这里又有一些自己的问题集。

谨慎进入框架领域

随着您在大规模应用程序中取得不断进展,就会发现,很多通用应用程序服务都不是由纯粹的 JavaScript/DOM/CSS 或全新的 Ajax 框架(例如 Dojo 和 Prototype)提供的。您要尝试创建自己的框架级的代码来简化新应用程序级功能的创建。这通常不是什么坏事;大部分最好的开发框架(例如 Ruby on Rails)都已经从具体的应用程序需求中提取出来了。但是务必谨慎;我已经警告过,在小范围内采纳 Ajax 是可行的,但是大规模采纳 Ajax 会非常困难 —— 难度可能会高出一个数量级。支持大规模采纳 Ajax 的设计框架级技术的难度又会高出一个数量级,尤其是在您刚刚接触 Ajax 技术领域时更是如此。

框架代码引入了更多层次的抽象和间接调用,这使得代码路径很难理解。经验之一是尽可能在具体的应用程序层进行工作,只有在应用程序中至少有 3 个部分都可能会使用代码所提供的功能时,才考虑将部分代码移动到一个框架和可重用的库中。

迭代,迭代,迭代

新领域开发中的一个主要的反模式就:在最初设计和实现一个真正的用户可用并可提供反馈意见的小产品之间需要花费太多时间。因此,在您着手实现大型的新 Ajax 应用程序之前,应该先在几周之内提供一个基本可以工作的展示模型,以便让用户开始提供反馈。UI 可能还非常原始,代码也许并不完美,但如果您在让用户体验新应用程序之前先花费 6 个月的时间进行开发,结果也是这样;惟一的区别就是,要丢弃的代码和 UI 都要多上 10 倍。

您需要在很长的设计周期中加速循环过程,使真正的用户一直在一个仿真产品条件的环境中体验产品。这种方法的最高境界是搭建一个测试服务器,开发人员每隔几天就在上面更新代码,这样用户和项目主管就可以体验新产品并提供反馈了。

 

 

 
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值