3.5 如何搭建结构
我们在解决问题的时候,一般有两种方法:一种是从目标出发,沿着不同的路径分解,探求问题的答案;另一种是把各种信息聚合起来,得出一个正确结论或解决方案。这两种方法也是我们搭建金字塔结构时仅有的两种方法:一是自上而下地搭建金字塔结构,即问题分解,也叫作疑问回答分解;二是自下而上地搭建金字塔结构,即概括总结做聚合。
3.5.1 自上而下
如果我们明确地知道要解决的问题是什么,那么就可以考虑用自上而下的方式对问题进行拆解。比如你要准备竞聘,这是一个非常明确的目标,就比较适合做自上而下的分解。
对于写一篇有明确主题的文章也是一样。比如前段时间,阿里巴巴技术协会的同事邀请我写一篇教技术人员“如何写好技术文章”的文章。对于这样的命题作文,我们就可以通过自上而下的方式对问题进行拆解,大部分的技术文章都可以通过What(是什么)、Why(为什么)、How(怎么做)来构建结构,也就是2W1H。
2W1H是构建结构时最常用,也是最有用的框架之一 。因为它涉及一个问题最核心的3个要素,即“是什么”“为什么”和“怎么做”。
有了2W1H这个思考框架,我为“如何写好技术文章”搭建了自上而下的结构(如图3-15所示),接下来写出这篇软技能文章,也就不是什么难事了。
(1)为什么写文章:1)写文章是费曼学习法;2)写文章可以增加影响力。
(2)什么是好文章:1)内容有价值;2)结构要清晰。
(3)如何写好文章:1)选择好内容;2)搭建清晰的结构;3)刻意练习;4)迭代优化。

图3-15 写文章的结构化拆解
2W1H实际上是对5W1H的简化和提炼,如果需要更加全面的思考,那么要尽量满足MECE原则,此时5W2H(Why、Who、When、Where、What、How和How much)可能是更好的选择。
此外,我们还可以用“疑问解答”的方式自上而下地搭建结构。这样做的好处是,一方面可以通过设置悬念来吸引听众的注意力;另一方面,这种不断问“为什么”的方式也在帮助我们更加深入地理解问题,让论证更有说服力。
假设你要给大家分享“猪应当被当作宠物来养”这个话题,大部分听众会很疑惑:“为什么猪可以当宠物呢?”你接着说“猪很漂亮,所以可以当宠物”。这回答了前面的疑问,却又引发了大家新的疑问:“猪怎么能漂亮呢?”,然后你说“因为猪很肥”。大家的疑问更多了:“肥为什么还漂亮呢?”这样一步一步往下走,用先抛结论的倒序方式紧扣着听众的好奇心,如图3-16所示。这种提出疑问、回答疑问的悬念方式是非常有吸引力的,同时,因为你对对方关心的问题逐一进行了解答,说服力自然也会比较高。

图3-16 问答式引导结构
3.5.2 自下而上
有时我们要解决的问题并不十分明确,有时可能面对的是一堆零散的元素。比如在做头脑风暴的时候,我们产出了很多想法,那么要如何整理这些想法,并构建清晰的结构呢?
试想这样一个场景,假如客户最近对销售报告和库存报告很不满意,需要你去调查一下原因。你是一个执行力很强的人,接到任务后,立即开展信息收集工作。通过客户访谈、产品调研,你很快找到了如下一些使客户不满意的原因。
(1)提交报告的周期不恰当。
(2)库存数据不可靠。
(3)获得库存数据的时间太迟。
(4)库存数据与销售数据不吻合。
(5)客户希望能改进报告的格式。
(6)客户希望除去无意义的数据。
(7)客户希望突出说明特殊情况。
(8)客户希望减少手工计算。
面对这些信息,你千万不要急着打报告交差。因为这些信息是零散的,老板没有那么多时间去逐条理解,这些信息的罗列会让人理不清头绪、抓不住重点,自然不能做决策。
那么如何才能让报告更清晰、更易于理解呢?我们可以用结构化思维对同类信息进行归纳分组,向上聚合形成一个金字塔的结构。分组的逻辑是找到共性,比如“周期不恰当”和“时间太迟”都是报告产生的时机不好,可以归为一类。
通过逐条分析原因,我们可以将上述8个原因概括为以下3组。
(1)时机不好:产生报告的时间太晚,无法采取有效措施。
(2)数据质量不好:报告中含有不可靠的数据。
(3)格式不对:报告的格式混乱。
进行分组之后,我们就可以得到如图3-17所示的金字塔结构的报告。

图3-17 金字塔结构的报告
显然,这种结构化的表达能够让问题的表述更加清晰,领导也可以快速抓住问题的要点,并给出相应的决策。
代码晦涩难懂,原因通常也在于“没有结构”的混乱,长方法(long method)之所以是典型的代码坏味道,正是因为它把过多的信息放在了一起。就像前面提到的,人类的大脑不是CPU,一次容不下过多的概念,我们搭建结构的目的是更加清晰地表达,减轻大脑的负担,这和我们强调代码可读性的要求是一致的。
商品是电商系统中最重要、最复杂的要素之一。在发布商品的时候,我们需要组装商品(offer)的各种参数。offer需要的信息特别多,导致组装offer的代码篇幅也特别长。随着时间的推移,还不断有新的信息被添加到这个方法中。如果把代码类比成文章,那么这是一篇没有章节、没有段落的文章,可想而知其可读性和可维护性有多糟糕。


面对这些零散的“素材”,我们有必要对其进行归纳整理,从而构建一个更清晰的结构。通过简单归纳,不难发现,商品信息主要包括商品核心信息、商品描述信息、产品属性信息、销售属性信息、系统属性信息、商品扩展信息等。其中,扩展信息又可以进一步拆分成产品信息扩展(比如是否进口)、销售信息扩展(比如销售单位规格)、供应链信息扩展(比如仓库类型)等,因此可以形成一个如图3-18所示的结构。

图3-18 offer信息的结构化
根据这样的结构,我们可以很轻松地写出如下代码。


按照同样的业务逻辑,对比两种不同的实现方式,不难看出结构在其中起到了重要的作用。所以, 写出优雅的代码也许不在于运用多么高深的技法,而在于是否能静下心来把结构梳理清楚。
3.5.3 上下结合
自上而下地分解与自下而上地归纳,二者不是你有我无的关系。在构建结构的过程中,通常会同时用到这两种方法,不是一次性地从上到下或从下到上,而是上上下下、来来回回、反复修改、反复优化的过程。
我写过一篇《一文教会你如何写复杂业务代码》的文章,其核心思想是提出了通过自上而下的结构化分解+自下而上的抽象建模,上下结合来治理复杂业务的方法论。实际上,这就是典型的结构化思维,是演绎法和归纳法的完美结合。道理都是相通的,结构化思维本来是指导人们进行清晰表达和写作的,但在软件设计和代码实现中也同样适用。
自上而下的结构化分解可以帮助我们更清晰地整理业务逻辑、表达业务过程,这种分解非常有必要,但它过于面向过程,导致代码的复用、扩展和语义表达能力偏弱。因此,我们还需要自下而上的抽象建模,帮助我们提升代码的复用性、扩展性和业务语义表达能力。
我记得有一次在做分享的时候,有一位同学问我:“分解必须是自上而下,建模必须是自下而上的吗?”当然不是,在分解之前,我们可能已经初步构建了模型,同理,在建模的同时,我们也可以同步实施业务过程的分解。这两个步骤是相辅相成的,是螺旋式上升的过程。步骤既可以交替进行,也可以同时进行。随着对问题域理解的深入,我们很有可能在某个时间点重构结构和模型。将自上而下和自下而上的方法分开介绍,是为了说明演绎思维和归纳思维的区别,但在实际工作中通常是上下结合一起使用的。