系统调整的成本

许多组织在发展过程中需要开拓新的业务线、寻找合作伙伴或者与其他公司合并。在这些商业活动中,企业会花费巨大的成本对系统进行调整。但有时候这些成本甚至超过了计划带来的效益。这就非常尴尬了,本来是想通过自动化的系统来提升效率的,结果却因为系统限制了业务的灵活性。 那么这些成本到底是怎么产生的呢?如果对这些调整逐一分析,你会发现无论是对单一系统进行改动,还是对跨系统集成的系统改动,其成本的都是一样的。而相对于修改单一系统,对集成系统改动的成本和风险会大很多,所以大部分人会倾向于修改分散在各部分的系统。

通用概念引起的语义耦合

在软件中,系统服务(Services)会出现像数据类型(data types)或者实体名称(entities names)的概念,这些概念是通用的,会在服务(Services)之间相互引用。 比如,有一个小型的零售系统,是用微服务来实现的。其中有一个很重要的实体类型叫SKU(Stock Keeping Unit 库存),这个实体表示“可以出售的商品(或虚拟商品)”。在一个典型的零售系统里,一个SKU通常会有很多属性,这些属性被用来描述商品的定价、配送、在WEB上的展示、超售、交叉销售、评论、分类以及征税方式等。 SKU一般保存在MDM(master data management 主数据管理系统),除此之外,MDM中会保存其他的数据,这里我们不详细展开,重点是要知道MDM中的SKU数据会提供给其他的服务,如下图:

语义耦合的危害 - 图1

每个微服务都会根据服务本身的功能要求来使用SKU的信息。比如内容管理系统会使用“描述和销售”内容,用于WEB上的展示;定价服务则会把价格信息添加到销售规则中;物流服务则会用到承运人、物流参数、费用等信息;而对于订单服务,这个系统中最复杂的服务,则需要跟踪库存、订单、交货规则、退款等信息。

假如我们现在对SKU做一个比较大的调整,会出现什么问题?比如,调整价格管理的方式。一般的做法是对每一个SKU单独设置售价,但是由于目录众多,不可能使用这种方式一个个修改,因此,我们引入一个新的概念“价格点(price points)”。“价格点”是指被应用到各类SKU中的一个价格。当我们修改“价格点”时,所有与“价格点”相关的SKU都会被统一修改。这样,当我们想对某类SKU进行降价处理时,只需要对这类“价格点”进行调整就可以了。

假如现在要引入“价格点”这个新概念,那么我们需要修改多少微服务呢?

如果把“价格点”看做一个核心实体对象,那上图中依赖于SKU的所有微服务都必须添加这个实体。这种调整的影响面是非常大的,会消耗的成本也很大,甚至不值得做这个调整了。又或者不增加“价格点”了,通过组织一支临时工的队伍,每两年手工修改一遍价格,这样也能够对付。但这肯定不是一种完美的做法,毕竟自动化的主要目的就是要让工作变得高效。如果只是因为系统修改起来太麻烦就坚持使用过时的处理方式,这对于一个企业的长久发展是不利的。

消除语义耦合

问题的关键是“价格点”这个概念出现语义耦合了。其实有很多系统不需要关心“价格点”,比如物流服务和评分评论服务就跟它没什么关系。
那在这个例子中,如果我们不把 “价格点” 定义为核心实体,而是将它作为作为 SKU的一个附加信息,那所有下游服务将收到的SKU的价目表,至于这些价格表是怎么来的,下游服务就无需关心了。这样就达到了消除“价格点”语义耦合的问题。 再具体一点,就是将SKU和“价格点”的“多对一”的关系去掉,相当于消除了一个实体,同时也消除了所有下游服务对这个实体的引用。 # 在服务中形成一套统一内部标识 由于SKU包含的信息非常多,我们甚至可以将其分解成多个独立的概念。对于MDM可以保留SKU这个概念,但对下游的每个服务都应该有一套内部概念,可以映射到SKU的相应信息。 语义耦合的危害 - 图2 以上图为例,定价服务不需要知道它正在为SKU定价,它只需要给“商品”定价,这两句话听起来好像没什么分别。一般来说,我们认为SKU是一个统一的概念,所以按照这样的思路在所有微服务中创建了该实体对象。但是如果我们能够在定价服务中增加一个全新的概念,这个概念能够映射到SKU,是不是也能实现定价服务的功能。这样就不用要求所有跟SKU相关的数据都称作SKU了。 我们应该仔细的检查每个微服务,不断的问自己“这个服务真的需要用到SKU吗?还是因为SKU刚好存在你需要用到的信息?”我认为在所有情况下,服务真正需要用到的是“那些可以被确定的东西”。比如定价、征税方式、物流、评论等。是否只有SKU能够被征税?是否只有SKU能够被评论?等等。

消除语义耦合的好处

在消除语义的这个过程中,我们会发现四个现象:
  1. 服务将会减少;
  2. 服务会变得更加通用;
  3. 服务会形成一套内部的标识;
  4. 团队组织会更加灵活。

总结

这篇文章提出的关键点是,一个概念有时候看起来不可拆分,只是因为我们用了一个词来描述它。但仔细观察就会发现,我们可以找到概念中的一些业务的边界,根据这些边界再拆分出新的概念。同时,不要把所有的东西都做成通用的,也不要把所有的下游服务都耦合到整体的概念,以及不要把下游服务耦合到一些关系复杂的概念。那样做的话,往往对会后期的调整带来很大的麻烦。