小型初创公司经常面临一系列令人眼花缭乱的技术选择:如何交付他们的应用程序,使用哪种语言,是采用现有组件(商业或开源)还是自行开发……等等,不一而足。更重要的是,围绕这些选择的决策通常需要快速做出。本案例研究真实地反映了一家年轻的初创公司在努力在 Web 上部署产品时面临的各种挑战。与许多初创公司一样,这也是一个没有美好结局的故事。
命运弄人,SalesCentrix 这家本案例研究中的核心公司,最终并未成功。在本案例研究中讨论的产品 AccountDynamics 的工作于 2006 年完成,当时 SalesCentrix 仍然是一家持续经营的公司。但公司不久之后就失败了。随后,AccountDynamics 的知识产权被温哥华 BC 省的另一家新兴组织 Realm Dynamics 收购,该公司在 2008 年也遇到了资金困难。
即使这些组织没有成功,SalesCentrix 和随后的 Realm Dynamics 都认为本案例研究中讨论的 RIA(富互联网应用程序)技术是“成功的”。然而,由于与 AccountDynamics 无关的业务挑战,此处讨论的功能从未实际发布。
如果您也有幸为一家年轻的初创公司工作过,那么这个故事可能会让您感到非常熟悉。对于由此带来的不愉快回忆,我们深感抱歉。——
SalesCentrix 是一家位于温哥华的小型初创公司,在 2006 年意识到,必须对其 SaaS(软件即服务)解决方案进行一些改进,该解决方案用于在 QuickBooks 和 SalesForce 之间同步数据,以便用户更好地利用 Web。在大多数情况下,SalesCentrix 软件充当连接这两个流行应用程序的手段,在后台无缝地完成其工作,而无需提供太多用户界面。然而,在设置期间,SalesCentrix 用户必须能够准确地从他们的 QuickBooks 和 SalesForce 数据库中捕获和同步基线状态。
为了促进这一点,一个高度交互式的、类似桌面的用户界面,配有一个类似电子表格的工作区——并且设计为主要在客户端运行——似乎是正确的方法。SalesCentrix 团队认为,他们的客户应该能够立即使用此功能,而无需首先下载新版本的启用软件或安装其他应用程序。很快就决定,SalesCentrix 应用程序的这一设置部分需要作为 RIA 来实现。
SalesCentrix 面临的下一个决定是采用哪种 RIA 技术。在构建早期产品的过程中,该公司的开发人员获得了 Java applet 的经验,但由于他们遇到了一些部署和升级问题,这次他们拒绝了这种选择。他们发现,当客户的浏览器上安装了不兼容的 Java 版本时,部署会变得多么复杂和混乱。他们还了解到,服务器端 applet 往往会变得臃肿,从而导致仍在使用拨号连接的任何客户端的下载和启动时间显着增加。
与此同时,Flash 在 SalesCentrix 团队看来主要用于多媒体演示。他们还意识到,为 Flash 平台开发会占用学习 ActionScript 的开发时间。最后,由于 SalesCentrix 不是一家微软商店,因此甚至没有考虑微软技术。
这实际上将候选技术的范围缩小到仅基于 JavaScript 的解决方案。意识到这一点后,SalesCentrix 团队很快就确定了 AJAX(异步 JavaScript 和 XML)。他们对 AJAX 的舒适度很高,这既是因为它在当时(2006 年初)在 Web 开发人员中普遍流行,也是因为 Google 已经推出的基于 AJAX 的应用程序似乎提供了他们希望实现的交互性和性能。
在确定 AJAX 后,SalesCentrix 团队开始评估五个开发框架:Backbase、ClearNova ThinkCAP、Dojo、NextApp Echo2 和 TIBCO General Interface。他们的主要目标是找到一种可以最大限度地减少 JavaScript 编码和直接与 DOM(文档对象模型)交互的框架,从而使他们能够避开通常以 AJAX 为特征的客户端复杂性。他们还认为,就可维护性而言,JavaScript 不适合程序员团队构建复杂系统。特别是,JavaScript 缺乏类型检查,并且没有任何在组件之间定义严格接口的方法,这将使构建一个充分组件化和解耦的系统变得困难。因此,他们认为使用 JavaScript 会妨碍他们构建和维护 MVC(模型-视图-控制器)风格架构的能力。
另一个重要的考虑因素是,SalesCentrix 工程师希望避免他们必须攀登才能获得 JavaScript 专业知识的学习曲线。他们认为,一个更好的选择是找到包含可视化设计工具的框架,他们可以使用该工具完全避免 JavaScript。在评估可用的 AJAX 框架时,他们还将易于跨浏览器支持和供应商稳定性(即,他们可以确信不会被遗弃的公司)放在优先位置。就他们正在寻找的属性而言,一个好的小部件集、添加他们自己的组件的能力以及优雅降级的能力对他们来说尤其重要。
考虑到这一切,SalesCentrix 团队下载了所有五个框架,完成了每个框架提供的实践教程,并尝试使用每个框架生成一个简单的应用程序,以了解它们的环境和流程的实际工作方式。这是 SalesCentrix 团队首次接触 AJAX;但是,所有框架都没有要求他们处理低级别的 AJAX。事实上,他们发现使用 AJAX 框架非常像使用他们以前使用过的其他框架开发 UI(用户界面)applet。
SalesCentrix 团队知道他们需要表格来显示和操作数据。这被证明是评估框架时的一个重要区分点,因为并非所有框架都将表格作为其入门程序的一部分。然而,ClearNova ThinkCAP 等一些产品确实包含表格,这使得 SalesCentrix 工程师可以轻松测试他们希望纳入的功能。这几乎肯定影响了他们的决定,而 ClearNova ThinkCAP 最终成为了他们的选择,它提供了与其他产品相同的许多功能。他们选择 ThinkCAP 不仅是因为它处理表格的方式,还因为它公司被认为很稳定,以及一些额外的研究表明,ClearNova 产品是五个框架中唯一一个在用户浏览器不支持 AJAX 时提供优雅降级的框架。
做出选择后,几乎立即开始了使用 ClearNova ThinkCAP 进行原型设计。虽然部分目标是测试该技术,但主要目标是粗略地演示他们打算如何为其应用程序实现 UI。完成此操作不需要实现整个应用程序或将其连接到真正的后端,因此原型很快就完成了。更好的是,利益相关者喜欢他们看到的 UI,并批准了它。
然而,不久之后,GWT(Google Web Toolkit)发布了。尽管 SalesCentrix 团队认为 ClearNova ThinkCAP 是一个不错的产品,但他们对被锁定在其专有的 UI 组件集中感到不太舒服。相比之下,GWT 是开源的,这意味着 SalesCentrix 不会面临被锁定在特定供应商产品中的风险。此外,即使 GWT 提供了底层框架,它也为开发人员提供了比 ClearNova ThinkCAP 更大的设计自由度,包括深入到 JavaScript 的潜力。
然后,该团队重复了刚刚使用 ClearNova ThinkCAP 框架采取的许多相同步骤,完成了 GWT 的实践教程,并构建了一个使用表格的简单应用程序,以便他们可以验证 GWT 是否允许他们完成他们面前的项目。一旦满意,并且尽管已经投入了大量时间和精力使用 ClearNova ThinkCAP 进行原型设计,SalesCentrix 团队仍然很快得出结论,他们将切换到 GWT。
除了 GWT 提供的自由度和其固有的非专有性质之外,SalesCentrix 工程师对使用 GWT 进行编程完全用 Java 完成印象深刻——这在他们考虑的所有其他框架中都不是真的——然后工具包生成每个主要浏览器所需的 JavaScript 等效代码。SalesCentrix 是一家狂热的 Java 商店,因此他们认为使用 Java 这种更高级、面向对象的语言有助于(与 JavaScript 不同)降低代码复杂性并简化代码维护。GWT 还提供了一个类似 Swing 的库,这与工程师们熟悉 Java 的 AWT(抽象窗口工具包)和 Swing 图形库非常契合。
GWT 的架构基础设施还将自动满足不同浏览器提出的不同 JavaScript 要求,从而无需 SalesCentrix 工程师设计自己的机制。更重要的是,GWT 用 Java 而不是 JavaScript 编写,提供了他们正在寻找的那种高级设计框架——一种允许他们创建和维护他们希望构建的那种 MVC 架构的框架。
另一个考虑因素是,作为 Google 产品,GWT 被认为来自稳定可靠的来源。SalesCentrix 团队还认为,由于 Google 显然了解 AJAX 领域,GWT 将被证明是健壮且高效的。不过,这些都是主要凭信仰做出的判断,因为 GWT 当时还只是测试版。真的没有办法查看在 Google 内部或外部基于 GWT 构建的现有应用程序。
鉴于 GWT 仍处于测试阶段,SalesCentrix 团队完全意识到,与更成熟的产品相比,可能会出现更多问题,包括更高的错误发生率和性能问题。在其他缺点中,JavaScript 级别没有调试功能,并且 GWT 的小部件集不包含滚动表格小部件。所有这些担忧都被 Google 的突出地位以及 SalesCentrix 工程师对使用 Java 进行开发的熟悉和舒适感所压倒。如果这种熟悉感的代价是他们必须构建自己的小部件,他们也非常愿意忍受。鉴于开发团队对 Java 的熟悉程度以及对直接编写 UI 代码的舒适程度,GWT 可视化设计工具的缺乏(SalesCentrix 最初的标准之一)被认为是可管理的。他们也喜欢 GWT 的 UI 库的大部分方面,并且对 GWT 如何处理客户端和服务器之间的通信印象深刻。
决定使用 GWT 的第一个肯定来自于发现它相当轻松地融入了 SalesCentrix 构建环境。Ant 已经在那里用作基础设施,使得将 GWT 构建集成到现有构建过程中相对简单。此外,由于 SalesCentrix 工程师正在用 Java 构建其余的应用程序,GWT 的 Java 方向非常契合。即使 GWT 和 Java 编译器不同,工程师们也发现使用 GWT 构建东西的精神与构建 Java 应用程序的方式非常相似,因此非常熟悉。
总而言之,他们使用 GWT 框架的经验被证明是非常积极的。他们发现它很稳定,即使他们遇到了错误(正如预期的那样),也及时进行了修复。UI 库允许他们做他们想做的事情,GWT 提供了一个良好的调试环境,尽管只是在 Java 级别,这对于处理编码错误和其他简单问题来说已经足够了。
在网络方面,客户端-服务器通信问题在很大程度上已经得到解决,尽管 GWT 的序列化/反序列化基础设施需要使用特定类型的 GWT servlet 来实现数据通信设施。由于 SalesCentrix 已经有一些服务器端架构来处理身份验证,他们不得不进行一些调整才能将 servlet 插入其中。
由于 GWT 不提供加密,SalesCentrix 使用 HTTPS 进行身份验证。除此之外,他们对与 AJAX 相关的安全性没有任何担忧——至少没有任何超出任何基于页面的应用程序中通常会出现的担忧。
他们也没有遇到任何真正的问题将 GWT 与他们架构的其余部分集成。他们能够建立他们想要的 MVC 架构,将这种体验描述为类似于使用类似 Swing 的应用程序来实现它。唯一的轻微瑕疵是,由于 AJAX 的异步性质,他们必须编写他们的应用程序,以便所有对服务器的调用都是异步的而不是同步的。
然而,在开发过程中,工程师们确实发现了 GWT 的两个性能问题。第一个与 GWT 缺乏滚动表格小部件有关。相反,他们用 GWT 提供的非滚动表格和滚动窗口组合成了一些类似于滚动表格的东西。尽管如此,GWT 的表格被证明甚至无法处理中等数量的数据,考虑到 SalesCentrix 的大型数据集,这非常令人震惊。
SalesCentrix 工程师提出的解决方案是创建一个简单的缓冲组件。他们 MVC 架构中的控制器调用此缓冲区来获取数据,这些数据从服务器异步获取并缓存。然后,控制器使用此数据增量地填充表格,基本上是动态地将数据移入和移出表格。通过这种方式,他们能够在相对较短的时间内传输大量数据。这足以确保每当用户向上或向下翻页时,都可以立即从缓存中获取数据。但是,一旦用户一次向上或向下移动超过一个屏幕,就必须回调服务器以检索更多数据。
作为一种权宜之计,这被证明是相当成功的。尽管用户体验到的滚动不如完全填充的表格那么流畅,但延迟非常小。
一个更严重的性能问题与序列化/反序列化有关,最初速度非常慢,以至于框架几乎无法使用,传输 500 个对象(400 KB)需要一分钟以上。当 SalesCentrix 工程师第一次遇到这种延迟时,他们不太确定是什么原因造成的。通过简单的“printf 调试”,他们很快就能够确定程序中延迟发生的位置。然后,使用一个旨在监控数据获取的测试程序,他们观察到反序列化过程异常计算密集型,在很长一段时间内消耗了 100% 的 CPU 周期。
令人高兴的是,GWT 的后续版本将反序列化延迟提高了一个数量级,因此相同的操作只需要几秒钟。虽然仍然远非快如闪电,但这至少使性能落在可接受的范围内。
另一个困难,在后来与为各种浏览器生成的应用程序的不同实例相关的困难是,界面在所有不同的环境中呈现不一致。工程师们设法在 Java 级别修复了这个问题,方法是使用其他选项来布局、组合和组合小部件,以便它们无论底层浏览器如何都显示相同。
依赖测试版的一个不足为奇的后果是,当 2007 年年中发布 GWT 的新版本时,它无法开箱即用。GWT 布局和样式的几处更改导致 SalesCentrix 屏幕显示不同。SalesCentrix 只有经过一定数量的集成返工才能保持最新并获得新版本的优势。
同样不足为奇的是,无法在 JavaScript 级别进行调试极大地阻碍了 SalesCentrix 工程师加快表格填充速度和改进大型数据集滚动功能的努力。尽管一个主要因素是 GWT 的本机调试功能仅限于 Java,但 SalesCentrix 自身缺乏 JavaScript 专业知识是另一个明显的障碍。尽管如此,任何调试生成的 JavaScript 代码的努力几乎肯定都会被证明是有问题的。
回顾过去,SalesCentrix 团队得出结论,他们本可以更好地在更基本的级别实现自己的小部件,而不是像他们那样从现有小部件中组合它。他们实施的权宜之计效果很好。如果它失败了,SalesCentrix 工程师会发现自己处于 JavaScript 和 DOM 的级别,从头开始构建自己的小部件实现。与此同时,他们将面临另一个复杂的问题,即找到一种方法将他们自己开发的小部件无缝集成到 GWT 框架中。
SalesCentrix 可能最严重的问题出现在序列化/反序列化问题上。这个问题被证明是如此深入且根本,以至于很可能,如果 GWT 的后续版本没有将延迟提高十倍,那么它很可能会成为一个致命问题——清楚地说明了使用早期工具包的风险。他们直到开发后期才设法发现这个问题,这促使他们对如何在最初的风险分析中错过这一点进行了回顾性评估。他们早期的工作和 GWT 的初始性能指标表明,客户端和服务器之间有足够的带宽来支持他们正在寻找的那种本地交互性,尤其是在滚动浏览数千条记录的能力方面。然而,他们用来来回传递数据的测试非常简单,并且没有以与最终应用程序相同的方式来执行 GWT 的数据传输机制。回顾过去,他们应该这样做。是的,请将此视为一个宝贵的经验教训。Q
JEFF NORWALK ([email protected]) 是一位资深技术传播者和项目经理。他也是一位康复中的律师和前最佳男孩,目前居住在曼哈顿。
最初发表于 Queue 第 7 卷,第 1 期—
在 数字图书馆 中评论本文
Pete Hunt, Paul O'Shannessy, Dave Smith, Terry Coatta - React:Facebook 在编写 JavaScript 方面的函数式转变
用户友好的 JavaScript 前端长期以来的讽刺之一是,构建它们通常需要艰难地遍历 DOM(文档对象模型),而 DOM 几乎不以其对开发人员的友好性而闻名。但是现在,由于 Facebook 决定开源其用于构建用户界面组件的 React 库,开发人员有一种方法可以避免直接与 DOM 交互。
Bruce Johnson - 在约束中狂欢
Web 朝着交互性发展的轨迹始于用于验证 HTML 表单的简单 JavaScript 代码片段,最近确实开始加速。一种新型的 Web 应用程序开始涌现,它具有基于直接操作浏览器 DOM(文档对象模型)并通过越来越多的 JavaScript 构建的日益交互式的用户界面。Google Wave 于 2009 年 5 月在旧金山举行的 Google I/O 开发者大会上首次公开演示,它就是这种新型 Web 应用程序的典范。
Eric Schrock - 在生产环境中调试 AJAX
JavaScript 语言有着一段奇特的历史。最初只是一个简单的工具,让 Web 开发人员可以向原本静态的 Web 页面添加动态元素,但此后已发展成为交付基于 Web 的应用程序的复杂平台的核心。在早期,该语言静默处理失败的能力被视为一种优势。如果图像翻转失败,最好保持无缝的 Web 体验,而不是向用户呈现难看的错误对话框。