如何在OpenExpressApp做客户化工作

很多产品都会遇到客户化问题,也就是在通用产品之上针对一些客户会进行配置和定制工作,也就是处理721问题(为了简单描述这类问题,我们简单的使用721术语,7为通用功能,2为可变功能,3为个性功能,这里721只是从数字分布上表明共性和个性的大致比例,实际中并不完全就是按照721比例分配),下图表示的就是产品线的主注内容,这个在我以前blog中也介绍过多次,本篇重点是介绍如何在OpenExpressApp这种面向对象框架下做客户化。

版本策略

  • 以往的客户化分支版本策略带来的问题

以往我们做客户化时,可能会专门弄出一个客户化小组,并且从SVN中弄出一个代码分支,然后进行更改,个性的东西都保存在各自的分支中,对于共性问题在开发后期再单独合并到主干中去,这样可以带来一个好处就是在进行客户化任务时可以独立于主干版本,可以较为自由的进行更改。

但是这会带来后期的合并版本问题:

  1. 如果分支功能很多,我们以前的做法时专门用一期任务来做合并工作,这又势必带来工作的重复
  2. 有时合并过程中说不定还会带来客户化与主干版本之间设计上的冲突
  3. 由于没有明确采用可变性管理而是使用分支版本方式来管理客户化工作,当客户化数量增加时势必势必会带来管理的复杂性

我想这也就是产品线工程方法中对于代码一套性说法的原因,产品线工程认为产品所有功能(包括721)在任何时候都可以通过一套源代码库获取,然后通过可变性管理等手段来达到针对客户化发布。

  • OpenExpressApp的产品线版本策略

OpenExpressApp是基于产品线工程方法来做的,我画了一个图,用来说明一下我拟定项目后期对于客户化工作的总体版本策略,如下图所示:

  • 只有一个主干版本,这个产品的所有功能都由同一个代码库来管理,包括通用功能、可变功能,并且还包括个性功能,这些功能通过类继承、模型动态配置、代码静态配置等方式来处理可变性
  • 通用功能和可变功能由领域工程来完成,将作为产品线的核心资产;个性功能由应用工程完成
  • 分支版本只在临时性的情况下发生,例如马上需要给客户演示,并且需要在短时间修复一些bug再次演示时,我们可以临时性的打出一个分支。需要明确的是,这个分支一定是抛弃型的,并且是短期存在的
  • 721中的功能会随着客户的增多带来功能迁移的情况,也就是以前是个性的可能会变为可变性或共性,以前是可变性的可能会变为共性,共性的也可能会变成可变性功能,这就要求我们在产品开发过程中随时进行重构

可变性管理

  • 处理可变性的方法

软件产品线工程方法 - 四个主要方法原则中介绍过产品线中的可变性管理,在技术架构上来讲,存在以下三种基本的处理可变性方式:

上图中矩形框代表整个软件,三角矩形代表组件,圆形代表接口。下面我简单介绍一下这三种方式,后面会把我们现在常用的一些技术对应到这三种方式上。

  • 适配

只有一个组件实现,但是该组件提供各种接口方式来改变它的行为,例如可能采用配置文件、运行期参数或者组件源代码补丁方式。

  • 替换

一个组件有多种实现,每个组件都符合该组件接口规范。领域工程中可以提供多种实现,然后在应用工程中选择其中一个,或者在应用工程中遵循组件规范开发一个个性的组件

  • 扩展

扩展需要架构提供一些允许增加新组件的扩展点,添加的组件可以是特定产品或者框架内部的。这些组建不是系统提供的功能,而是由外部插入到系统中的,这就要求系统架构必须考虑清楚有哪些扩展点。

  • 具体的可变性机制
    • 继承(适配)
      子类通过继承父类来改变一些默认行为,只有一个实现组件
    • 补丁(适配)
      如果可以获得组件的源代码,通过补丁方式可以有效地更改部分行为,而不需要维护整个组件。通过这种方式,补丁由应用工程来维护,而组件本身由领域工程来维护
    • 编译期配置(适配)
      编译器提供机制在编译期改变组件,预处理和宏就属于这种方式。Makefiles可以编译多个不同变体的组件,或者选择一个正确的组件
    • 运行期配置(适配)
      组件内部有多种实现,运行期可以通过配置动态改变组件行为
    • 代码生成 (替换)
      代码生成通过读取一些高级别模型或者脚本等约定来生成某些组件或者整个产品所需要的代码
    • 组件替换 (替换)
      默认实现了多个组件,这些组建可以是领域工程实现的,也可以是应用工程特定实现的,只要符合一定接口约定都可以通过替换整个组件来改变具体功能实现方法
    • 插件 (扩展)
      有很多插件为系统提供扩展点,插件只要找到扩展点就可以添加额外需要的功能

考虑模型驱动

在没有模型驱动时,客户化工作更多的可能是通过代码、配置、脚本来完成,如果考虑模型,则需要对可变性建模,以下是产品线工程中的一种可变性元模型图例:

如果我们也支持类模型,那么类模型和可变性模型可以按照以下方式对应:

如果我们采用了代码生成技术,通过这些模型后,我们可以进一步对特定产品只生成需要的代码。

应用案例场景

例如清单综合单价积累可以形成典型清单库,通过积累过程也可以形成图集组价库。对于这种需求来说,从用户需求以及销售角度来看,我们可以把对图集库的支持作为产品的可选附件。我们实现的理想方案可以是提供一或多个dll,当考到目录下系统则加入图集功能,这就需要我们应用上面的可变性技术来解决。

  • 采用适配和替换方式,通过从综合清单类库继承下来,增加图集相关属性
  • 添加相应的一些图集相关模块
  • 把图集相关的内容部署到独立于主程序的dll,以便通过简单的复制功能达到模块的配置
  • 当然还有更多的一些方法,这些需要在实际工作中不断深化……

发表评论