第 6 章 我们为什么停下来了?
作为项目的驾驶员,你有责任把每个人安全地送到目的地。但旅程可能因为很多原因提前停下。你可能会遇到路障:交通事故、收费站,或者一条挤满了羊的乡间小路。你可能会发现地图丢了,或者车上的人对要去哪儿意见不一。又或者,你可能只是意识到自己应该去别的地方。
项目没在前进——它应该前进吗?
在第 5 章中,我们讨论了如何启动项目。现在来看看项目可能以哪些方式停下来。我们先从出问题时可能遇到的两种临时停顿说起:被某些东西阻塞,以及迷路。
然后我们会看看你可能主动让旅程停下来的几种方式。有时这意味着过早宣布胜利,但有时也确实到了旅程该结束的时候,无论它是否已经抵达目的地。
借这个机会也要指出:作为组织中的领导者,你同样可以帮助那些不是由你领导的项目。有时候,你的时间最好的用法,就是放下手头的事,通过推一把、轻轻点拨、迈出一些小步(好吧,有时也包括重大的升级上报),让一个停滞的项目重新动起来。正如 Will Larson 所说,这一点点时间投入可能产生巨大的影响:
数量惊人的项目,离成功只差一个小改动,离打开新机会只差一次快速调整,离达成共识只差一次对话。凭借你在组织中的特权、你在公司各处建立的关系,以及经验赋予你的预见能力,你往往只需投入最微小的一点努力,就能改变一个项目的结果,而这是你能做的最有价值的工作之一。
为了行文一致,本章其余部分会假设你就是那个停下来的项目的负责人。不过,如果你是介入进来帮忙的,其中很多技巧同样适用。
但别忘了:看到一个问题,并不一定意味着你就该扑上去。正如我在第 4 章所说,你需要捍卫自己的时间。不要陷入图 6-1 时间图所描绘的那种境地:被太多支线任务和援手缠住,以至于没有时间去做你真正要负责的工作。要有判断力!选择那些你的帮助最有价值的机会,然后有意识地采取行动,并计划好事后如何再次抽身。
图 6-1. 你完全可能把时间都花在帮助和推动各种项目上,而没给自己承诺要做的主要项目留下任何空间。
我们先从项目停滞的第一类原因说起:它们被阻塞了。
你堵在路上了
在完美的世界里,团队都是自主的,永远不必考虑彼此的工作。而现实中,任何大型项目都会横跨多个团队、部门和职能。有时甚至一个人的拖延就足以错过一个重要的截止日期。而当项目是一次迁移或下线弃用时,成功可能取决于所有其他工程团队的工作,一路上有很多被阻塞的机会。
无论你面对的是哪种阻塞,都会用到一些相同的技巧:
理解并解释
你要排查到底发生了什么,弄清楚阻塞所在。然后确保其他所有人对正在发生的事情有同样的理解。
让工作更容易
你要绕过阻塞,办法是减少对你正在等待的那些人的依赖。
获得组织支持
当你能证明某项工作是组织目标时,就更容易让它获得优先级。你要展示这项工作的价值,从而获得这种支持。有时你还需要升级上报,寻求帮助来越过阻塞。
制定备选方案
有时阻塞就是不会消失,你要用创造性的方案来取得成功。或者,你要接受这个项目以当前的形式就是无法实现。
我们来看看,当你以各种方式被阻塞时如何运用这些技巧:等待另一个团队、等待一个决策、等待一次审批、等待某一个人、等待一个没有分配出去的项目,或者等待一次迁移中涉及的所有团队。
被另一个团队阻塞
我们从一个经典的依赖问题开始:你的项目进展顺利,但你需要另一个团队完成一些工作,而这件事就是没有发生。如果你运气好,那个团队的负责人会提前告诉你发生了什么、他们什么时候能准备好。如果运气没那么好,那个团队已经不再回复你的邮件,你只能自己拼凑出事情的来龙去脉。等待他们令人沮丧。你掌握的信息他们都有,他们也知道有个发布日期!他们为什么不在乎?去弄清楚。
发生了什么?
如果你所依赖的团队没有交付你需要的东西,几乎可以肯定背后有很好的理由。三个可能的原因是:误解、意外和优先级错位。
误解
即便在沟通路径清晰的组织里,信息也可能丢失。一个团队认为某件事显然需要在某个日期前完成;另一个团队却完全不知道有截止日期,或者对他们被要求做的事情有不同的理解。
意外
生活总有意外。有人离职、生病,或者需要突然请假。你所依赖的团队人手不足、负担过重,或者被他们自己的下游依赖阻塞。无论这件事有多重要,他们都可能根本无法赶上截止日期。
错位
也许这个团队的速度令人印象深刻——只是不在你的项目上。即使你在做的事情至关重要,另一个团队可能还有优先级更高的事。看看图 6-2。项目 C 是团队 2 的最高优先级,他们把它放在所有其他工作之上。但它只是团队 1 的第三优先级!他们有时间才会去做。
图 6-2. 优先级错位的团队。如果每个团队都做自己最重要的项目,团队 2 很可能要一直等团队 1。
应对依赖
下面是这四种技巧的实际运用:
理解并解释 先弄清楚另一个团队为什么没有动起来。是他们不理解需要做什么吗?有什么东西挡住了他们吗?理解意味着彼此交谈。如果私信或邮件不起作用,就改成同步的语音对话——是的,这意味着开会。如果这个团队很难联系上,走一些非正式渠道可能会有帮助:希望你已经和这个团队里或团队附近的某个人搭起了桥梁。(见第 2 章。)
解释这项工作为什么重要,讲清楚你希望他们交付什么、什么时候交付。再给他们一次机会,告诉你这是否现实,或者他们是否可以做些别的事情来解决你的问题。
让工作更容易 如果你需要一个没有时间的团队为你提供某样东西,试着向他们要一个更小的东西。这可能意味着只要一个你绝对需要的功能,而不是你真正想要的好几个。如果他们被自己的依赖阻塞了,想想你能否做点什么来帮他们解除阻塞:如果你能解决他们的问题,让他们得以解决你的问题,那就皆大欢喜!有时你可能会沿着一条依赖链走上一段支线任务,直到找到一个小小的推动点,让所有人重新动起来。
或者,你也可以主动提出替他们完成部分工作,例如让另一个团队写代码,然后发给他们审查。要注意,这个提议可能没有你想象的那么有帮助:比如,在一个难以驾驭的代码库里,指导一个不熟悉的人完成修改,往往比自己动手还要费劲。如果对方团队没有接受你的提议,不要觉得被冒犯。
获得组织支持 如果你在等的团队正在做他们认为优先级更高的事,就去弄清楚他们是否正确。如果优先级不明确,请组织的领导层来裁定哪个项目应该“胜出”。要尊重、友善,但要问足够多的问题来弄明白情况。我希望这不言自明:如果你的组织认为你的工作没那么重要,你就应该让另一个团队专心做他们正在做的事,不要去打扰。
但如果你被阻塞的项目确实更重要,这可能就是需要向双方共同的上级升级上报的情况。无论你有多沮丧,都要陈述不带情绪的事实:说明你需要什么、为什么重要、什么事情没有发生。升级上报之前,可以先和你的项目发起人或经理讨论一下情况。他们可能会提出其他办法,或者愿意替你去进行其中一些对话。
警告
升级上报不意味着大吵大闹或抱怨另一个团队。它意味着和一个有能力提供帮助的人进行一次礼貌的对话,试着一起解决问题。要保持建设性。
制定备选方案 如果那个团队真的抽不出身,你就需要另找办法绕过阻塞。这可能意味着重新界定项目范围、选择另一个方向,或者比原计划更晚发布。事已至此,只能接受。务必就任何日期变更与你的利益相关者和项目发起人沟通,确保他们理解你被什么阻塞了。他们可能有你没想到的解除阻塞的点子。
被一个决策阻塞
团队应该走路径 A 还是路径 B?应该为一个单一、具体的用例做设计,还是尝试解决一个更宽泛的问题?架构、API 或数据结构应该怎么设计?太多东西取决于细节,而没有这些细节就很难取得进展。你可以为最大的灵活性做设计,但那代价高昂,而且你也想避免过度设计。可如果因为走错了路,一年后不得不把方案扔掉,那感觉会很糟糕。于是你向利益相关者要具体的需求、用例或其他决策。而你得到的是……什么也没有。怎么会有人要你去构建一样东西,自己却不知道想要什么?!
发生了什么?
当你在等别人做决定时,很容易觉得他们的工作比你的轻松。他们只需要决定自己想要什么,对吧?然后真正困难的构建工作就落到你头上了。我经常在需要由工程以外的人做出的决策上看到这种偏见。“产品团队为什么就不能……?”就像“就”或“只要”这类词的许多用法一样,答案会很复杂。产品或市场团队(或任何其他人)和你一样,无法仓促做出决定。或者他们可能也在等他们所依赖的某个人提供信息,然后才能做决定。
他们也可能并不理解你在问什么。当工程师向非工程师解释一个工程问题时,这种情况尤其常见。我见过一位工程师问一位利益相关者:“你想要 X 还是想要 Y?”得到的回答是:“好啊,那太好了!”这位利益相关者并不是故意装糊涂!不同的背景和不同的领域语言意味着,他们看不出你问的这两样东西有多大区别,所以不可能做出知情的选择。
应对悬而未决的决策
当你的决策被别人的决策阻塞时,要有同理心:站在他们的位置上,这个决定可能并不容易。但当然,你也不想永远等下去,所以下面是一些在别人难以做决定时推动进展的技巧。
理解并解释 记住你们站在同一边。与其把你在等的人看作障碍,不如看看能否一起穿过这片模糊地带。弄清楚他们做决定需要什么信息或批准,并尽力帮他们拿到。确保他们知道这件事为什么重要,以及在他们做出决定之前(或者如果他们不做决定)哪些事情无法推进。解释这对他们(而不是你!)关心的事情有什么影响。如果他们被阻塞了,弄清楚他们在等谁或等什么。
让工作更容易 想想你是怎么提问的,并在脑中建立一个模型:对方是如何接收这个问题的。真正试着站到他们的角度去想:如果你是他们,你会怎么理解这些话?有没有容易产生的误解?想想能否用图片、用户故事或例子来重新表述这个问题。一旦他们豁然开朗,做决定可能就容易了。
有时问题在于这个决策没有明确的负责人,而各个利益相关者就是无法达成一致。如果你需要的决策被冲突卡住了,可以考虑充当调解人,帮助各方理解对方的观点,找到一个双方都满意的方案。如果你的决策者被他们的决策者阻塞了,就以他们带回去所需的形式,给他们所需的信息。花点时间给他们准备一些要点,让他们需要打交道的人能够理解。如果决策的某些部分比其他部分更重要,就说明哪些部分以后很难或代价很高才能逆转,哪些部分其实无关紧要。
获得组织支持 如果你仍然无法促成一个关键决策,就和你的项目发起人谈谈他们想怎么做。他们可能对前进的路径有些想法,或者能出现在一些你进不去的场合,在那里推动决策的做出。
制定备选方案 在一个重大决策尚未做出的情况下推进项目,往往令人不满意而且复杂:当你必须对各种未来方向保持开放时,方案就没法那么简洁优雅,往往代价也更高。但有时,保留选择余地就是你能做的最好选择。
或者,有时候对正确的路径做出最佳猜测、承担猜错的风险,也是可以的。如果你确实要猜,就把权衡和决策记录下来。1 确保决策者知道你是在猜测,并理解你所选方向的影响。花点时间想想可能发生的最坏情况,以及以后你可能会后悔当初没做什么,并尽一切可能降低这些风险。
最后,要现实一点。如果你的组织无法做出这个关键决策,绕开它就足够了吗?下一个决策时你会不会又碰到同样的问题?也许是时候接受你目前就是无法继续这项工作了。如果是这样,就和你的项目发起人谈谈,告诉他们你尝试过什么,并确保他们也同意无法继续推进。
被一次 $%@$% 按钮点击阻塞
我们都经历过,这让人无比抓狂。你在等一个团队或一位审批人,他们只需要勾选一个框、部署一份配置,或者审查一个五行的拉取请求。这只要花他们 10 分钟!他们为什么就不能点一下那个该死的按钮?!
发生了什么?
我曾经在一个团队里,负责为公司其他所有人配置负载均衡。我们的文档写着,往负载均衡器里添加一个新后端需要提前一周通知;但说实话,每个请求大约只要半个小时。我们需要准备额外的容量、修改配置、重启服务。这是一项频繁的任务,对熟手来说也很简单。其他团队知道我们做的事情并不是什么高深的学问,所以我们经常收到这样的请求:“我们明天上线,所以请今天把我们的负载均衡配好。”而通常,我们并没有配。
我们为什么坚持要提前一周通知?因为这些配置并不是我们唯一的工作。数百个团队都在使用我们的负载均衡器集群,而负载均衡只是我的团队所支持的四项关键服务之一。我们不想一直被动应对:我们希望把每周的工作计划好,把这些配置变更攒成批次来做,而不是每次都去重启服务。因此,对于那些怒气冲冲地跑来质问我们为什么还没做好几个小时前才告诉我们的事情的人,我们没什么同情心。我们团队的座右铭变成了“你缺乏计划,不等于我这里出了紧急情况”。2
再说一次,当你站在另一个团队的位置上时,世界看起来会非常不同!你的请求只是别人工作中的一小部分,是他们时间图上的一个小方块。对他们来说也许只是一次按钮点击,但还有很多其他人也在给他们送来等着点的按钮。他们可能人手不足、苦苦支撑。他们可能在努力改进运营的过程中不断发现边界情况。我见过一些团队意识到他们处理请求的流程无法扩展,于是抽出一些成员去构建更好的方式,结果在短期内团队更加人手紧张,速度甚至更慢。
请记住,其他团队在给出批准时,往往也承担了责任。当你请安全团队“只要点一下按钮”批准你的上线,或者请公关传播团队批准你的对外宣传口径时,你是在请他们在出问题时分担(甚至完全承担!)责任。他们不应该轻率地这样做。
应对没人点的按钮
如果那个团队就是没在做这件事,你可以用本章前面讨论过的大部分处理依赖阻塞的方法。但如果事实证明,与他们打交道有一套标准方式,而你没有按这套方式来,那就需要换一种做法。如果你并不真正着急,也许可以就这么等着,让那个团队排到时再处理。但如果你有一个真正的截止日期,你也没法穿越回去重新走一遍流程。下面再次列出这些技巧:
理解并解释 如果你真的需要插队,试着去请求。尽可能礼貌、友善:比起冲着这个忙碌的团队大喊大叫,道歉会让你得到更好的结果。
如果有人特意帮了你,要说声谢谢。在设有同事奖金或即时奖金的公司里,已经有现成的致谢机制:用起来。如果那个团队在同一个地方办公,你能不能给他们送一份感谢礼物,比如高档的茶或巧克力?至少要把他们列进上线邮件的致谢名单里。事后,别人不会把你记成那个在最后一刻提要求的团队,而是会记得你是那个搭建桥梁、广交朋友的团队。
让工作更容易 就像处理团队依赖一样,把你需要的东西尽可能缩小。组织好你的请求,让对方很容易点头,需要阅读的内容越少越好。(示例见图 6-3。)如果你能看到这个团队收到的其他请求,看看通常会出现哪些问题:缺少什么信息、什么地方复杂、什么地方有争议。试着让你的工单成为那种简单的工单——干活的人会最先拿起它,因为不用太费脑筋。
图 6-3. 一个把所有信息都摆清楚、不需要读太多内容的请求。
获得组织支持 如果你真的没有其他办法获得帮助,而截止日期又很重要,你可能需要请求帮助来插队。注意:升级上报可能会和你求助的团队结下梁子:没有人喜欢自己的总监或 VP 要求他们把某个请求挪到队伍最前面。要尽可能减轻潜在的敌意,明确表示你理解这个团队为什么要有这套流程,并且你是带着歉意请求仅此一次绕过它。
制定备选方案 有可能你和那个团队里某个人已有的(或新建立的)联系,就足以提高优先级。(世界不应该这样运转,但它往往确实这样运转。)不过,如果这些办法都不奏效,你可能就只能等着了。让你的利益相关者知道你会延期。
被某一个人阻塞
如果等待一个团队令人沮丧,那么当一整个重要项目都在等某一个人时,情况可能更糟。工作已经分配了,就摆在某人的桌上,而他就是不做。
发生了什么?
我曾经有个项目被一位同事阻塞,他需要写几个简短的 Python 脚本来解决一个问题。几周过去了,脚本迟迟没有出现,我想自己动手写的冲动一天比一天强烈。我的同事总有很好的借口:出了故障,或者他需要请一天假,或者他的电脑有硬件问题需要修。在为他毫无进展而沮丧了几周之后,我意识到他并不是在偷懒:他是被吓住了。他来自运维岗位,习惯了那种被打断驱动的工作,从一个火场奔向另一个火场,很少有整块的专注时间。这个项目是他开始写代码的机会,但他并不真正相信自己能做到,所以迟迟无法开始。
同事告诉你的阻塞原因,并不一定是真正的原因。这个人可能被吓住了、卡住了,或者手上的事情太多了。他们可能因为个人生活中的某些事情压力很大,根本无法集中注意力;或者他们可能从自己的领导那里收到了关于什么最重要的信息——却不敢告诉你,你的项目不在那份清单上。又或者,你前两次解释时他们没听懂你要什么,又不好意思问第三次。从外面看,所有这些原因都一样:这个人就是没在做这件事。
应对没在干活的同事
当有人难以完成自己的工作时,你有一些办法可以帮忙。先说清楚:你不是这个人的老板,也不是他的心理治疗师,纠正他的拖延不是你的职责。但你也许能得到你想要的结果,而且如果对方经验较少,你还可以借此机会教他一些技能。你可以这样做:
理解并解释 看看你能否进一步了解这位同事到底怎么了。下次和他交谈时,不要只是接受他“再过一周就好”的承诺:再往深里挖一挖。你可能没法弄清真正的原因,但你会感觉到这是不是你能帮上忙的事情。
非常清楚地说明这项工作为什么必要。当你在等一位更资深的同事时,这一点尤其有用,因为他(大概!)是在有意识地判断事情的相对重要性,而不只是在拖延。描述业务需求,说明在他的工作完成之前哪些事情无法进行。如果他工作负担很重,请他在无法完成时告诉你,这样你就有时间寻找替代方案。可以考虑设定一个更早的“继续/放弃”截止点,过了这个时间点,你们双方都明白他无法按时准备好,而你应该另找办法。
让工作更容易 让对方尽可能容易地完成你想要的事情。这可能意味着增加结构、拆解问题,或者设定里程碑:当项目太难时,有时就连思考怎么拆分它都太难了。3 不要把请求弄得晦涩难懂,比如让对方在一份文档里翻找分配给他的行动项,或者让他去揣摩你要他做什么:直接讲清楚你需要什么。看看 Brian Fitzpatrick 和 Ben Collins-Sussman 提出的向忙碌的高管提请求的“三个要点加一个行动号召”技巧:它在这里同样适用!
你到底要什么?
我很喜欢 Brian Fitzpatrick 和 Ben Collins-Sussman 在他们的书 Debugging Teams(O’Reilly)中介绍的“三个要点加一个行动号召”方法。正如他们所写:“一封好的‘三个要点加一个行动号召’邮件包含(最多)三个要点来详细说明眼前的问题,以及一个——只有一个——行动号召。就这些,别无其他——你需要写一封可以轻松转发的邮件。如果你东拉西扯,或者在邮件里放了四件完全不同的事情,那么可以肯定,他们只会挑一件来回复,而且会是你最不关心的那一件。更糟的是,心智负担太重,你的邮件会被完全搁置。”
如果你的同事不堪重负,这可能是一个辅导的机会。让他放心:他正在做的事情确实很难,但是可以学会的。帮助他,但尽量不要接管。4 提问题、回答问题,帮他找到自己的路。
如果你的同事看起来愿意做这件事,只是难以开始,看看你能否和他一起做。我前面提到的那位同事就是这样解决的:一起结对写脚本,帮他越过了这项工作中令人生畏的最初几步,之后他就能自己继续下去了。结对也可以是一起在白板上讨论,或者坐在一起同时编辑一份文档。当你在等自己的经理时,最后这种方式有时会是个好办法:你们可以约一次一对一会议,建议他用这段时间来做你需要的事情,而你待在旁边,随时回答他过程中的任何问题。
获得组织支持 虽然在升级上报之前你应该先尝试其他办法,但归根结底,是有人没有做好自己的工作,这是一个人员管理问题。和他的经理进行一次艰难的谈话会让人不舒服,但如果另一个人是项目即将失败的原因,你若视而不见,那你也没有做好自己的工作。就像我在其他情况下说过的,升级上报不意味着抱怨:它意味着寻求帮助。例如,如果你的同事被阻塞是因为他在做经理认为更重要的事情,那么和那位经理谈谈,可能是调整优先级的唯一途径。
被没人认领的工作阻塞
如果这项工作根本没有分配给任何人呢?当一组团队一起解决某个问题时,有时会出现一项大家都认为需要做、却不在任何人路线图上的工作。它太大了,任何一个工程师都无法单独承担;它需要大量专门投入的时间;或者它会涉及创建一个需要长期负责和支持的新组件:它需要一个团队来负责。也许有好几个不同的团队都认为自己参与了这项工作——他们会出席与之相关的会议,对任何 RFC 都有很多意见——但没有一个团队打算提交代码去实现它。
发生了什么?
这是一个板块构造问题的例子(见第 2 章)。每个团队对自己负责的范围都有清晰的边界。牢固的边界可能很好——它们让每个人保持专注——但现在有一些至关重要的基础工作不属于任何人。我们在第 3 章的 SockMatcher 场景中见过这种情况。很多工程师都关心架构:Geneva 组织的讨论这些问题的工作组吸引了很多参与者。但这些挑战太大,任何人都无法把它当作副业来解决。除非它得到专门的投入,否则这项工作根本不会发生。
如果没有人被指派去做这项工作,那么拆解它、优化它或者制定计划的价值都很有限:在有人负责之前,你都会被卡住。工程师们经常试图通过在相邻的技术工作上投入更多精力,来解决这类组织层面的阻塞。(图 6-4 是一张说明性的藏宝图:那道无法翻越的山脊就是你缺少的人手!)
图 6-4. 除非你能找到办法越过那道无法翻越的山脊,否则走前三条路中的哪一条其实都无所谓。但团队却投入了大量时间争论该走哪一条注定失败的路。
但除非组织问题得到解决,再多的设计和巧妙方案也无济于事。组织上的缺口才是问题的关键。如果你解决不了这个,就是在浪费时间。
应对没人认领的工作
当你被一项似乎不属于任何人职责的工作阻塞时,有几件事你可以做。
理解并解释 一项工作没有负责人,这一点并不总是显而易见,尤其是当有很多团队与它紧密相邻的时候。由于你是最关心它能否成功的人,如果其他人认为现在你就是负责人,也不要感到意外。进行大量的对话,顺着线索追查,弄清楚到底是怎么回事。解读这些信息,得出明确的结论。然后把它们写下来!(见下面的边栏。)保持简短,陈述要清晰:正如我在第 5 章谈设计文档时所说,错误好过含糊,不消除歧义,你就发现不了任何误解。
汇总
GitHub 的经理 Denise Yu 描述了“汇总的艺术”:把所有信息汇总到一个地方,以“创造清晰、减少混乱”。这是一种用途广泛的技巧,适用于任何背景故事繁多、有好几条不同叙事线索、而且有些人可能已经跟不上进展的情况。
把要写进汇总的事实收集起来,是积累知识、确保自己理解现状的好方法。但把一切都写下来,也可能意味着你综合出了以前没有人明确表达过的新信息。也许 Alex 说:“新的库会为这个端点提供身份认证。”后来 Meena 告诉你:“我们要到第三季度才能升级到这个库的新版本。”你可以把这两个事实都写下来,同时写下推论:“至少在第三季度之前,我们不会有身份认证。”
在掌握了全部背景的情况下,这个结论可能显而易见,但如果之前没有人得出过它,有些人可能会大吃一惊。把它明确说出来,就给了每个人对这些信息做出反应、及时调整方向的机会。
让工作更容易 如果你有时间指导、提供建议或者加入做这项工作的团队,在你的汇总里提一下。总监们可能更愿意围绕一个已有的志愿者组建团队,而能够向一位 Staff+ 工程师学习的机会,也可以成为他们吸引其他成员加入时的一个激励。
获得组织支持 你在这个项目上最有价值的工作,就是争取组织支持和一个负责的团队。在你着手为这项工作寻找发起人之前,确保你已经打磨好了电梯演讲,能够解释为什么这个问题值得组织投入时间。你希望发起人不仅相信你,而且在需要时能够向他们的同级和领导层证明这项投入是值得的。
制定备选方案 如果已经有了可信的配备人手的承诺,就耐心一些,给它时间落地:为项目配备人手涉及调整团队,而经理和总监(可以理解地)更希望慎重行事。但如果你无法得到任何人负责这项工作的承诺,或者答复总是“下个季度”,却说不出人手会从哪里来,那就说明你的项目对组织来说不是高优先级,应该推迟。
被一大群人阻塞
我要谈的最后一类路障,是项目需要所有人帮忙的情况:就是那种使用某个服务或组件的所有团队都需要改变工作方式的下线弃用或迁移。很可能,并不是所有人都愿意。
我做过非常非常多的软件迁移,我知道它们有多令人沮丧。你有充分的理由弃用一个旧系统,你确切地知道需要做什么,也已经做了大量沟通,但其他团队就是无视你的邮件。你去追问时,他们说自己很忙——可你也很忙啊!他们为什么看不到这项工作的重要性?
发生了什么?
每个团队、每个人都有自己的故事。有的团队大体上支持迁移,只是没有时间。有的团队反对这个变更:他们可能更喜欢旧系统,或者觉得新系统缺少某个他们在意的功能。还有一群人可能无所谓支持还是反对,只是厌倦了源源不断、令人泄气的升级、替换和流程变更,而他们似乎从中得不到任何好处。
那些推动迁移的人和那些抵制迁移的人,都有各自的道理。但卡在迁移到一半的状态对谁都不好:团队需要花时间同时支持旧系统和新系统,新用户可能还得花时间弄清楚该用哪个,尤其是当迁移停滞、看起来有被取消的风险时。
应对完成了一半的迁移
迁移到一半的状态会拖慢所有必须和它打交道的人。这是 Staff 工程师可以介入并产生很大影响的地方。下面是一些帮助大家冲过终点线的办法。
理解并解释 迁移的来龙去脉可能会被遗忘。我有时听到有人把一次迁移说成“那个基础设施团队就是想玩新技术”,而实际情况是一项无法改变的业务或合规需求,基础设施团队自己也不喜欢。同样,我也听到过“那个产品团队根本不在乎偿还技术债;他们只想做新功能”,而实际上这个团队已经花了半个季度去应对其他迁移,迫切想要开始做自己的目标。理解双方,帮忙讲述双方的故事。说明这项工作为什么重要,也说明它为什么难。做一座桥梁。
让工作更容易 再说一次,说服别人做某件事的关键,是让这件事容易做。一般来说,应该倾向于让推动迁移的团队尽可能多地承担额外工作,而不是依赖其他每个团队多做事。任何可以自动化的步骤,都把它自动化。如果你能更具体地说明你希望每个团队到底做什么——比如你希望他们编辑哪些文件——就多花些时间提供这些信息。另外,希望这不言自明:新方式必须真的能用,而不是逼着各个团队去跳一个又一个火圈。
尽量让新方式成为默认选项。更新所有把人们引向旧路径的文档、代码或流程。找出可能会推荐旧方式的人,请他们帮忙。如果你有组织支持,可以考虑为现有用户设置一份允许列表,或者增加一些阻力,让旧方式更难被采用。我见过的一种做法是:让旧方式继续正常工作,前提是新用户要在配置里写上“i_know_this_is_unsupported”之类的内容。
展示工作的进度。我做过一个项目,需要让数百个团队修改配置以使用一个不同的端点。当我分享了一张图,显示有多少已经完成、还有多少待完成时,人们更积极地去完成自己那部分,好让数字降下来。我们的大脑里有某种东西,就是特别喜欢看到一张图一路降到零!5
有些团队确实会忙得没法迁移,或者有某个你的自动化不太支持的用例。可能还有一些组件已经没有人负责了,所以也没有团队去更新它们。你能和这些团队结对,或者替他们完成变更吗?
获得组织支持 如果你能证明这项工作是组织的优先事项,迁移就会更容易。当然,其推论是,这项工作应该确实重要。如果各个团队被变更压得喘不过气,你的组织就应该优先处理最重要的那些,先完成第一批变更,再开始下一批。如果你无法说服领导层,让你的迁移体现在组织的季度目标或重要项目清单上,也许这说明你现在不该把时间花在这里。
制定备选方案 到了迁移的收尾阶段,你可能需要一些创造性的方案。如果你有组织的授权,而一些团队仍然不动,你能否撤回对旧方式的支持,甚至开始在这条路上增加阻力,比如人为地让它变慢,甚至时不时把它关掉一会儿?没有强有力的组织支持,不要这么做(如果会给客户造成故障,那就根本不要这么做;要理智)。如果最后剩下的几个团队真的拒绝弃用旧系统,你能否让他们成为旧系统唯一的支持者和负责人,让它作为他们自己服务的一个组件来运行?朋友们,最后走的人负责关灯。
你迷路了
我们接着来看你可能难以推进的第二类原因:你就是迷路了。并不是有什么你看得见的东西挡住了你:你只是不知道该怎么走。这可能是因为你不知道现在该往哪儿去,因为问题太难,或者因为你不确定自己正在做的事情是否仍然得到组织的支持。每种情况下,你要用的技巧都不一样。
你不知道大家要去哪儿
想象一下,40 个团队在同一套遗留架构上工作。有一个巨大的单体代码库,十年来令人后悔的决策,以及一团乱麻般、同时归所有人所有的数据。各团队都不敢重构现有代码,于是就把新功能在外面硬加上去。你被点名为负责修复这一切的领导者,还有一个团队专门做这项工作。组织有一个“架构现代化”的目标。感觉你拥有做这件事的明确授权!然而……要做的决策实在太多了。利益相关者太多,每份文档下面都有海量评论,每次会议上的声音都太多。几个月过去了,你没有取得任何真正的进展。
发生了什么?
我们在第 3 章的 SockMatcher 场景中见过这种情况:要解决一个半个公司都热切关心的问题是很难的!每个人都有自己的看法。每个人都确信自己知道正确的做法。在这个例子中,几乎肯定有一群人主张拆分成微服务。另一派可能想要功能开关和快速回滚,好让变更更安全。第三派想转向事件驱动架构。第四派不在乎怎么做,只要底层的数据完整性问题能得到解决就行。这只是众多好建议中的四个。
一大群人去处理一团没有定义清楚的乱麻,几乎不可避免地会陷入分析瘫痪。每个人都同意应该做点什么,但无法就做什么达成一致。你没法驾驶这个项目,因为它只是一堆想法:根本没有项目可供驾驶。
选择目的地
在你非常清楚目的地是什么之前,你无法开始寻找通往目的地的路径。下面是一些选择目的地的方法:
明确角色 在这么大的一个群体里,领导者不能只是房间里的一个声音。从一开始就把角色讲清楚。明确表示你希望听到每个人的意见,但你追求的并不是完全一致:最终会由你来决定往哪个方向走。如果你觉得自己没有权力宣布自己是决策者,就请你的项目发起人或组织负责人明确表态会支持你。如果你没有这样的组织支持,那你可能就没有被放在一个能成功的位置上。
选择战略 除非你知道自己要去哪儿,否则几乎没有机会到达那里。定一条规则:在你们所有人就到底要解决什么问题达成一致之前,任何人都不许讨论实现细节。6 如果可以,挑选一个小团体深入研究这些问题,制定一份技术战略。要强调:任何战略按定义都会做出权衡,不可能让所有人都满意。你们会挑选少数几个挑战,而把其他真实存在的问题暂时搁置。第 3 章详细讲了如何撰写战略:要让大家有心理预期,这不会是一段短暂或轻松的旅程。
选择一个问题 如果分配给你的工程师们渴望马上为这个目标开始写代码,那么说你需要先花时间制定战略,可能会让人沮丧(而且在政治上不受欢迎)。如果你确实没有时间评估所有现有的挑战、按重要性给工作排序,那就选点什么,任何一个真实的问题都行。设定预期:你不会让这个群体被其他(非常真实的)问题分散注意力,但你完全打算在解决第一个问题之后回头去处理它们。再说一次,错误好过含糊:任何一个有意识选择的方向,大概都比僵在犹豫不决中要好。
选择一个利益相关者 选择要解决的问题的一种方法,是选择一个要让其满意的利益相关者。与其去解决“共享数据存储烂透了,我们需要重新思考整个架构!”,你能否去解决“有一个团队想把它的数据迁到别处”?把项目重新定位为把某样东西交付给某个人。目标是按“垂直切片”来解决:先帮一个利益相关者完成某件事,然后再帮另一个。朝某个方向前进,可以帮助打破僵局、明确下一步。一旦你拿出了一些成果,就可以考虑重新回到制定战略、确立全局目标的想法上来。
你不知道怎么到达那里
如果你确切地知道要去哪儿呢?目的地很清楚,路上也没有障碍,但你还是到不了。你不确定怎么解决眼前的下一个问题,或者项目太庞大,你甚至不确定接下来应该解决哪个问题。我在上一章提到过,冒名顶替综合征可能会自我应验:如果你觉得这项工作很难,就可能陷入恶性循环,让你更没有能力去应对它。也许你在回避去想它,但你越是不理这个项目,感觉就越糟。
发生了什么?
这个项目就是很难!可能是要跟踪的事项数量庞大,你感觉完全力不从心,尤其是在出问题的时候。或者,有一项不可能完成的任务——一个技术挑战或一道组织障碍——而你就是不知道怎么越过它。如果你以前没见过这类问题,可能要花些时间才能认清正在发生什么,找到解决办法则要花更长时间。
找到路
前方的路是未知的,但并非不可知!下面是一些开始找路的技巧:
清楚表述问题 确保你对自己要做的事有一个清晰明确的表述。如果你很难表述清楚,试着把它写下来,或者大声地对自己解释一遍。留意那些可以更精确的地方:你指的是谁或什么,以及正在发生的是什么、应该发生的又是什么。和任何愿意与你讨论的人把问题聊一聊,以此完善你的理解。
重新审视你的假设 有没有可能,你已经预设了某个特定的方案,只在那个框架内挣扎着解决问题?7 在可以接受权衡的情况下,你是否在寻找一个在每个维度上都更好的方案?你是否因为某些方案看起来“太简单”而把它们排除了?大声解释你为什么认为这个问题无法解决,可能会帮你发现一些之前没注意到的、其实可以挪动的约束。
给它时间 你有没有遇到过这种情况:被一个编码或配置问题卡住,怎么也解决不了,结果第二天早上一下子就解决了?睡眠真是神奇。度假也有同样的效果。我发现,如果我离开一个问题几天,回来时几乎总会有更好的想法,即使这期间我根本没想过它。
提升你的容量 试图在会议之间的零碎时间里解决问题,会限制你能产生的想法。给自己安排一些专门的时间,在脑子里真正把情况理清楚:光是清空你之前在想的其他事情带来的杂音,就可能需要几个小时。争取以最好的状态去赴这场与自己的会面:对我来说,这意味着睡个好觉、吃不油腻的食物、多喝水,以及待在一个光线和空气都好的房间里。你了解自己的大脑:做任何能让你变聪明的事。
寻找已有经验 你真的是第一个解决这类问题的人吗?看看别人在公司内外都做过什么。别忘了,你也可以向软件以外的领域学习:航空、土木工程或医学等行业,对于很多科技人员以为是自己第一次发现的问题,往往早就有深思熟虑的解决方案了!
向他人学习 和项目发起人或利益相关者把问题聊一聊,有时就能给你足够的额外背景或想法,让你找到下一步。你也可以向公司以外的人学习。大多数技术领域都有活跃的网络社区。看看有没有某个领域专家聚集的地方,花时间在那里吸收他们的思考方式,以及他们提到而你还不知道的关键词和解决方案。
换个角度 从另一个角度看问题,激发创造性的方案。如果你在试图解决一个技术问题,就想想组织层面的解决办法。如果是一个组织问题,就想象一下你会如何用代码来解决它。如果你必须把它外包出去:你会花钱请谁来解决这个问题,他们会怎么做?(这会不会也是一个选项?)如果你不在了,这项工作会被重新分配给谁,他们会怎么处理?
从小处着手 如果你被任务压得喘不过气,又不清楚该先做什么,试着先解决一个小部分,看看能否获得一种进展感,让剩下的工作显得更容易完成。另一个角度是问问自己:你真的需要把这个问题解决得很好吗?一个凑合的方案暂时够不够用?或者,你能不能先从一个很糟糕的方案开始,然后不断迭代,这样你就不是从一张白纸开始了?
寻求帮助 虽然你可能觉得成功与失败之间只取决于你的技能,但你并不是孤身一人。向同事、导师或本地专家寻求帮助。如果你是那种讨厌求助的人,请记住:通过学习别人的经验,你是在分摊他们当初学习同样东西所花的时间;让你们俩都从第一性原理出发去琢磨解决方案,是很低效的。
你不知道自己处境如何
这是迷路的最后一种形式,从某些方面来说也是最可怕的一种:你不知道自己的工作是否仍然有必要。你在最近一次全员大会上听到的某句话,可能让你担心一个新举措会让你的项目脱轨。也许你注意到经理或项目发起人来过问的次数少了,对你的成果似乎也不那么感兴趣了。或者,公司发布了一份公告,列出了所有重要项目——而你的项目不在其中。糟了。和你合作的一些人似乎也不那么投入了:他们谈起你的项目时,更多说的是“如果”而不是“等到”,而且他们在优先做其他工作。他们是不是听到了什么你没听到的消息?这个项目还在继续吗?没人告诉你任何事。你还是负责人吗?
发生了什么?
组织变动、领导层变动和公司优先级的变化,都可能影响大家对你项目的热情。如果来了一位新的 VP 或总监,他们可能不认为你在解决的问题重要;或者有时更糟,他们可能认为这个问题如此重要,以至于要以比你所承担的大得多的范围、由另一位负责人来解决它。你的项目可能真的面临被砍掉的风险,而没有人想到要告诉你。如果你的领导位置比较特殊,这种沟通缺失尤其常见——比如,你所在的组织与承担大部分工作的组织相邻,或者你领导的人比你更资深。当优先级变化时,你很容易被遗忘,或者被排除在做决策的会议之外。
或者,情况也可能完全不是这样!你的项目可能进展得非常顺利,所以领导层对你的关注才变少了。当别处在着火时,没人会去过问一个运转良好的项目。沉默可能意味着“继续做你正在做的事”。
重新站稳脚跟
在不清楚自己处境的情况下沿着同一条路继续走,只会徒增压力,而且你可能是在浪费时间。下面是你可以做的一些事情:
明确组织支持 做好心理准备,你可能不喜欢听到的答案,然后去弄清楚发生了什么。和你的经理或项目发起人谈谈,说明你听到了什么,问问你的项目是否打算继续下去。
明确角色 如果你是负责人,却发现自己不太敢以这个头衔自居,或者你不确定自己被允许做什么,那就需要把角色正式确定下来。我在第 5 章介绍的 RACI 矩阵在这里可能是个有用的工具,第 1 章的角色描述文档也是如此。顺便说一句,如果你试图以“非正式负责人”这样的头衔来运作一个项目,那就是在自找失败——如果你是负责人而其他人都不知道,那你就不是负责人。
要求你所需要的 如果你缺少做这项工作所需的权限、正式认可或影响力,谁能帮你获得这些?想要一些确认,确信你的项目仍然重要,这是很自然的。请求在全员大会上提一下这个项目,或者把它列进组织目标,都是可以的。你未必能得到想要的,但如果不开口,就一定得不到。
重新加油 做一件似乎没有其他人在乎的事情,是很令人泄气的。如果你和你的团队感到精力不足,你可能需要有意识地把它重新积攒起来。重新加油可以是设定新的截止日期、制定新的项目章程,或者举行一次新的启动会或团队外出会议:用“欢迎来到项目第二阶段”来重新出发,不知怎么就比“我们继续做之前在做的事吧,但我发誓这次会不一样”更能激励人。如果你能加入一两位跃跃欲试的新成员,他们的热情可能就足以让团队重新动起来。
你到达了……某个地方?
项目停下来还有第三个原因:团队认为项目已经到达了目的地……然而不知怎么,问题并没有得到解决。
我见过很多项目像图 6-5 那样收场:离目标只差一点点。项目计划里的所有任务都完成了,团队成员领了表扬,转去做别的事情了,但客户仍然不满意。
图 6-5. 团队宣布胜利后就回家了——但还有另一份更好的宝藏,他们始终没有拿到。
在本节中,我们会看看三种在没有真正到达目的地的情况下就宣布胜利的方式:只做定义清楚的工作,做出了方案却不告诉用户,以及仓促交付一个粗制滥造的东西。要警惕这些终局状态!
可是代码已经写完了!
我感觉在我的职业生涯中,这样的对话我已经经历过上百次了:
-
“我很期待新的 foo 功能。什么时候能用上?”
-
“哦,已经做完了!”
-
“太棒了!我怎么开始用?”
-
“嗯……”
“嗯……”之后,跟着的总是我今天用不了它的种种原因。foo 里还有硬编码的凭证;它只在预发环境运行,没上生产;有一个 PR 还在等审查。但对方会坚持说它已经做完了。只是还不能用而已。
发生了什么?
软件工程师常常认为自己的工作就是写软件。我们规划项目时,往往只列出与写代码有关的那部分工作。但要让用户真正用上这些代码,还有太多事情需要做:部署和监控、获得上线批准、更新文档、让它真正跑起来。软件准备好了,还远远不够。
LaunchDarkly 的开发者布道师 Heidi Waterhouse 曾经说过一句让我醍醐灌顶的话:“没有人想要使用软件。他们只想抓一只宝可梦。”一个想玩电子游戏的用户,并不在乎代码是用什么语言写的,也不在乎你解决了哪些有趣的算法难题。他们要么能抓到宝可梦,要么不能。如果不能,这个软件就跟不存在一样。
确保用户能抓到宝可梦
作为项目负责人,你可以通过着眼于项目的全局,而不只是看哪些任务完成了,来防止工作出现疏漏。下面是一些你可以使用的技巧:
定义“完成” 在开始工作之前,就最终状态是什么样子达成一致。Agile Alliance 提议设定一个完成的定义(definition of done),即任何用户故事或功能被宣布完成之前必须满足的标准。8 这可能既包括适用于所有变更的通用检查清单——比如,我经常看到 PR 模板里有一节用来说明变更是如何测试的——也包括针对单个项目的一套具体标准。类似地,用户验收测试让新功能的目标用户去尝试他们想用它完成的任务,并确认这些功能运作良好。即使是内部软件也可以有用户验收测试。在这些测试完成、用户表示满意之前,谁都不能宣称项目已经完成。
成为自己的用户 你能否经常使用自己正在构建的东西?当然,这并不总是适用,但如果有办法让你体验客户的感受,就花时间去做。这有时被称为“吃自己的狗粮”(dogfooding)。
庆祝着陆,而不是起飞 庆祝把东西交付给了用户,而不是那些只有内部团队看得见的里程碑。在用户愉快地使用你的系统之前,你还不能庆祝。如果你在做迁移,要庆祝的是旧东西被关掉了,而不是新东西上线了。
做完了,但没人用
你有没有见过一个平台或基础设施团队,花了几个月为一个常见问题打造出一个漂亮的方案,发布、庆祝,然后又因为似乎没有人想用它而沮丧?他们确信它更好:它确实能改善用户的生活。可各个团队仍然在用老旧、费劲的方式做事。
发生了什么?
这个团队没有跳出技术工作去思考。不幸的是,内部方案的推广往往是这样的:我们做出一个有用的东西,给它起一个可爱的名字,(也许)写一份文档说明怎么用它,然后就停下了。我们做的东西可能有很多潜在用户会喜欢,但他们无从知道它的存在;就算偶然碰到,这个名字也丝毫看不出它是干什么的。人们针对这个问题常用的搜索词,也不会把他们引向这个方案。我把这类项目称为“小心豹子”项目,出自我最喜欢的 Douglas Adams 的经典作品 The Hitchhiker’s Guide to the Galaxy(Pan Books)中的一段。
“可是那些规划图一直是公开展示的……”
“公开展示?我最后不得不下到地下室才找到它们。”
“那就是展示部。”
“还得拿着手电筒。”
“啊,嗯,灯大概是坏了。”
“楼梯也坏了。”
“可你瞧,你不是找到那份通知了吗?”
“是的,”Arthur 说,“是的,我找到了。它‘展示’在一个锁着的文件柜的最底层,文件柜塞在一间废弃的厕所里,厕所门上挂着一块牌子:‘小心豹子’。”
这就好像方案的创造者们在试图把它藏起来!信息是存在的——有人得以把自己的文档里程碑标成绿色——但不知道自己要找什么的人,永远也找不到它。
把它推销出去
Michael R. Bernstein 对做出方案却完全不推广这件事,有一个很好的比喻。他说,这就像一个农民播种、浇水、除草、种出了庄稼,然后就把它留在地里不管了。你需要收获你种出的东西,把它带给人们,让他们看到为什么需要它。如果用户不知道它的存在,或者不相信它值得花时间,那么世界上最好的软件也毫无意义。你需要做推广。
告诉大家 你不仅需要告诉人们这个方案存在:你还需要不停地告诉他们。很多迁移之所以停留在迁移到一半的阶段,就是因为工程师们以为用户自己会来找这个软件。帮他们找到它。发邮件、做巡回宣讲、在工程全员大会上争取一个时段。为那些事后很可能替你说好话的特定客户提供贴心的专属服务。如果你们在共享办公室办公,可以考虑贴海报!收集用户好评。了解大家可能对什么心存顾虑或提不起兴趣,确保你的推广表明你已经考虑过(最好也已经解决了)这些问题。坚持不懈,一直告诉大家,直到他们开始互相转告。
让它容易被发现 无论你做了什么,都要让它容易找到。这意味着在目标用户可能去找的任何地方都放上指向它的链接。如果你们有多个文档平台,确保在其中任何一个上搜索都能找到正确的地方。如果你们公司有短链接服务,就为所有可能的名字设置链接,包括人们可能猜测的拼写错误和各种连字符写法。9
它建立在不牢靠的地基上
我要谈的最后一种“做完了但没真正做完”,是一种可能引发很多冲突的情况。那就是一个原型或最小可行产品进入了生产环境,用户用起来也还不错,但所有人都知道它是东拼西凑出来的。用户能抓到宝可梦,工作完成了:产品经理会说,该转去做下一件事了!但工程师们知道,基础设施无法扩展,接口不可复用,或者团队正在把骇人的技术债推给未来。
发生了什么?
尽可能便宜、快速地交付某样东西,可能有很好的理由。当市场竞争激烈——或者存在根本没有市场的风险——时,先把某样东西发布出去,往往比让它足够扎实更重要。但当团队转去做别的事情之后,那个廉价的方案依然留在原地。代码可能没有测试——甚至无法测试。这个功能可能是一个架构上的权宜之计,其他所有人现在都得绕着它走。
很久以前,我曾在一个数据中心工作,我在那里学到的一件事是:根本不存在临时方案这种东西。如果有人从一个机架拉了一根线到另一个机架,却没有把线缆整理整齐、贴上标签,那根线就会一直留在那里,直到服务器退役。每一个临时的权宜之计都是如此:如果在项目结束时你没有把它整理好,以后要清理它就得付出极大的努力。
加固地基
虽然短期内交付粗制滥造的软件也能蒙混过关,但这不是可持续的做法。你是在把软件的成本推给未来的自己。作为 Staff 工程师,你比大多数人拥有更多的杠杆。下面是一些你可以用来倡导保持高标准的办法。
建立质量文化 你们的工程文化会由最资深的工程师的行为来引领。如果你的组织没有扎实的测试文化,就通过成为那个总是要求写测试的人,开始把它往正确的方向推。或者做那个总在追问“我们要怎么监控这个?”的人,或者那个总会指出文档需要随拉取请求一起更新的人。你可以借助风格指南、模板或其他杠杆,把这些提醒推广到整个项目。我们会在第 8 章探讨如何制定标准、推动文化变革。
把基础工作写成用户故事 理想情况下,组织认同交付方案不只是做功能——还要为未来做好准备。功能工作和维护工作之间保持健康的平衡,团队会把保证高质量所需的时间计入项目成本。即便是那些为了尽早获得用户反馈而先构建轻量级初版、或为了更快把有竞争力的产品推向市场而背上技术债的团队,也总会回过头来改进他们交付的东西。
不幸的是,很少有组织能以理想的方式运作。你可以帮忙确保项目的用户故事中包含你需要做的所有清理工作。你可以把这说成用户体验的一部分(没有人会对一个不稳定或经常崩溃的产品感到兴奋),或者说成是在为下一个功能打基础。如果用户提交了相关的缺陷报告,或者故障之后有待办事项,有时你可以用它们来证明清理工作的必要性。把对话重新聚焦到客户的需求上,说明这项工作会对他们产生实实在在的影响。
争取由工程师主导的时间 如果你们公司没有随手清理的常规文化,看看能否推动定期举行清理周。我听说过它们被叫作“修复周”和“技术债周”,也见过不少清理工作是在工程探索时间里完成的,比如“20% 时间”或“兴趣项目周”。另一个选择是设立一个轮值制度,让团队里始终有一个人专门负责响应问题、改进系统。不要纠结于名字,或者某件事是否真的“算”技术债。关键在于,这是一段专门用来做工程师们都知道必须做的工作的时间。
项目就停在这里
在你绕过障碍、应对各种棘手局面的过程中,你会离目的地越来越近——或者发现它终究无法到达。我们以项目可能有意结束的四种方式来结束本章:认定已经做得足够了、提前终止、被你无法控制的力量取消,以及宣布胜利。
这里是更好的停靠点
有可能到了某个时间点,进一步的投入已经不值得付出代价,于是可以宣布项目“已经做得足够了”。我在第 2 章谈到过局部最优:一个团队在做一件低优先级的事,因为那是他们自己领域里最重要的问题,而隔壁团队却有五个更重要的项目没时间去做。你的团队是否在打磨一个其实已经做到足够好的东西、还在给它加功能?也许是时候宣布成功、去做点新的事情了。在这样做之前,看看上一节中的那些失败模式,确保你没有丢下不满意的客户,没有在技术工作一做完就撒手不管,也没有扔下一个迁移到一半的局面。如果一切都没问题,恭喜你到达了新的目的地!
这不是该走的旅程
我见过的最被大家庆祝的成功之一,本来也可以被看作一次失败。一个由资深人员组成的团队花了几个月打造一个新的数据存储系统。其他团队都在热切地等着它。但随着工作推进,这个团队发现新系统在大规模下行不通。他们没有否认现实、为自己做出来的东西四处寻找可能的用例,而是终止了项目,并写了一份详细的复盘。
那是失败吗?并不是!其他团队没能得到他们期待的系统,确实很失望。但存储团队不经过探索,是不可能发现这个方案行不通的。如果他们意识到这项技术对他们行不通,却依然硬着头皮推进,那才是失败。
你听说过沉没成本谬误吗?它说的是人们如何看待自己已经投入的时间、金钱和精力:如果你已经在某件事上投入了大量时间和精力,你就更可能坚持下去、把它做完,即使那是个坏主意。要跳出这种思维模式可能很难,但如果你对某件事是否仍然是个好主意没有高度敏锐的判断,你就可能在错误的路上走很久。
试着留意自己是否身处一个不可能成功的局面;如果是,就尽早抽身。在一个注定失败的项目上硬撑下去,只是在推迟不可避免的结局,还会妨碍你去做更有用的事。良好的判断力包括知道何时止损、何时停下。可以考虑写一份复盘,尽可能多地分享发生了什么。对心理安全感来说,很少有什么比这句话更有力量:“那没成功。没关系。这是我们学到的东西。”
项目被取消了
公司对你们正在做的事情的热情可能会改变。也许项目拖得太久了,或者比预期的更难,收益已经不足以证明成本的合理性。也许新来的高管心里有不同的方向,或者市场变了,或者你的组织摊子铺得太大,正在寻找可以砍掉的项目。无论出于什么原因,这个项目不做了。
你管理链上的某个人把你叫到一边,告诉你这个艰难的消息。如果你运气好,你会比公司其他人更早知道。
我们先从感受说起,因为这是一个艰难的处境。这感觉很糟。即使你的团队理解并接受取消的理由——即使你们都同意!——突然丢下你们制定的计划和里程碑,也会让人很不适应。你们可能都会觉得自己做的工作全白费了。如果你没有参与取消的决定,这可能会让你觉得是个人的失败。你可能会感到愤怒、失望、受骗,或者怨恨一个对你影响如此之大的变化,竟然是在一个你不在场的房间里决定的。这可能是一个合理的抱怨:如果经理们做出重大技术决策,却把技术通道的人排除在外,这也许值得好好谈一谈。但大多数时候,这些决策是在更高层面做出的,做决策的人看的是一个大得多的全局,优化的目标也和你不同。
梳理你自己的感受,承认它们。和你的经理或你信任的倾诉对象聊一聊。试着理解更大的全局,尽可能多地获得不同的视角。然后再和你的团队或下一级负责人谈。告诉他们发生了什么,先讲为什么。给他们时间谈谈自己对这个消息的反应。要尊重他们可能会生你的气——你作为项目负责人,是坏消息的传递者,或者是那个没能“挽救”项目的人。重要的是,他们要直接从你或另一位领导者那里听到这个消息:不要让他们从小道消息、群发邮件或公司全员大会上得知。
给自己和团队一点时间,然后尽可能干净地关停项目。能停止运行的二进制程序,就把它们关掉;能删除的代码,就删掉。如果你认为项目以后确实有可能重启,就尽可能记录下来,让未来的某位工程师能够理解你们当时想做什么。(不过,对它复活的可能性要现实一点。)如果有可以吸取的教训,可以考虑做一次复盘。
这不公平,但一个被取消的项目可能会让晋升受阻,或者打断一连串出色的绩效评级。尽你所能展示每个人的工作。如果你的团队成员要转去做其他项目,务必把他们的成绩告诉他们的新经理,并主动提出在绩效评估时和新经理谈谈,或者写同事评价。如果有人正处于晋升的边缘,要向他的新负责人强调这一点,这样他就不必从零开始重新积累业绩记录。
庆祝团队的工作,以及你们一起拥有的经历。解散一个合作良好的团队令人难过,但要留意将来和这些人再次合作的机会。
这里就是目的地!
恭喜!你完成了你着手要做的事情!
在庆祝之前,再确认一下你确实到达了目的地。你的可衡量目标显示出你想要的结果了吗?用户能抓到宝可梦了吗?地基是否稳固、干净?如果你真的到了终点,就是时候宣布胜利了。花点时间纪念这个时刻,让你们的成功显得特别。对有些团队来说,庆祝意味着聚会、礼物或休假。可能会有邮件里的点名表扬,或者在全员大会上获得认可。寻找机会,通过内部和外部的演讲或公司博客上的文章,让团队成员(还有你自己!)获得曝光。还可以考虑做一次复盘:复盘不只是用来审视出了问题的事情。你从顺利的事情中能学到的同样多。
如果你们的文化中有某个方面是你想要强化的,比如大家互相帮助或者沟通良好,就着重指出它在项目中是如何体现的。点名表扬那些超额付出、或者表现出任何你希望看到更多的行为的人。一个成功的项目,可以是一个绝佳的机会,来庆祝你们文化中你最欣赏的那些方面,并向其他人展示出色的工程是什么样子。
本着向你的组织展示如何做出色工程的精神,我们进入本书的第三部分:更上一层楼。
回顾
-
作为项目负责人,你有责任弄清楚项目为什么停下来了,并让它重新启动。
-
作为组织中的领导者,你也可以帮助重启其他人的项目。
-
你可以通过以下方式为项目解除阻塞:解释需要发生什么、减少其他人需要做的事情、明确组织支持、升级上报,或者制定备选方案。
-
你可以通过明确目的地、就角色达成一致、在需要时寻求帮助,为一个漂泊不定的项目带来清晰。
-
除非项目真正完成,否则不要宣布胜利。代码写完只是其中一个里程碑。
-
无论你是否准备好了,有时项目就是到了该结束的时候。庆祝、复盘、清理。
-
可以考虑使用轻量级架构决策记录(Lightweight Architectural Decision Records)来说明你为什么做出了这样的选择。 ↩
-
回想起来,我现在对其他团队要同情得多。在生产环境中运行一个服务所需的配置数量非常庞大,任何临近上线的团队都有很多事情要考虑。是的,他们大概应该提前意识到自己需要负载均衡,但我们只是他们上线前需要进行的 15 次对话之一。而且我们本该想办法把手动步骤替换成某种自助服务,至少覆盖最常见的情况。换个角度看就不一样了。 ↩
-
如果你就是那个拖延的人,可以试试我在第 4 章提到的日历技巧:把你需要做的任务放进日历。如果连弄清第一步都很难,就专门安排一个日历时段,只用来想清楚这项工作的第一步是什么,再另外安排一个时段去做这一步。给未来的自己布置尽可能小的任务。 ↩
-
眼看着你在乎的工作被做得很糟,真的很难受,但尽量不要插手替他们做。如果这个问题必须马上解决,看看你能否和对方一起做,让他自己走每一步,而不是你直接动手。如果你一直握着方向盘,你的同事就永远学不会开车。 ↩
-
这只有在图表显示出进展时才有效:如果很明显没有人在做这件事,就可能适得其反。但影响他人的社会性一面是一个非常好用的工具:“别人都在做,我们为什么不做?” ↩
-
这永远不会完全奏效,但要坚持下去。你越能让人们不陷入细枝末节,成功的机会就越大。 ↩
-
正如 Leslie Lamport 所告诫的,你应该“独立于解决方案所用的方法,精确地说明要解决的问题”。他写道:“这可能是一项出人意料地困难而又富有启发的任务。它曾好几次让我发现,一个‘正确’的算法并没有真正实现我想要它做的事情。” ↩
-
他们还区分了“完成”和“完完全全地完成”(done-done),并援引了作家、敏捷教练 Bill Wake 在 2002 年发表的一篇文章,文中提出了一个耐人寻味的问题:“‘完成’意味着‘完成’吗?” ↩
-
Google 曾经有一个叫 Sisyphus 的项目,这个名字对有些人来说很好记,但对另一些人来说只是一串不太可能拼对的字母。我会一直佩服那位设置了 go/sysiphus 和 go/sisiphus 这两个短链接、让它们重定向到 go/sisyphus 的人。这也是一种很好的安全实践:它能防止有人在拼错的地址上架设一个假冒的服务。 ↩