定制需求处理模式

cover
面向政企业务开发应用,通常不可避免会遇到定制需求,无论是SaaS形态,还是项目交付,个性化定制需求都是令人头痛的问题。以及由此衍生出的代码管理、需求冲突、交付方式等,都是需要考虑的问题。本文对如何处理定制需求,做简单的总结

根据本人的经验,目前主要想到有3种模式,来处理定制需求

概念澄清

在开始之前,首先需要明确问题域,澄清几个容易混淆的概念

定制需求 ≠ 需求变更

无论做什么系统,需求变更都是必然的。有时是意料之外的变更,有时是产品计划内的演进。但无论需求怎么变化,始终都是一致的,这些都不属于定制需求。典型的比如单机游戏,每个版本都会增加新的特性,但是所有玩家拿到的版本都是一样的。这显然不属于定制需求,而是常规的版本升级。至于是服务端统一部署,还是客户端分发,只是解决应用分发、版本控制的问题。不在本文讨论的范围之内。

姑且下个定义:只有不同的项目,存在差异化需求,这才是定制需求。本文总结的是这种情况。并且这些不同的项目,他们的基本需求是类似的,也就是大概80%以上的需求都是一样的,只有20%存在差异化。否则如果需求完全不同,那显然也不属于定制需求。

跟低代码的关系

低代码(low code)也是近年比较热的概念,相对于传统的开发方式而言,号称可以通过少写或者不写代码的方式,构建应用系统。

所以低码在理想情况下,提供了相对来说“低门槛,高效率”的开发方式。比如说,可以让不具备开发技能的业务人员,通过低码的方式,开发简单的应用系统。但是说句题外话,实际上并没有这么乐观。首先低码平台的功能和易用性如果做得不够好,所谓的“低门槛高效率”存疑,其次对于很复杂或者可用性要求高的系统,低码平台的表现也缺少说服力,最后如果用户是有熟练开发技能的专业程序员,是看不上所谓的低码的。

总之,低代码只是构建系统的方式之一,跟定制需求没有必然联系,属于两个不同的问题域。如果说稍微有点关联,可能是低码在理想情况下,修改代码和发布资产相对方便一些,可以更快地响应定制需求。本文接下来也不涉及低代码

模式1:独立代码副本

这是最基础的方式,即针对每个项目(线下交付方式),或每个租户(SaaS方式)部署单独的一份代码

从代码仓库,到最终部署的系统都是分开的。如果是SaaS方式的话,可能是同一个入口页面,但是根据租户标识,路由到不同的系统里

这种方式最简单,复用度也最低,优点是互不干扰。

standalone

由于大部分代码还是相同的,所以还是要有复用的部分。如果完全不复用的话,也会有问题。比如相同的部分如果要增加feature,或者修复bug,那就需要改N遍,维护的成本很高。

复用的方式有很多,比如提取出公共的代码框架,不同的项目基于代码框架做定制开发(类似于插件化);或者在有定制需求的地方,加上项目标识和编译开关,从一份源码构建出不同的项目版本。由于最终交付的产品还是多套,部署也是分离的,所以这种方式依然属于“独立代码副本”

另外,这种方式针对单个项目量体裁衣,经常能够达到最好的效果。比起下文将要提到的其他模式,这种模式虽然最简单,也最不灵活,但是经常交付效果是最好的。因为其他的方式为了兼顾灵活和通用,通常无法针对特定项目做精细的优化。所以对于超级VIP用户,也可以考虑独立代码副本的模式。

模式2:配置驱动

配置驱动模式,是预先实现变化点,在项目实施时,根据配置项做选择。本质上是通过配置项,走到不同的代码分支,以下是示意图

configuration

这种模式与“独立代码副本”有点类似,如果根据项目标识(可以理解为一种配置),增加编译开关,达到的效果跟这里说的配置驱动差不多。区别在于配置项是用于编译期,还是用于运行期。

本质上来说,区分是配置驱动,还是独立代码副本,关键在于最终部署的是同一套系统,还是不同的系统,前者是配置驱动,后者是独立副本模式。

如果定制需求涉及的逻辑和流程,可以比较容易地分离到不同的分支里,那么通过配置项来切换就是一种比较好的方案。

这种模式的优点在于兼顾了灵活性和复用性,系统的代码只有一套,方便管理,可以避免分支管理、版本冲突等非常麻烦的问题。

但是这种模式,如果定制需求需要添加新的分支,那就需要修改代码重新发布,增加新的代码分支。举例来说

projectc

模式3:元数据驱动

比配置驱动更灵活的方式,是元数据驱动模式。此模式跟配置驱动模式一样,不同项目部署的也是同一套系统,代码库也只有一套。

区别在于,定制需求的代码逻辑,是在运行期根据元数据生成的,而不是事先编码。针对不同项目配置不同的元数据,就可以实现不同的逻辑,满足不同项目的定制需求。基础代码相当于元数据的翻译器,在运行期根据不同项目的元数据,生成并执行各项目的逻辑。

元数据驱动,本质上是抽象变化点,项目实施时根据元数据生成。元数据的形式可以是代码、脚本、数据、图片等

这样说可能有些抽象,举一个具体的例子。比如项目A和B,在某个环节的录入阶段需要2种不同的表单,包含不同的录入字段,这是一个典型的定制需求。

如果是配置驱动的模式,需要预先写好form a和form b,在运行时根据project配置项的值,选择弹出form a或者form b。而元数据驱动的方式,则不需要预先把表单写好,而是为两个项目各配置一组元数据,表单分别根据元数据生成出来。

这种模式明显的优点是更加灵活,比如需要增加项目C,需要第三种表单。那就不需要修改代码。只要增加一套元数据,form c就能生成出来。不需要重新发布版本

总结

用一张图表示一下3种模式的区别

summary

模式 统一代码库 新需求热部署
独立代码副本 no no
配置驱动 yes no
元数据驱动 yes yes

通常的路径,都是从具体到抽象,比较符合客观规律。即先用独立代码副本,做出基础的产品。在项目实施复制的过程中,逐渐识别出变化点。如果变化点的实现是相对固定的,那么就用配置驱动的模式,预先将变化点实现好,在项目实施时通过配置来实现。如果变化点的实现差异性极大,那么就可以考虑用元数据驱动的模式,将变化点隔离出来,实现定制化的交付。

当然也不排除对业务非常熟悉,那么从一开始就能预估存在哪些变化点,设计之初就使用元数据驱动的模式,或许也是可以的。