中台扩展性设计(一): 代码是如何腐化的

1,123 阅读3分钟

系列文章:

一、为什么中台系统需要扩展性 ?

这里以电商交易中台系统为例,由于业务及玩法的差异,导致交易行为也存在一些差异。业务影响体现在:如券卡类虚拟商品只需要发码,而普通实物类商品则需要发货,酒旅类需要用户发起预约和商家接单。玩法影响体现在:如业务会叠加一些诸如订金+尾款,免费试等玩法。由于交易流程会随着业务迭代也一起不断变化,因此系统扩展性就显得尤为重要。

二、代码是如何腐化的 ?

一般情况下,在业务迭代压力比较大的时候,系统难免会做一些妥协,如果不经过事先的良好架构设计,代码腐化变得臃肿将不可避免。下面以常见的系统迭代为例,简单介绍一下腐化过程 (系统分层,分模块是基本要求,下面情况只针对业务差异逻辑的处理方式讨论)。

阶段一,硬编码处理差异逻辑。

为了避免对现有功能影响,一般通过 if...else... if...else...方式快速支持业务差异,这也将导致了通用逻辑和业务特殊扩展逻辑耦合到了一起。

public void process(String biz) {
    if (biz == "bizA") {
      Service service = new ServiceA();
      service.process();
    } else if (biz == "bizB") {
      Service service = new ServiceB();
      service.process();
    } 
    ....
}

阶段二, 引入常见的设计模式。

  1. 策略模式,本质上和if...else...没有多少区别,只是看着比较优雅。随着业务方不断增加,或需要扩展的策略不断增加,某个特点行业的差异逻辑依然将会很分散,且请求会触发哪些策略也无法直观看出。
// 常规的策略模式,当前业务方增加时,还是需要不断新增策略
public void process(String biz) {
  // 根据不同业务,找到不同的策略
  Service service = ServiceFactory.getService(biz);
  // 执行策略
  service.process();
}
  1. 路由表,将不同业务逻辑直接路由到不同的流程实现。这种方式不太推荐,会引入很严重的问题,导致逻辑出现发散,降低代码复用性,进个导致整个可维护性出现很大问题。

  1. 动态SPI,依次调用所有实现类。这种方式相当于把差异逻辑下放到了业务方,可以保证中台逻辑稳定。简单业务场景下这种方式还是很优雅的。但是随着业务方增多,实现类执行顺序,是否会相互影响,只能运行时确定实现类等等问题,且仍然无法直观看出该业务有哪些扩展实现。
// 一种spi方式实现的策略模式,可是现实不需要改现有逻辑
public void process(String biz) {
  // 获取service所有实现
  List<Service> services = Loder.loader(Service.class);
  for (Service service:services) {
    // 匹配了当前biz的service会执行逻辑
    if (service.match(biz)) {
        service.process();
    }
  }
}

三、如何解决中台扩展性问题 ?

中台的扩展性解决方案,其中比较优雅的方案,可以参考淘宝的TMF框架的设计思想(一种扩展点插件化设计方案)。具体设计的讲解,以及借鉴该思想的框架实现落地,敬请期待后文讲解。