阿里高级技术专家

张建飞 Frank

《从码农到工匠》作者

读完需要

7

分钟

速读仅需 3 分钟

阿里妹导读:针对业务在不同场景下的差异,我们常常会习惯性地使用 if-else 来实现不同的业务逻辑,久而久之代码越来越难以维护。那么如何消除这些 if-else?面对复杂业务应如何思考和分析?

You should not be a if-else coder, should be a complexity conquer.
——Frank

这篇文章,是对之前我在《阿里高级技术专家方法论:如何写复杂业务代码?》说的“自上而下的结构化分解 + 自下而上的抽象建模”方法论的升级。因为在之前的方法论中,我们缺少一个多维度看问题的视角,这种维度思维的缺失,可能会导致miss掉一些重要的业务信息,从而使我们制定软件设计策略的时候,陷入困难。

有了维度思维,我们便可以更加方面的去看清业务的全貌,更加全面的掌握业务信息,从而帮助我们更加体系化的去治理复杂性。

1

从 if-else 说起

我经常说,我们不要做一个if-else coder。这里的if-else,不是说我们在coding的时候不能使用if-else,而是说我们不应该简陋地用if-else去实现业务的分支流程,因为这样随意的代码堆砌很容易堆出一座座“屎山”。

业务的差异性是if-else的根源。以零售通的商品业务为例。不同的处理场景,其业务逻辑实现是有差异性的。如下图所示,商品业务的差异性,主要体现在商品类型、销售方式和仓储方式的不同。

这三个维度上的差异组合起来,有 2 * 3 * 2 = 12 之多。这就是为什么在老代码中,到处可以看到 if(组合品) blabla,if(赠品) blabla,if(实仓) blabla 之类的代码。

那么,要如何消除这些讨厌的if-else呢?我们可以考虑以下两种方式:

  • 多态扩展:利用面向对象的多态特性,实现代码的复用和扩展。

  • 代码分离:对不同的场景,使用不同的流程代码实现。这样很清晰,但是可维护性不好。

1.1

多态扩展

多态扩展可以有继承和组合两种方式。继承勿用多言,组合有点像策略模式,也就是把需要扩展的部分封装、抽象成需要被组合的对象,然后对其进行扩展,比如星环的能力扩展点就是这种方式。

这里,我们举一个继承的例子,商品在上架的时候要检查商品的状态是否可售,普通商品(Item)检查自己就好了,而组合商品(CombineItem)需要检查每一个子商品。

用过程式编码的方式,很容易就能写出如下的代码:

    
public void checkSellable(Item item){if (item.isNormal()){item.isSellable(); //省略异常处理}else{List<Item> childItems = getChildItems();childItems.forEach(childItem -> childItem.isSellable()); //省略异常处理}
}

然而,这个实现不优雅,不满足OCP,也缺少业务语义显性化的表达。更好的做法是,我们可以把CombineItem和Item的关系通过模型显性化的表达出来。

这样一来,一方面模型正确的反应了实体关系,更清晰了。另一方面,我们可以利用多态来处理CombineItem和Item的差异,扩展性更好。重构后,代码会变成:

public void checkSellable(Item item){if (!item.isSellable()){throw new BizException("商品的状态不可售,不能上架");}
}

1.2

代码分离

所谓的代码分离是指,对于不同的业务场景,我们用不同的编排代码将他们分开。以商品上架为例,我们可以这样写:

/**
* 1. 普通商品上架
*/
public void itemOnSale(){checkItemStock();//检查库存checkItemSellable();//检查可售状态checkItemPurchaseLimit();//检查限购checkItemFreight();//检查运费checkItemCommission();//检查佣金checkItemActivityConflict();//检查活动冲突generateCspuGroupNo();//生成单品组号publishItem();//发布商品
}/**
* 2. 组合商品上架
*/
public void combineItemOnSale(){checkCombineItemStock();//检查库存checkCombineItemSellable();//检查可售状态checkCombineItemPurchaseLimit();//检查限购checkCombineItemFreight();//检查运费checkCombineItemCommission();//检查佣金checkCombineItemActivityConflict();//检查活动冲突generateCspuGroupNo();//生成单品组号publishCombineItem();//发布商品
}/**
* 3. 赠品上架
*/
public void giftItemOnSale(){checkGiftItemSellable();//检查可售状态publishGiftItem();//发布商品
}

这种方式,当然也可以消除if-else,彼此独立,也还清晰。但复用性是个问题。

1.3

多维分析

细心的你可能已经发现了,在上面的案例中,普通商品和组合商品的业务流程基本是一样的。如果采用两套编排代码,有点冗余,这种重复将不利于后期代码的维护,会出现散弹式修改(一个业务逻辑要修改多处)的问题。

一个极端情况是,假如普通商品和组合商品,只有 checkSellable() 不一样,其它都一样。那毫无疑问,我们使用有多态(继承关系)的CombineItem和Item来处理差异,会更加合适。

而赠品上架的情况恰恰相反,它和其他商品的上架流程差异很大。反而不适合和他们合用一套流程代码,因为这样反而会增加他人的理解成本。还不如单独起一个流程来的清晰。

那么,问题来了,我们什么时候要用多态来处理差异,什么时候要用代码分离来处理差异呢?

接下来,是我今天要给你着重介绍的多维度分析问题的方法论之一:矩阵分析法。

我们可以弄一个矩阵,纵列代表业务场景,横列代表业务动作,里面的内容代表在这个业务场景下的业务动作的详细业务流程。对于我们的商品业务,我们可以得到如下的矩阵:

通过上面的矩阵分析,我们不难看出普通品和组合品可以复用同一套流程编排代码,而赠品和出清品的业务相对简单,更适合有一套独立的编排代码,这样的代码结构会更容易理解。

2

维度思维

2.1

多维度的重要性

上面的案例不是我编造出来的,而是我在和张文(我同事)讨论应该用哪种方式去处理业务差异的真实故事。

我记得在和大学讨论完,开车回去的路上,我一直在想这个问题,然后在第二个路口等红灯的时候,突然有一个灵感冒出来。我抑制不住兴奋,一边开车,一边发消息给张文说:“我想到了一个很NB的方法论,能解决在‘多态扩展’和‘代码分离’之间如何做选择的问题”。

其实,我知道我兴奋的不仅仅是解决了这个问题。我兴奋的是,我第一次真正领悟到了多维度思考的重要性。从而有机会从一个“单维度”生物,升级成一个“多维度”思考者。妈妈再也不用担心我被“降维打击”了 :)

结构化思维有用、很有用、非常有用,只是它更多关注的是单向维度的事情。比如我要拆解业务流程,我要分解老板给我的工作安排,我要梳理测试用例,都是单向维度的。

而复杂性,通常不仅仅是一个维度上的复杂,而是在多个维度上的交叉复杂性。当问题涉及的要素比较多,彼此关联关系很复杂的时候,两个维度肯定会比一个维度要来的清晰,这也是为什么说矩阵思维是比结构化思维更高层次的思维方式。

实际上,我们从汉语的词汇上,也不难看出一个人的思维层级,是和他的思考维度正相关的。当我们说这个人很“轴”、“一根筋”的时候,实际上是在说他只有一维的线性思维。所以,观察事物的视角越多,维度越丰富,其思维层级也会越高。

2.2

无处不在的多维思考

有了这些感悟,我开始系统的整理关于多维度思考分析的资料,发现这种思考方式真是无处不在。发现的越多,我越是感慨,为什么如此重要的思维方式,我到现在才领悟到。

波士顿矩阵

比如,在做产品分析的时候,有对产品发展前景进行分析的波士顿矩阵。

订单要素分析

当年,我在1688做交易下单业务的时候,有非常多的下单场景,每种场景下,买家享受的权益是不一样的(如下表所示)。我们当时也是使用了矩阵去表达这个复杂的关系,只是当时还没有想到要将其提升到方法论的高度。

数据交叉分析

在数据分析中,维度分析是非常重要的,特别是维度很多的时候,我们可以通过皮尔逊积矩相关系数,做交叉分析,从而弥补独立维度分析没法发现的一些问题。

简单相关系数矩阵

分析矩阵

最近我碰巧看到Alan Shalloway写的《设计模式解析:Design Patterns Explained》,这是一本非常经典的关于OOP的书,里面的第十六章就是专门讲“分析矩阵”的,作者创造这个方法论的初衷也是因为业务涉及的要素太多,信息量太大,他需要一种组织海量数据的新方式。

我和Alan的路径不一样,但是都得出了同样的结论。由此可见,这种矩阵分析的方式的确是对复杂业务进行分析的一把利器,业务场景越多,交叉关系越是复杂,越需要这样的分析。

组织阵型

生产关系决定生产力,对于一个管理者来说,如何有效的设置组织结构是决定团队是否能高效协作的关键。所以我们可以看到公司里面,每年都有比较大的关于组织结构和人员安排的调整。

对于技术团队来说,我们习惯于按领域划分工作范围,这样做的好处是责任到人、职责清晰。然而,领域只是一个维度,我们工作通常都是以项目的形式的开展,而项目通常是贯穿多个领域的。所以,在做团队组织规划的时候,我们可以通过业务领域和业务项目两个维度去看。

比如,在我负责的商品团队,我会按照如下的形式去做职责划分。

时间维度

除了工作,生活中也到处可见多维思考的重要性。

比如,我们说浪费可耻,应该把盘子舔的很干净,岂不知加上时间维度之后,你当前的舔盘,后面可能要耗费更多的资源和精力去减肥,反而会造成更大的浪费。

我们说代码写的丑陋,是因为要“快速”支撑业务,加上时间维度之后,这种临时的妥协,换来的是意想不到的bug,线上故障,以及无止尽的996。

RFM模型

简单的思考是“点”状的,比如舔盘、代码堆砌就是当下的“点”;好一点的思考是“线”状,加上时间线之后,不难看出“点”是有问题的;再全面一些的思考是“面”(二维);更体系化的思考是“体”(三维);比如,RFM模型就是一个很不错的三维模型。可惜的是,在表达上,我们人类只能在二维的空间里去模拟三维,否则四维可能会更加有用。

3

复杂业务治理总结

在前言部分,我已经说过了,多维分析是对之前方法论的升级。加上以前的方法论,完整的方法论应该是“业务理解-->领域建模-->流程分解-->多维分析”。

为了方便大家理解,下面我把这些方法论做一个简单的串联和解释。

3.1

业务理解

理解业务是所有工作的起点。首先,我们要找到业务的核心要素,理解核心概念,梳理业务流程。

比如,在零售通的商品域,我们要知道什么是商品(Item),什么是单品(CSPU),什么是组合品(CombineItem)。在下单域,我们要知道订单(order)的构成要素是商品、优惠、支付。在CRM领域,我们要理解客户、机会、联系人、Leads等等。

这里,我想再次强调下语言的重要性,语言是我们思考的载体,就像维特根斯坦说的:“凡是能够说的事情,都能够说清楚”。

你不应该放过任何一个模糊的业务概念,一定要透彻的理解它,并给与合理的命名(Ubiquitous Language)。唯有如此,我们才能更加清晰的理解业务,才能更好的开展后续的工作。

3.2

领域建模

在软件设计中,模型是指实体,以及实体之间的联系,这里需要我们具备良好的抽象能力。能够透过庞杂的表象,找到事务的本质核心。

再复杂的业务领域,其核心概念都不应该太复杂,抓住了核心,我们就抓住了主线,业务往往都是围绕着这些核心实体展开的。

比如,商品域虽然很复杂,但其核心的领域模型,无外乎就如下图所示:

3.3

流程分解

关于流程分解,在《阿里高级技术专家张建飞:应用架构分离业务逻辑和技术细节之道》里面已经有非常详细的阐述,这里就不赘述了。

简单来说,流程分解就是对业务过程进行详细的分解,使用结构化的方法论(先演绎、后归纳),最后形成一个金字塔结构。

比如,在商品领域,有创建商品、商品上架、上架审核、商品下架、下架审核、修改商品、删除商品等一些列动作(流程),每个动作的背后都有非常复杂的业务逻辑。我们需要对这些流程进行详细的梳理,然后按步骤进行分解。最后形成一个如下的金字塔结构:

3.4

多维分析

关于多维分析,我以二维的矩阵分析为例,我想我前面应该已经说清楚了。

业务的复杂性主要体现在流程的复杂性和多维度要素相互关联、依赖关系上,结构化思维可以帮我们梳理流程,而矩阵思维可以帮忙我们梳理、呈现多维度关联、依赖关系。二者结合,可以更加全面的展现复杂业务的全貌。从而让我们的治理可以有的放矢、有章可循。

既然是方法论,在这里,我会尝试给出一个矩阵分析的框架。试想下,如果我们的业务很简单,只有一个业务场景,没有分支流程。我们的系统不会太复杂。之所以复杂,是因为各种业务场景互相叠加、依赖、影响。

因此,我们在做矩阵分析的时候,纵轴可以选择使用业务场景,横轴是备选维度,可以是受场景影响的业务流程(如文章中的商品流程矩阵图),也可以是受场景影响的业务属性(如文章中的订单组成要素矩阵图),或者任何其它不同性质的“东西”。

通过矩阵图,可以清晰的展现不同场景下,业务的差异性。基于此,我们可以定制满足差异性的最佳实现策略,可能是多态扩展,可能是分离的代码,也可能是其它。

这就是矩阵分析的要义,其本质是一种多维度思考的方法论。

4

篇后寄语

最后,我想说世界是熵增的(即万物都在缓慢的分崩离析),控制复杂度是我们这些从业者无法推卸的责任和使命。

软件行业的发展才几十年,还是一门年轻的学科,软件工程就像一个刚学会走路的小孩,还很不成熟,有时还很幼稚。

但毕竟还是有几十年的沉淀,还是有一些好的方法和实践可以参考,我的这些总结沉淀只是在前人的基础上,多走了一点点而已。但就是这一点点,也实属来自不易,其中冷暖,只有自己能体会。可以说,这一路走来,是一场对心力、脑力和体力的持续考验。

  • 心力是指不将就的匠心,不妥协的决心,不满足的好奇心、以及不放弃的恒心。

  • 脑力是指那些必要的思维能力、学习能力、思考能力、思辨能力。

  • 之所以说“业务理解-->领域建模-->流程分解-->多维分析”是体力,是因为实现它们就像是在做填空题,只要你愿意花时间,再复杂的业务都可以按部就班的清晰起来。

梳理清晰了,再配合COLA(https://start.aliyun.com/)的指导,我们就有可能写出清晰、易读的代码,就有可能从一个if-else coder升级为一个complexity conquer。

而这不正是我们工程师孜孜不倦的追求吗?

想要加入中生代架构群的小伙伴,请添加群合伙人大白的微信

申请备注(姓名+公司+技术方向)才能通过哦!


推荐阅读

阿里专家常昊:新人如何上手项目管理? 2020-09-29

蚂蚁集团沈凋墨:Kubernetes-微内核的分布式操作系统 2020-09-28

快狗打车CTO沈剑:如何利用计划管理提升团队效率和产能 2020-09-27

找CTO杜仲:技术人别把股权(期权)弄成一张废纸(新书推荐) 2020-09-26

阿里合伙人范禹:常挂在阿里技术人嘴边的四句土话 2020-09-25

阿里技术专家都铎:一文搞懂技术债 2020-09-23

支付宝研究员兼OceanBase总架构师杨传辉:我在数据库梦之队的十年成长路 2020-09-21

阿里技术专家麒烨:修炼测试基本功 2020-09-16

阿里巴巴闲鱼架构负责人王树彬:万亿交易规模技术架构实践 2020-09-05

阿里高级技术专家张建飞:应用架构分离业务逻辑和技术细节之道 2020-08-31

阿里P9专家右军:大话软件质量稳定性 2020-08-03

   END     #接力技术,链接价值#点分享点点赞点在看

阿里高级技术专家张建飞:面对复杂业务,if-else coder 如何升级?相关推荐

  1. 阿里高级技术专家张建飞:深度剖析领域模型vs数据模型的用法

    张建飞 frank 读完需要 21 分钟 速读仅需 7 分钟 阿里巴巴高级技术专家,著有图书<代码精进之路 从码农到工匠>,维护公众号<从码农到工匠> ID:craftsman ...

  2. 阿里高级技术专家张建飞:应用架构分离业务逻辑和技术细节之道

    中生代技术 链接技术大咖,分享技术干货 全文:4449字14图 张建飞 <从码农到工匠> 读完需要 9 分钟 速读仅需 3 分钟 架构 什么是架构? 关于架构这个概念很难给出一个明确的定义 ...

  3. 面对复杂业务,if-else coder 如何升级?

    作者 | 张建飞  阿里巴巴高级技术专家 导读:针对业务在不同场景下的差异,我们常常会习惯性地使用 if-else 来实现不同的业务逻辑,久而久之代码越来越难以维护.那么如何消除这些 if-else? ...

  4. 阿里高级技术专家方法论:如何写复杂业务代码?

    阿里妹导读:张建飞是阿里巴巴高级技术专家,一直在致力于应用架构和代码复杂度的治理.最近,他在看零售通商品域的代码.面对零售通如此复杂的业务场景,如何在架构和代码层面进行应对,是一个新课题.结合实际的业 ...

  5. 阿里高级技术专家箫逸:如何画好一张架构图?

    中生代技术 链接技术大咖,分享技术干货 全文:10000字 阿里妹导读:架构图是什么?为什么要画架构图?如何画?有哪些方法?本文从架构的定义说起,分享阿里文娱高级技术专家箫逸关于画架构图多年的经验总结 ...

  6. 阿里高级技术专家宋意:平凡人在阿里十年的成长之旅

    宋意 读完需要 14 分钟 速读仅需 5 分钟 阿里妹导读:不管是什么角色,成长是我们每个人都必须经历的过程.作为一个技术人,成长不仅是技术上的不断精进,也包括日常工作中的方方面面. 本文分享阿里巴巴 ...

  7. 应用架构的核心使命是什么?阿里高级技术专家这样说

    阿里妹导读:什么是架构?关于架构这个概念很难给出一个明确的定义,也没有一个标准的定义.如果,硬是要给一个概述,阿里巴巴高级技术专家张建飞认为架构就是对系统中的实体以及实体之间的关系所进行的抽象描述.今 ...

  8. 应用架构的核心使命是什么?阿里高级技术专家如是说

    导读:什么是架构?关于架构这个概念很难给出一个明确的定义,也没有一个标准的定义.如果,硬是要给一个概述,阿里巴巴高级技术专家张建飞认为架构就是对系统中的实体以及实体之间的关系所进行的抽象描述.今天,张 ...

  9. 阿里高级技术专家:整洁的应用架构“长”什么样?

    简介: 作者张建飞是阿里巴巴高级技术专家,入司6年,他创建了COLA.希望可以探索一套切实可行的应用架构规范,这个规范不是高高在上的纸上谈兵,而是可以复制.可以理解.可以落地.可以控制复杂性的指导和约 ...

最新文章

  1. C指针9:指针数组(即数组中的每个元素都是指针)
  2. Register-SPWorkflowService 远程服务器返回错误: (404) 未找到
  3. 关于搜狐焦点房产的数据分析
  4. Dubbo(四)之xml配置方式
  5. HDU 5136 Yue Fei's Battle
  6. git暂存工作区stash
  7. OpenCV-矩阵变形reshape
  8. 域服务器账号权限,域中文件服务器权限设置
  9. 【老孙随笔】怎样才能当上项目经理?
  10. 打包openstack of opencontrail
  11. Unreal 4 更改Engine位置
  12. sql Server STUFF()函数
  13. 磁通和磁通链,电感关系
  14. HTML5捕鱼php,html5捕鱼达人 游戏源码
  15. 河南省专利申请费用一览表,郑州专利申请的费用
  16. 构造法 | 栈 | POJ3295.Tautology
  17. 和氟西汀类似的备注_氟西汀一样好听的网名有哪些
  18. 星号构成的直角三角形图案
  19. 0-1岁社群运营有哪些好用的社群工具推荐?
  20. 你还在用for循环遍历list吗?

热门文章

  1. 聚合数据-免费的接口
  2. eNSP第二篇:Eth-trunk,链路聚合,常用命令,二层链路聚合和三层链路聚合
  3. 在Lua中使用枚举型变量
  4. 移动域全链路可观测架构和关键技术
  5. 智能工厂方案与设备选型
  6. 网络渗透测试实验三——XSS和SQL注入
  7. 对比学习sass和stylus的常用功能
  8. 如何用python实现输入1~5的数字能够对应打出周一~周五的程序
  9. 2022/7/17/题解2022河南萌新联赛第(二)场:河南理工大学https://ac.nowcoder.com/acm/contest/37344
  10. CCLE 2022 第五届中国教育后勤展览会