内容


设计复合应用程序:组件设计

Comments

复合应用程序是面向服务体系结构(Service Oriented Architecture,SOA)和上下文协作策略中的关键元素。它们为公司和组织提供业务灵活性,让他们能够快速响应市场的需求变化。复合应用程序由松散耦合的用户界面组件组成,支持组件之间的通信。组件可以在多个复合应用程序中重用。

能够将多种技术组合成一个应用程序,这种能力可以提供巨大的业务价值。它可以保护和扩展公司现有的软件资产,增加业务灵活性。与传统的应用程序开发方式相比,创建复合应用程序要容易得多,这帮助公司快速且成本高效地响应业务需求。

粗粒度组件之间的这种松散耦合是复合应用程序体系结构的基础。它还使位于不同地点的小组可以相互分享工作成果并进行协作。每个小组只需要了解组件的输入和输出,而不必掌握其内部逻辑。例如,一个部门正在开发会计应用程序,另一个小组正在开发销售趋势跟踪应用程序。在复合应用程序体系结构中,可以将销售趋势跟踪应用程序中的一些组件添加到会计应用程序中,从而按照会计学的上下文提供相关的资产视图。同样,在销售趋势跟踪应用程序中也可以添加会计应用程序中的组件,从而按照资产的上下文提供会计信息。随着开发出的复合应用程序越来越多,在整个公司范围内共享组件的机会会呈指数式增长。这种体系结构的目的就是让总体大于部分之和。

复合应用程序模型是 IBM WebSphere Portal 开发人员已经熟悉的模型。这种方式已经扩展到 IBM Lotus Notes V8 中,这让 Lotus Notes 开发人员能够在复合应用程序中以组件形式提供他们的 Lotus Notes 应用程序。IBM Lotus Domino Designer V8 已经可以使用属性代理,并提供一个更直观的用户环境。Lotus Notes V8 还支持插入 Eclipse 组件,所以复合应用程序可以是 Lotus Notes 组件和 Eclipse 组件的任意组合。这适合进行 on-the-glass 集成(将不同组件集成在同一用户界面中);如果进行扩展,还可以通过属性代理让组件可以相互操作。可以使用 Composite Application Editor 或 WebSphere Portal Application Template Editor 定义复合应用程序。

复合应用程序的组件开发不同于传统的 Eclipse 或 Notes 应用程序开发。这种开发的目标是创建具有足够灵活性的组件,让它们可以简便地部署在应用程序中,而不需要做重大修改。本文讨论设计这样的组件的方法,以及可以考虑采用的最佳实践。

前提条件

本文假设您熟悉 Lotus Notes 中的复合应用程序。请参考 IBM Lotus Domino Designer Help 中的复合应用程序部分。

教程 “Customer interests composite application sample for IBM Lotus Notes V8” 可以帮助您获得实践经验。它组合出一个基于 NSF 的复合应用程序,其中包含使用组件间通信的 NSF 组件和 Eclipse 组件。

群策群力

复合应用程序组件的定义非常宽泛。可以做您希望的几乎任何事情,这非常强大,但是也带来了不确定性,比如应该做什么以及如何建立一种标准的开发方法。请记住,本文中提供的组件分类仅仅是提出一种可能的方法。方法是无所谓对错的,只是是否适合您的问题。如果您认为我们的建议适合您,那么就采用它们。如果您有其他需求,也可以调整这些方法。

但是,仅仅通过创建复合应用程序,并不能实现这种集成。创建的组件的互操作性可能并不比两个单独的 Web 页面更好。成功地部署组件应用程序体系结构的关键是建立一个论坛,让开发人员在这里讨论不同的开发工作。一定要在组织中建立适当的开发过程来协调这些开发工作,将复合应用程序设计的潜在优势尽可能转换为真实的利益。

如果您的公司有与体系结构讨论会相似的活动,这可能是适合讨论组件重用和互操作性的场合。如果公司比较小,甚至可以指定一个人作为数据类型所有者来专门负责这个方面。这样的组织方式一定不要影响开发的速度。过分关注开发过程会抵消过程带来的好处。相反,讨论会应该是一个自由讨论中心,各个开发小组可以在这里相互交换想法,并发现从别人的工作成果获益的机会。

组件的类型

对于组件可以由什么东西组成,没有什么技术限制。从字面上说,组件是一个用户界面部件,它们具有定义良好的入口点和出口点。为了帮助我们决定要构建的组件,我们来定义几个组件类别。

复合应用程序能够共享组件,这模糊了实际应用程序之间的界限。这是非常好的用户体验。用户应该能够执行他们需要的各种操作,而无需意识到自己从一个领域进入了另外一个领域。在组件开发方面,组件常常来自一个应用领域或者与其相关联。它们具有交互点,可以通过交互点连接到其他领域;但是,在最灵活的设计中,这些交互是在组装应用程序时而不是在组件设计阶段确定的。在讲求实际效果的开发项目中,常常根据应用领域划分工作任务。在划分工作时,常常要考虑资源、时间表和交付使用的成果,所以根据应用领域考察设计是比较合理的。

销售趋势示例由三个基本应用领域组成:

  • 核心销售趋势应用程序,它跟踪公司和销售趋势
  • 一个讨论应用程序,其中包含关于销售趋势的讨论
  • 一个法律应用程序,它跟踪公司与客户签署的合同和修订协议

以领域为中心的组件

以领域为中心的组件是创建的应用程序的基本部分。在创建一个涵盖自己领域的功能的复合应用程序时,主要的用户界面元素可能只与这个领域相关,只在这个领域的上下文中有意义。要确保有一组组件可以支持一个应用程序的所有现有功能,这常常是组件开发的第一个层次。如果要对现有的应用程序进行转换,一种方法是首先确保在复合应用程序中有对应的功能。这些组件能够以最快速的方式提供主要功能。这些组件可能在您的应用程序中多次使用,但是不太可能在另一个复合应用程序中使用。因此,为了提供更丰富的功能,这些组件的耦合可以紧密一些。

示例应用程序 中,CompanyList、SalesLeadList、SalesLeadDetail 和 SalesLeadEdit 等组件属于以领域为中心的组件(见图 1)。

图 1. 以领域为中心的组件示例
以领域为中心的组件示例
以领域为中心的组件示例
以领域为中心的组件示例
以领域为中心的组件示例
以领域为中心的组件示例
以领域为中心的组件示例
以领域为中心的组件示例
以领域为中心的组件示例
以领域为中心的组件示例
以领域为中心的组件示例

领域上下文组件

以领域为中心的组件是一个应用程序领域的基本部分,而领域上下文组件是辅助部分。这些组件修饰应用程序中的视图,提供与领域相关的信息,但是它们采用与上下文相关的方式,或者只提供属于某一信息子集的信息。在传统的转换过程中,领域上下文组件是开发的第二个层次。它们不是应用程序的基本工作所必需的,但是它们能够显示上下文信息并减少页面切换或复制/粘贴,从而提高了易用性。因此,在其他复合应用程序中有可能需要它们。如果两个领域中有共同的元素,那么这些组件可以以相同方式提供领域相关信息。

将应用程序转换为复合应用程序的另一种方法是,首先以适合集成到其他复合应用程序中的方式开发一些上下文信息组件。这种方法可以在采用复合应用程序体系结构时尽早享受重用带来的好处。如果应用程序很大而且复杂,那么整体转换过程可能需要很长的时间。如果原来的应用程序使用另一种体系结构(例如,由后端系统支持的在文本终端上运行的绿屏应用程序),那么整体转换是没有意义的。但是,正如 Web 服务可以提供对这些后端系统的访问一样,可以通过开发领域上下文组件,将信息从这些系统中取出来(很可能要使用相同的 Web 服务),以便在新的复合应用程序项目中重用。

示例应用程序 中,CompanySummary、LeadSummary 和 LeadList ConstrainedByCompany 等组件属于领域上下文组件。图 2 说明如何将它们部署在讨论和法律应用领域中,从而在它们的上下文中提供相关的核心信息。

图 2. 领域上下文组件示例
领域上下文组件示例
领域上下文组件示例
领域上下文组件示例
领域上下文组件示例

通用组件和工具组件

在开发复合应用程序时,常常会遇到并不专属于您的应用领域的元素。开发复合应用程序的任何人都可能需要这些组件。

在示例应用程序中,Pager、Browser、RSSReader 和 MailSearch 等组件属于工具组件。Lotus Notes 附带几个通用组件。例如,Lead Manager 示例应用程序(使用了名称和地址簿组件)和 Managed Browser。

集中的活动

既然已经有了区分组件类型的框架,我们就来讨论围绕复合应用程序开发的开发过程。

首先,建立一个集中的论坛,让开发小组能够发表他们的复合应用程序开发计划,这样做的好处是无法估量的。一个小组的应用领域可能与另一个小组的应用领域毫不相关,但是从一个小组的开发工作中得到的经验教训可以应用于别的小组。让各个小组能够分享计划并获得反馈可以改进开发过程。

实现这种广泛的交流的原因之一是,这可以促使形成复合应用程序开发的 “语言”。设计和开发复合应用程序的过程与其他应用程序开发过程是一样的。它要求建立需求、规格说明、测试计划和交付。复合应用程序的特殊之处在于,组件开发可能没有确定的应用目标,而且可以以各种方式组合出应用程序。通过让各个小组分享他们的过程(包括如何编写规格说明、如何开发测试计划以及如何组织交付),可以分享工作成果并节约资源。本系列后续的一篇文章 “Designing Composite Applications: Managing the Process” 将讨论这些问题。

如果公司对项目开发的要求非常严格(比如项目必须符合某些法律法规),或者各个工作任务会产生广泛的影响,那么论坛可能应该更加正式,而且可能需要批准开发计划,然后才能进行开发。在要求不这么严格的环境中,批准可能只是个形式。但是,即使只是走个形式,在批准过程中也会交换更多的信息,这会增加重用的可能性。

这些活动可以帮助开发以领域为中心的组件。但是,对于领域上下文组件帮助更大。因为设计这些组件的目标是在应用领域之外使用,所以公布它们的开发计划(以及在开发完成时演示它们的功能)会引起热烈的反响。您的设计可能非常适合另一个小组的需要。别的小组可能希望做一点儿小改动,或者需要相同的组件,但是使用略有不同的信息集。另外,因为别人主要关注他们自己的应用领域,所以他们希望知道您在自己的应用程序中如何使用他们的领域上下文组件。

小组集中讨论的另一个好处表现在对通用组件和工具组件的决策上。可以向大家推荐组件,让所有领域都使用它们,而不是只限于一个领域。一些组件可能最初属于一个小组。随着其他小组开始使用它们,它们可能被转交给其他小组,那些小组会添加他们需要的特性。随着这个过程的发展,组件的特性会越来越丰富,而且只要保持严格的向后兼容性,部署它的其他应用程序也会受益。

如果一个小组需要一个有可能跨领域使用的组件,当在集中讨论会上提出计划时,可能会出现另一种有利的局面。如果其他小组对这个组件感兴趣,那么他们可能愿意为这个组件投入资源。例如,一个小组可以负责组件的开发,另一个小组负责测试。在大家的共同努力下,可以产生特性更丰富的组件和应用程序。

在示例应用程序中,有一个 Tag Cloud 组件。这个组件最初是为满足示例应用程序的一些次要需求开发的。但是,另一个小组看到了我们正在使用这个组件,他们认为 Tag Cloud 组件会使他们自己的应用程序受益。他们接管了它的开发,用自己的特性来增强它。因为他们没有破坏我们的示例应用程序所需的基本特性,所以我们可以继续使用这个组件,而且从他们添加的特性获得了好处。

对于讨论会,最重要的技术问题是维护一组通用的数据类型。组件相互通信的方法是将数据通过线连从属性发送到动作。如果这些线连的两端不使用相同的数据类型,那么线连就无法实现。两个组件可能都有日期的概念,但是如果定义日期的方式(名称空间、名称、类型)不同,它们就无法相互连接。讨论会(或者专门的数据类型所有者)可以维护在整个公司范围内通用的数据类型定义列表。在每个小组公布他们的开发计划时,应该识别出属性和动作所需的数据类型。对于与现有的公司数据类型定义匹配的数据类型,就使用通用定义。新的独特的数据类型可以添加到公司数据类型定义列表中。

以领域为中心的组件常常只在这样的组件之间相互通信。它们定义的许多数据类型可能不会跨领域使用。但是,领域上下文组件在理想情况下会在许多领域中使用。对于这些组件,保持数据类型的一致性是非常重要的。

我们的目标是,尽可能增加组件的重用机会,减少组装复合应用程序所用的时间,并允许业务用户通过添加领域上下文组件、通用组件和工具组件,轻松地扩展和修改现有的复合应用程序。

组件模式

在为复合应用程序开发组件时,有几种经常出现的模式类型。在为复合应用程序设计组件时,应该首先考虑这些模式。同样,布局模式可以帮助您安排组件集合的布局,应用模式可以帮助确定整个应用程序的结构。

本系列后续的一篇文章 “Designing Component Applications: Design Patterns” 将详细讨论这些模式。

决定组件粒度

在决定将什么东西实现为组件时,可以采用不同的方法。如果您正在从头开始设计新的应用程序,那么选择前面提到的组件模式之一会有帮助。可以以适当的模式作为基础,考察自己的应用程序的哪些部分符合这些模式。

对于新的应用程序,另一种有用的方法是反向推导。首先设想出应用程序的外观和表现,然后判断出实现这些所需的组件。如果首先用一系列屏幕来描述应用程序,例如在白板上画出屏幕示意图,就可以识别出常用的元素。对于那些在几个应用程序页面上完全相同或相似的用户界面元素,可以考虑将它们实现为组件。

下一步是审查您画出的示意图,寻找那些属于其他应用领域或者在其他应用领域中可能有意义的用户界面部分。按照这种连续的划分方法,可以将设计转换为组件。

根据现有的应用程序设计组件既困难也容易。说它容易是因为您已经有了现成的应用程序设计。困难是因为必须在使用现有的东西和提高组件重用性之间进行权衡。

对于 Lotus Notes 应用程序,可以使用一些基本用户界面类型。后续文章 “Designing Component Applications: Lotus Notes Components” 将详细解释一个把讨论数据库转换为复合应用程序的示例,其中介绍的原理适用于许多 Lotus Notes 应用程序类型。

对于 Eclipse 应用程序,还有一个优势,因为这种应用程序是基于视图的,而视图会直接转换为组件。Lotus Notes V8 提供了更丰富的交互和重用功能;在将应用程序转换为 Eclipse 应用程序时选择的粒度可能不适合复合应用程序。通过使用 Eclipse 视图(如果希望进一步划分,也可以使用透视图),可以应用连续划分方法派生出组件。

组件之间的通信

组件通过使用属性和动作相互通信。可以按照几种不同的方式使用组件来实现操作。

属性

属性代表传出的值。最简单的方法是传播一个简单的数据值。例如,如果一个组件包含一系列数据条目,那么它可以向外传播一个代表当前选择的条目名称的属性。在传播这种值时,有多种选择。数据条目常常包含许多数据项,例如名称、部件编号、供应商编码、库存的数量等等。可以为每个数据项传播一个单独的属性。对于复杂的大数据条目,这种传播方式会非常复杂。目前的属性代理实现只允许传播可以表示为字符串的数据条目,不能按原样传播复杂的条目。

解决这个问题的一种方法是定义一个执行序列化的方法。例如,可以用一个 XML 数据结构表示复杂条目的细节,然后将 XML 数据结构序列化成字符串。Web 服务常常使用这种技术。但是,应该注意这种技术的一些缺陷。首先,每当修改一个数据元素时,都必须传播整个结构。这种方法只适用于在后端上有关系的设置组。第二,这会减少这个组件与来自其他领域的组件相互操作的机会。尽管各个数据项可能具有相同的类型,但是如果整个数据结构是这个应用领域特有的,那么其他组件必须了解这个数据结构的定义,才能使用它。这会破坏设计的松散耦合性质。

还可以用属性实现事件通知。事件通知只在某些东西发生变化时传播。例如,执行复杂操作的组件可以传播它的状态。当它开始提交时,它可以在状态属性中传播一个值来表示这一情况。其他组件可以监听这个状态属性,当它们链接的组件处于不适当的状态时,它们可以禁用本身,以避免冲突或无效操作。

为了提高可重用性,各个组件应该避免指定应用程序流。相反,它们应该向外传播它们的视图状态变化,从而将确定应用程序流的任务推迟到组装时。这样就可以用一个控制器组件处理各个组件之间的状态迁移,实现整个应用程序流(同样,这个任务也推迟到组装时,而不是在设计时完成,因此提高了组件的可重用性)。

例如,在 Sales Lead 应用程序中,许多组件向外传播一个称为 ViewState 的属性。这个属性包含这个组件希望传播到应用程序级的一个预定义值,这个值表示操作的类型或状态迁移。例如,Company Edit 组件在保存它之后将这个属性设置为 #company.save,在单击 Close 按钮之后设置为 #company.close。在组装应用程序时,各个组件被线连到一个页面切换组件,这个组件将这些状态通知映射为特定的页面迁移。

动作

动作表示传入的值。与属性一样,可以按照几种不同的方式使用动作。

与属性一样,最简单的方法是实现一个简单的数据接收器。组件可以消费这个属性并存储它,供以后的操作使用;还可以执行一个面向数据的操作,比如更新一个编辑框的值。对于这些动作,数据类型直接对应它们代表的字段。

另一种典型用法是动作直接对显示产生影响。最常见的形式是,将一个索引传递给信息获取组件,这个组件查询对应的数据记录并显示内容或内容的子集。产生的结果值还可以通过属性进一步传播。这种动作的数据类型通常是惟一 ID 或其他索引类型。对于列表组件,这可能是排序条件或搜索条件。在其他场合,动作还可以控制组件的显示模式,或者根据用户的角色启用或禁用组件。如果动作是一个索引,那么它常常采用对应字段的数据类型。对于更复杂的搜索字符串,可以定义一个特殊的类型;但是,为了提高互操作性,也可以考虑使用通用字符串类型。

在本文的示例中,使用动作处理服务型的操作,但是这些服务只能接收一个参数。如果通过组件提供的服务需要多个输入,那么怎么办?目前,只能向动作传递一个参数。支持更复杂的服务有两种方法。首先,可以采用与处理复杂属性相同的方法;可以将所需的多个参数序列化在一起,形成一个字符串类型的参数。例如,邮件组件可以接收一个包含 mailto: 字符串的动作。这个字符串实际上包含多个参数,包括 to、cc 和 bcc 地址的列表以及一个主题和邮件体字段。与序列化的属性值一样,这样做的缺点也是数据类型会成为这个动作所特有的,这会使互操作变得困难。另外,如果输入值来自不同的组件,那么将它们组合成单一的序列化字符串是很困难的。

另一种方法是建立多个数据接收器动作,它们各自对应一个参数。然后在用户界面中建立一种操作方式,例如按钮、热点或菜单右击。当触发这个操作时,它获取以前设置的值,如果所有非可选值都已经设置了,它就执行操作。(如果设置的值不够,那么用户界面可以反映出这一情况。例如,可以禁用某个按钮。)这种方法的优点是它基于简单的类型,而且它适用于各种情况,比如在当前上下文中可能无法获得所有数据,或者数据可能来自几个组件。

结束语

复合应用程序体系结构使我们能够将几种技术组合成一个应用程序,轻松地向用户提供关键的应用程序功能。这会大大提高用户的工作效率。另外,用现有的可互操作组件创建特性丰富的复合应用程序可以提高开发组织的灵活性,让他们能够快速且成本高效地响应业务需求的变化。


相关主题


评论

添加或订阅评论,请先登录注册

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Lotus
ArticleID=285464
ArticleTitle=设计复合应用程序:组件设计
publish-date=02042008