专栏-解析面向构件的应用架构


 2005-06-11 00:00:00       748

引言

常到北京的人,登长城应该是每年的计划。一路上绿水青山,上了长城几可无止境地攀登。体验之余,惊叹起长城的架构来了:简简单单的砖头,却构造出稳立千年的奇迹;山势如何多变险峻,亦能随势而就。而我们呕心沥血挑灯夜战的大多企业级应用软件,却过一两年就每每要被“新一代”的系统割接而弃用。

这里边正好暴露了软件从一门技术学问走到应用行业过程中的困惑。应用软件的开发商无法建立长期不变的竞争能力,而大型企业也得不到适用的、稳定的、价格合理的应用软件系统。经过不断的在软件技术方面的努力,越来越多的人已经发现,应用架构正是解决应用软件可塑性、稳定性、性价比的重要手段,而构件化是建立良好的应用架构的最佳选择。

面向构件的应用架构适用于多种软件技术和原理,可以是基于代码的传统软件程序为构件的基础单元,可以是模型化的软件为构件的基础单元,也可以是基于模型产生的代码为构件的基础单元。不管应用的逻辑通过什么样的形式来表达,面向构件都提供了重用的、高效的、随需应变的应用架构,参见图1。



构件分解的基本原则

构件分解可谓面向构件应用架构的关键所在,下面谈一谈构件分解的基本原则。

正交分解 “正交性”是从几何学中借鉴而来的术语。简言之,如果两个或更多事物中的一个发生变化,不会影响其他事物,这些事物就是正交的。

软件的复杂性是影响系统开发和维护的主要因素,正交分解是应付复杂性的好办法。一个复杂的系统,最终被正交分解成相互独立的不同构件;每个需求,最终都是由相对隔离的一组构件协作完成;需求的改变,总能明确定位到少数构件,并避免变化的影响波及开去。

本质上,正交思维是“分而治之”思想的一种具体手段。要考虑的问题越复杂,正交分解的效用就越明显。

完备性

分解得到的构件应当清晰、简单、充分、完整、原始,而所有构件的集合必须是完备的。完备性是对整个问题认识的全面性的体现。更重要的是,问题解决方案的敏捷可变的程度,和你对问题认识的全面成熟程度成正比。对于面向构件的应用架构而言,其生命周期应该比较长,而构件分解的完备性尤显重要。

从这一点上,我们可以体会到面向构件发展到今天,其实反映了软件业界对自身认识的“深刻回归”--充满了对软件所要解决的问题的深刻思考,已经对业界解决问题的方式的深刻思考--而不是单单把眼睛盯在解决方案本身上。

实用性

作为一个好的面向构件的应用架构,完备性和实用性其实是一对密不可分的概念。你想象过用加法去实现乘法吗?没有乘法的编程语言,照样是完备的,但不实用!面向构件的应用架构既然最终要支持全新的软件开发方式,就应当提供必要的“常备武器”,这样才能使应用开发更“顺手”。

稳定性 任何支持随需应变的“系统”(包括非软件系统),都必须按照变化发生的原因和频率将构件划分开来。这样一来,就可以理顺依赖关系,使“易变的”依赖于“稳定的”--这一点对构造软件大厦很重要。

构件接口必须稳定。构件的实现可以千差万别,但它必须遵守接口这个“契约”;构件的调用者可以随心所欲地搭建想要的个性化功能,但它也必须遵守接口这个“契约”。因为人解决问题的思考过程是先抽象后具体,从笼统到细节的,所以我们先生产出的势必是抽象程度比较高的实体,而后才是更加细节化的实体。“抽象不应依赖于细节,细节应该依赖于抽象”,这个著名的依赖倒置原则是架构之道的重要部分。

构件功能也必须稳定。构件使用者只关心这个构件对外提供了几个功能,以及这个构件要用到人家的几个功能。就像社会生活中的邮局,我们可以只知道邮局可以寄信可以拿信。

多层次封装

封装和抽象,是一个硬币的两面--封装可以屏蔽细节,只将用户感兴趣的抽象提供出来。而大型系统的架构设计,应非常注重多层次的构件封装。例如,用户界面层它可以有很多的构件组装起来;业务流程一级的工作流,也可以通过构件组装的方法;还有业务逻辑、运算逻辑、以及数据,都通过构件化来封装。

数据独立性

在面向构件的应用架构中,数据的分离很重要。通过构件技术,把数据单独提取成一个构件以后,软件设计可以把数据跟逻辑更好地分离开来。我们大量企业应用的经验表明,其实数据是在一个企业里面是最长期稳定的东西,业务逻辑反而是不断变换的东西,如果把数据和业务逻辑分开的话,应用设计会变得更加有意思。

标签数据使构件重用性最大化

遇到问题了吗?那就上升一个层次考虑!标签数据借助元数据的力量,为构件重用性的最大化出力不小。

问题

目前,还有不少业务数据交换是以数据结构形式、复杂文件、音像流等形式交换的。在处理这类数据时--特别是在电子商务和虚拟企业情况下,我们频繁遇到两个重要的灵活性需求问题:

        如果这些接口的所有用户不以同样速度演变的话,接口的演变就会带来问题;

        该数据结构的接收者或许只希望使用数据结构的某个部分,但它却不得不接收和解析整个数据结构。

我们将上述问题称为“接口脆弱性问题”。在业务快速演变或新系统必须尽快连接的情况下,任何小小的不匹配都可能引起通讯的即时故障,而且这种故障还很难被发现。具体而言,接口脆弱性问题的背后,隐藏着类型匹配、语义安全、以及版本兼容性等问题。

接口脆弱性问题触发我们进行本质性的思考--在一个快速改变的业务世界里,系统必须用尽可能少的设置延迟就可开始交互。

解决方案

标签数据提供的灵活性通过分离各种烦恼来应对接口的脆弱性问题。该解决方案的精华在于,在发送数据时一起发送的还有元数据。

相对元数据这个术语而言,“标签数据”显然在业界有更长的历史,被发送的数据就称为“标签数据”。表示标签数据的约定俗成的标准为XML,作为一种公认的并日益得到广泛使用的标准,XML提供了一系列能力,允许各种文件以一种标准化方式进行描述。如今,已经有许多标准制定团体使用XML来表达它们的标准。

标签数据可为上述接口演变问题提供灵活性:

     XML等标签数据提供的是一种“自描述”的数据,于是,顺序变得不再重要。当然,嵌套级别必须遵循;设计良好的XML结构能直观地反映业务的实际情况,结构内部的嵌套不会成为问题(虽然可能存在别的原因需要嵌套不应太深)。

    标签数据是基于文本的,这种方式要比严格的类型匹配更加灵活。

    当采用标签数据时,一个大的数据包有多个小的、高内聚的数据项组成。它支持数据包在一定范围内的演变,比如缺少了某个数据项,可能意味着采用缺省值。

标签数据还使接口的用户获得了很高的自由度。假设调用方系统包含了一个特定数据项,而目标构件并没有准备(或者不感兴趣),这个额外的标签就被忽略了。这可以说是“接口属于客户”原则的一个推广--处理权属于客户。

总体而言,标签数据具有如下优秀本质。首先,标签数据是“强标签化的(strongly tagged)”而不是“强类型的(strongly typed)”。这就是说,数据的含义是从它的标签中导出的,这清楚地体现了通信双方对于数据标签和总体结构必须达成一致。标签是在运行时间进行检查的,而不是在编译时间进行检查。其次,契约的本质发生了改变。不再是调用方被迫严格遵循目标的详细接口,而是目标能够适应调用方提供的数据。在这一正一反之间,恰恰隐藏着软件灵活性的巨大玄机。而且基于数据语义的标签等级上进行类型检查,保证了特定结构等级中数据顺序的无关性。第三,调用方能适应缺失的标签,只要调用方自己提供缺省数据。

面向构件的应用架构案例--电信网上经营系统

网上经营系统,是一种为运营商建立的网上营业厅和网上管理系统。电信网上经营系统通过CRM系统对电信运营商的客户、产品、以及经营中的促销活动进行管理,并通过在线分析等,对不同客户群采取不同的经营和促销策略。网上经营系统的管理提供了面向各个业务系统的接口,使得从网上受理的业务能转接到不同的业务系统中;并且提供网上经营系统的配置和运营商外部系统的接口管理。

一个大型系统的架构师,必须掌握通过正交分解步步明晰架构的方法。下面介绍该系统的分解思维,如图2所示。图中展示了对经营系统进行多方位正交分解的理念。通过层层正交分解,需要解决问题的粒度越来越小,最终呈现出一组松耦合、高内聚的构件包和构件。

如Brooks所说,概念的完整性是产品质量的核心。建立一个完整、稳定的业务模型,是软件架构工作的重要方面,架构师必须对概念完整性负责。图3所示为电信网上经营系统的业务模型。

该业务模型充分体现了“以客户为中心”的经营理念。总体而言,该模型全面反映了电信网上经营系统必须处理的核心业务(模型中已用不同颜色标出):

    客户关系管理子系统     服务和产品管理子系统     营销活动管理子系统     资源管理子系统 以营销活动管理为例。为了促进销售业绩、提升客户忠诚度,会进行不同的营销推广项目(Project),具体包括客户关怀(Customer Care)、销售(Sales)、服务(Service)、大型活动(Campaign)等。每个项目的开展,都要通过包含一到多个工作项(Work Item)的过程(Process)来进行。而每个工作项又分解成具体的活动(Activities),工作项是进度安排(Schedule)的单位,而活动是评价(Evaluation)的最小单位。活动也是收入(Revenue)和成本(Cost)考量的单位。

最后需要说明的是,正交分解是角度问题,而多层次封装是层次问题,缺一不可。例如,经过层层的分解和封装,“网上缴费数据分析”模块会浮现出来,它负责对网上缴费数据进行分析,从而确定相关的业务策略。设计时,应当将不同的分析角度隔离开来,用不同的构件完成,例如时间维、客户维和费用维等。

相关阅读: