多版本软件构建策略分析

  • 内容
  • 评论
  • 相关

主要分析存在多个版本特性时的软件构建策略。多个版本特性在有些情况下仅仅对应于软件的本地化,复杂的情况就是不同版本中模块的业务逻辑、呈现策略都不相 同。这不仅在产品开发过程中增加成本,更多的成本将在维护阶段体现出来。因此,选择一个合适的构建策略对降低开发与维护成本都是非常重要的。

一、传统软件构建策略

不同的版本采用不同的代码,通过派生或直接使用不同的代码实现。每个版本都会对应到一份的这个版本相关的代码。在代码发布成产品时,我们还需要一个build过程,将源码打包发布成可执行文件。

这里体现多版本特性的代码可能简单可能复杂,关键要看软件整体的设计对多版本的支持。

1.1 采用strategy模式实现

模块A能访问到本地策略,根据不同版本的差异实现Local1、Local2来实现具体的用户需求。

这里存在几个问题。
一、系统中的层次结构很复杂,如果模块E同样也需要根据版本特性来确定自己的行为,这时可能有两种方式:将ILocal层层传递,从A到C再到E;采用singleton模式。不过这两种方式都破坏了对象的封装性。
二、ILocal中的方法会非常多。系统中所有的版本差异都将放到ILocal的方法中,很快这些方法就会失去控制。那是否可以对特性分类处理呢,将某一类特性放到一个接口中可以降低ILocal的管理成本,但没有从本质上解决问题。
三、Local实现类会随着项目的推进,或者在维护过程中变得臃肿。在项目过了几年之后,这点就成为顽疾了。

1.2 使用编译指令

编译指令是一个非常轻便的方式。在很多著名的商业化产品中都会出现,尤其是在处理操作系统不同版本的时候。

使用编译指令不会出现strategy模式中出现的问题,但是需要小心控制它的使用范围。更加严重的一个问题是,版本非常多的时候(比如几十个)编译指令就成了可读性的杀手。同时增加了build过程的成本与错误率。总之,选择这种方式之前必须慎重考虑。

二、基于配置的软件构建策略

不同的版本采用同一份代码 ,build后得到可执行的文件。但这里得到的可执行文件并不是最终的发布产品。可执行文件加上配置信息才能符合用户的需求。这种情况下,开发人员不仅需要开发代码,而且需要设计配置文件的格式(模块的可配置能力)。

基于配置的软件构建同样需要在整体设计上的考虑。并且有多种实现方式。

2.1 采用Local类

Local类读取配置文件,将配置文件中的配置元素返回给程序模块。这种处理方式遇到的问题与采用strategy模式时非常类似。另外,采用Local类只能处理相对简单的逻辑,例如控制界面显示等。

2.2 基于插件的实现方式

插件是将代码与配置分离的一种有效方式。与上面的Local类相比,插件的机制将配置粒度更加细化。

可以将插件系统的配置按照功能分为两大类:结构化配置、差异化配置。

结构化配置指定插件与插件之间的关系,插件之间相互协作。差异化配置体现单个插件的可配置能力。系统分为多个“代码+插件”的可执行模块。

2.3 代码与配置的权衡

在基于配置的软件构建模型中,代码和配置之间存在着一个分水岭。如何划分代码配置的界限影响到所有模块的详细设计。

配置的目的是什么,我们想要达到什么效果?在分析这些问题之前,先说明一下使用配置文件的两个极端。

“配置必须配置的点”是配置文件的最低限度。判断是否达到了这个最低标准的方式非常简单,就是观察系统中是否存在因多版本特性而引起的多份代码。
“配置能配置的所有点”是另外一个极端,达到的最终效果就是完成了一个配置语言运行的环境。

居于左侧的模块复用度低,但配置文件简单,易于维护。居于右侧的模块复用度高,配置文件复杂。具体的项目需要在这两个极端之间找到一个平衡点。

2.4 设计的一致性

一、怎样找到代码与配置之间的平衡点,最好的情况是由架构师定下一个判断原则,指导设计人员进行详细设计。这对于维持产品的设计一致性非常关键。

二、在配置度高的情况下,不同的模块定义了特有的配置文件规则。这些规则的统一对保证一致性也是一个挑战。

三、加入工具支持

好的工具可以提高生产效率,降低重复性劳动的成本。

3.1 传统软件构建策略

在基与多版本的代码开发时,工具能做的是代码生成工作。包括框架代码以及简单的控制代码。更多的情况下仍然需要手工修改源码文件。

关于代码生成技术,在.Net框架中提供了一系列的类来完成(System.CodeDom  namespace等),可以参考相关资料。这种技术自己实现比较简单的情况也并不复杂。

3.2 基于配置的软件构建策略

在基与配置的软件构建策略中,工具的主要目标可以放在配置文件的管理与生成上。代码由开发人员编写,工具生成配置文件后经过测试就可以发布。

这里代码与配置的分界线会影响到工具的复杂度。需要协调代码编写、配置文件管理、工具编写这几方面的成本与收益。

四、加入动态语言

将动态语言技术加到系统中,代码与配置的界限就变得模糊了。使用动态语言作为配置文件的形式可以充分利用它的语言特性提高配置能力,省去了自己设计配置格式与解析配置的过程。

上面说模块自定义的配置规则多的情况下,将破坏系统设计的一致性。如果采用某种动态语言,那么这种规则实际上就是这种语言的语法,有助于开发人员理解各个模块。但这时候的生成工具复杂度就增加了,本质上已经成为动态语言的代码生成器。