仓库源文

.. Kenneth Lee 版权所有 2020

:Authors: Kenneth Lee :Version: 1.0

见素抱朴:一个关于交付的例子


这两天参与一个交付方案的讨论。这个方案需要交付一个软件给一个市场域。我们姑且把 这个方案叫App。App现在已经有了,也在交付了。现在面对的新问题是:

  1. App除了需要支持老的硬件H1,H2外,还要支持正在开发中的新硬件H3

  2. App需要至此新的市场域中的新的OS,比如原来支持OS1,OS2,现在还需要支持OS3

  3. 新的市场域的交付节奏和原来不同,新的市场域需要从每年一个Release变成每个月一 个Release

我参与讨论前,实施团队已经讨论过几轮了,最后这个讨论是要消除几个分歧点,然后最 终决策。

我看了一下当前的分析,发现讨论得非常“充分”:比如竞争对手现在似乎如何交付的,我 们也可以如何交付,分多少个团队,每个团队的责任范围在哪里,需求进来以后谁先负责 ,新功能谁负责,bugfix谁负责,功能在版本间迁移谁负责,Debug谁负责等等。

我对这个方案从“根子”上就不满意:这看起来不是针对如何交付的,而是在划分“责任范围 ”。我们一个Team的人,只是分工一下而已,要不要弄成几个公司一样啊?

但在讨论现场,这一点可以Keep in mind,我们暂时忽略掉,不讨论它。那我们针对怎么 对客户好,继续讨论下去,实施方继续讨论要分多少个分支进行开发,开发方法是什么。

我还是觉得这个讨论“根子”上是不对的。这就是我以前讨论过的问题:

    :doc:`“知不知”如何影响决策的?`

我们在讨论一个抽象:“一个新功能进来,由哪个版本负责”。这个新功能是什么?都没有 确定呢。所以“新功能”这个名字,在这个语境中就是个“名”,是个抽象,不是具体“可以按 Channel独立复位设备功能”或者“可以设置设备水线深度”这样的具体需求。在这个高层抽 象中,你没有足够的信息对现在这个逻辑进行抽象设计。

那这个问题应该如何入题呢?

我的看法是这样的:首先,这个支持新市场域是谁提出来的?谁来埋单?你不要告诉我你 和市场部的人或者客户的工程师聊两句,觉得挺有道理,就屁颠屁颠给我接个需求进来, 这个首先得和我们的市场机构正规沟通过,确定是要做这个交付,愿意为此投入多少人, 我们才能谈。这个是我们首先要确定的“知”,没有这个“知”,后面所有的决策就有很大的 风险,这个就算现在我们不知,我们都值得先花点人力去搞清楚,否则一旦开始交付,钱 就像流水一样出去了,到时发现你搞错了,杀了你都没用。

知道我们有多大市场收益,可以投入多少人,是后面所有决策的基础。否则你的方案说得 这好那好的,你没人做,说根毛噢。

接着,我们不讨论抽象,我们不说“一个新功能进来”这种飘渺的东西。我们先用硬的东西 建个架子,然后我们可以根据新问题来调整。只要有东西是硬的,就已经可以支撑我们决 策了,这些硬的东西是:

  1. 原市场域是必须保持的,不能修改

  2. 新的市场域是确定要做的,无论需求是什么

  3. 新的市场域的交付节奏我们基本上是认知的

  4. 新市场域可以投入的人头数是基本确定的

那么我们先做的决策应该是落实有多少个独立维护的版本,比如一种可能的方案是这样的 :

  1. AppO-1:现在已经在原市场域使用的版本,支持OS1, OS2, H1, H2

  2. AppO-2:原市场域支持新硬件的版本,支持OS1, OS2, H1, H2, H3

  3. AppN-1:支持新市场域的版本,支持OS1, OS2, OS3, H1, H2, H3

(请注意这里每个版本都是需要根据市场情况做小版本升级的,因为你要修Bug,要加安全 补丁)

然后我们放人进去,把对这些分支的开发需求落实到具体团队,开始运作就OK了。

实施团队还是不死心:这些版本主流都是一样的,那新需求进来了,哪个版本的团队先负 责?

我的答案是:看到需求后,觉得该谁负责就谁负责,我们又不是多个公司,我们不是有架 构组,有管理团队吗?领导不是一个人吗,下面能自己决定就自己决定,吵起来向上要决 策就好了,为什么要提前处理这些还没有发生的事情?你以为这是包产到户,你的一亩三 分地别人不能动吗?这就是个“知不知”的问题,新需求是啥都不知道呢,凭什么现在决定 ?

问:如果把需求分配给AppN-1,但AppN-1的人没有这个开发能力怎么办。

答曰:到时把其他团队的人给你派过去好了,现实就是这么些人,难道推给其他的“自己人 ”,这件问题就不存在了?

再问:这三个团队有很多重复的东西,我们是不是应该建立一个机制,避免他们互相越走 越远了。

答曰:既然它们是重复的,为什么你要分成三个版本,一个版本不好吗?分成三个版本, 因为它们的驱动力是不一样的,比如AppO-1已经在原来的市场上使用了,你敢说“我有一个 AppO-2了,兼容AppO-1,你升级吧"吗?

你不敢。

因为用户工作环境中的东西,你不敢动。但用户如果升级了OS1的安全补丁,导致和你的 AppO-1不兼容了,你的AppO-1要不要升级呢?你还是要的,因为你给用户做了这个承诺的 。所以,如果你要支持H3,你的AppO-1被分解一个AppO-2是大概率事件。我们当然不希望 分多个版本维护,但很多时候,这个不是你可以控制的。

这样细细一看,其实你就发现了,你分成多少个版本,这些版本应该如何开发,根本不是 你驱动的,而是你的市场域驱动的。你现在为决策而决策,提前说要做什么“公共设计和控 制”,你的决策条件是什么?提前决策你没有决策条件的东西,就是一个“不知不知”的陷阱 啊。

你确定三个版本,后面有新需求来了,你可以先分配在这三个版本上,如果来了新需求, 你能分配在这些版本上,你就直接分配了。就算有一些小问题,部分客户的期望不能被完 全满足,那他也得接受,否则我们就不做这个生意了,因为你所有的细节设计都是基于这 个的,没有足够利益驱动,调整它就影响现在的生意了。

如果这个客户特别有钱,有钱到可以让你加人,或者让你放弃掉另一个市场域。那我们再 拉分支,关分支,做定制,都是有基础的。因为那个时候我们已经有确切的信息可以支持 我们决策了。

而所谓要不要有公共机制保证版本之间能尽量共享代码,这是弱于上面逻辑的另一个维度 。这种问题,我们很容易通过调配人力去控制。比如我可以定义一个AppA分支,我投80%的 人力给这个分支,其他几个分支都从这里拉特性,构架特性肯定自然会落到AppA分支上, 其他人也会想办法回合Bugfix到这个分支上,否则他们活不下去。更何况他们又不是独立 自主的,还有我们架构组的人盯着他们的具体设计呢。

而且,上面定义的版本其实是个基线,那个只是现在说得好听,AppN-1支持OS123,H123, 这个一定能做到吗?OS123也是有生命周期的,比如OS1,有OS1-1, OS1-2, OS1-3三个版本 ,OS1-1是早期的版本,进入维护期了,你让它支持你的H3硬件?根本不可能。所以,一旦 你针对着特性和具体的版本去分配你的需求,你想得特高大上的什么“AppH全兼容所有平台 ”的名,都不是那个意思了。我们自然就会直接谈“分配需求”,把“实现XX功能”这种高大上 的名(“九层之台”),就会落实为一组:“某某二进制版本,从什么时候开始,在某个平台 上,支持XX功能,生命周期在xx年xx月结束,如果客户加钱,可以延长到xx年xx月结束”这 样的“工作”(“垒土”)。这就叫“见素抱朴”,从一个“名”,解构为具体的一组事。

最后总结一下,这个案例,其实讨论了两个架构问题:

  1. 知不知:架构设计需要控制自己的决策节奏,不要尝试在信息不足的时候去提前决策。 我们很多时候总以为“这个事情反正迟早要决策的,为什么现在不先猜一个?”,没有注 意的是:提前决策本身破坏了结果,然后失去和后期决策的柔性。

  2. 见素抱朴:每个高大上的架构决定,都要落实下来,变成一组最脏的工作。让你那些高 大上的“名字”,始终有一些看着不爽的脏东西跟着你,这样你这些高大上的“名字”才能 一直接着地气。高大上的名字是我们的“追求”,但这个“追求”没有基础事实作为支撑, 它就飘到天上去了。架构控制难就难在这里,架构师即不能让实施团队失去了那个“追 求”,也不能自己失去了对“脏问题”(实施中最Tough的部分)的敏感,否则就会沦为纸 上谈兵了。

推广

前面讨论的是架构设计问题,下面推广到哲学上。

把一件事情做成,有很多的随机要素,所谓到老方知非力取,半缘修道半缘……啊呸……三分 人事七分天。但很多人事情做不成,完全就是自己作死,不肯面对现实。

所以,我们做战略决策要警惕一个陷阱,就是把事情抽得过于高大上。我以前经常说,架 构是设计未来,但我还没有说,设计未来的风险是脱离了现在。这两者是互相限制的。如 果我们在设计未来的时候,用过多的抽象,就会给自己找到安全感,这个安全感会破坏你 的设计逻辑。

比如曾经有人和我聊天,说自己工作快十年了,升迁得不快,对未来很迷惘。我跟他讨论 ,你最近的业务如何如何?为什么某某工作机会没有给你?这种具体的问题,他就特难受 ,因为他根本没有考虑过这些问题。他其实希望我给他这样的抽象:人生的际遇自有天定 ,你前十年没有发展,这是正常的,很多人其实也是一样的,比如马爸爸到40才创业,任 老爷子60才发展……诸如此类的。这些都是抽象,只是个解释,反正不会明天就开始执行。 但如果面对现实:我现在手上有什么筹码,我还可以赢什么筹码,先搞定现在哪件事情。 这个事情就累了,他马上就不想想了。他其实就是找一个“我也在进行战略思考”的幻想, 其实他从头到尾都没有在进行战略思考。

大部分的狡辩其实都是这样的,你犯了错误就犯了错误,狡辩的人会把具象拉高为抽象: 我是不是人民群众?人民群众是不是不能犯错?……你凭什么批评人民群众?或者你们所有 人都要执行我的编程规范,为什么你要搞特殊?大公司是不是都有编程规范?Linux是不是 也有CodeStyle?为什么你不能执行“我”定义的编程规范?……这种把抽象和具象互相交叉建 逻辑的,你根本没法跟他讨论,就对不到一起去,你只能埋头做自己的事,让他自己死去 。但我们身边这样决策的人很多。

所谓见素抱朴,就是破坏掉这个抽象的名,把千里之行映射为积于硅步,把九层之台映射 为起于垒土。我们不能没有了千里之行这个理想(心善渊),也不能不面对积于硅步这个 现实(事善能)。我们不能反过来,操作的时候谈抽象,抽象的时候又说这“没鸟用”,这 谁也救不了你。