在中学时期,学校非常强调防止踩踏事件的发生,因为在那个年代,踩踏事件屡见不鲜。
和踩踏事件类似的挤兑现象在生活中也非常多。新冠疫情期间,医疗挤兑、物资挤兑,甚至黄桃罐头都变成了挤兑资源。
挤兑则极其普遍的出现在软件工程中。 即使在 Thoughtworks,我早期参与的项目团队也会存在挤兑。有时候没有提前进行技术方案设计,而是在迭代开始之后才由领取到任务中的某一个人来主动进行设计数据库表、枚举和 API,并在每日 Code Review 的时候进行评审。
挤兑总是会在迭代的第一天发生。太多人同时申请开卡(Kickoff)或等待某一个人初始化数据库和一些基础代码。 因为多个人并行工作在一个代码仓库,如果没有提前的规划、安排,则写出来的代码和实现五花八门,因为单纯的规范不能约束到这么细。
导致在每个迭代的第一周非常紧张,出现特别多的返工和重构。
IO 密集型和 CPU 密集型任务
我们开始尝试让部分人提前进行技术方案设计、技术预研,力求在迭代启动后,"大部队" 所需要的准备条件都已具备,这样才能成规模地高速开发和交付。
有一些同事不理解这种实践,认为违反了敏捷宣言和 XP(极限编程) 的思想:不需要事无巨细的计划和设计,通过快速重构来完成迭代。
这种思想没问题,只不过忽略了一个小小的现实问题,进入交付阶段后,反复的确认、澄清、重构都需要时间成本。
有时候时间成本甚至比人力资源更宝贵,这是重构不能解决的。 我尝试使用一个比喻来澄清迭代前设计和规划工作的必要性:
- 迭代前设计工作:主要是澄清、确认、沟通、决策的内容,包括业务方案、技术方案(数据库、API、枚举值、外部接口集成等)。 迭代前的工作往往需要多线跟进等待干系人反馈,但是不需要太多工作量,类似 IO 密集型任务。
- 迭代中交付工作:将技术方案和业务逻辑翻译成具体代码。类似 CPU 密集型任务,尽量避免等待、阻塞的情况发生,才能让交付按时完成。
迭代前期工作就非常需要跑在前面的人,这些人就侦察兵,提前探明路况。
谁跑在前面,跑多远?
有人可能会说,如果提前设计了所有方案,那么剩下的开发人员就是无情的执行机器,得不到锻炼和成长。
这是另外一种误会。 跑在前面是为了大部队跟上的时候不发生挤兑、阻塞和各种问题,如果有人希望接受更多挑战,可以申请尝试去做一些方案设计的工作,只要其产出物能通过评审即可。
另外也不需要什么都提前设计,否则和把代码都写完就没有区别了。 要提前做决策性的内容,消除不确定性。
例如代码样板、领域模型、数据库、枚举、API、外部系统接口、技术预研 Demo等内容的设计(包含中英文信息,才不会多个人的工作串不起来)。
实际上,做技术方案的过程其实是对需求做了一道梳理,提前排雷,避免进入迭代后逻辑不同或者不能实现。
如果是确定性的内容就不用提前做。例如只是实现业务逻辑翻译为程序代码的工作,没必要提前做了。 一个极端的反例是,有团队为了响应提前设计的思想,要求提前做 Tasking,即将任务拆分为实现步骤。 如果在规范完备、有参考打样工程的团队中,这类工作并非不确定的,可以不用提前设计。
迭代准入要求
那么走在前面的人需要完成哪些工作才能让团队有效的进入交付呢? 答案是提前评审。
非常有意思是一些团队会把评审视为考试,想尽一切办法逃避评审。 甚至有人会骄傲的说:因为我们是敏捷开发,BA 和技术人员一起工作,所以不需要评审。
理想中我们会相信每个人都尽可能卓越地完成工作,现实是每个人的产出,或多或少会有缺陷。
一则技术管理的认知是:默认所有人和工作环节都是不可靠的。 通过系统性的机制来控制准入标准,即使在部分环节存在缺陷的情况下,依然可以提升整体的质量,这就是钱学森的系统工程思想。
评审只是系统性控制质量的手段,而非目的。 我们可以训练团队具备主动评审的思维,对自己的产出保持质疑,让团队伙伴帮忙评审。
另外,提前设计的方案还要具备这几个特点才能进入迭代:
- 估算出工作量:用于迭代经理计算人员投入,尤其是存在前后端分工时平衡人力资源就非常重要。
- 测试方式:确保方案可以被验证或者验收。
- 可行性验证:提供了 Demo,确保流程能跑通。
- 准确性:确保被评审的内容可以直接使用,例如表名、字段名。整个 IT 系统可以看做下定义的过程,每个词汇在后期会不断引用前面词汇,所以定义的约准确,整个团队沟通成本越低。
Spike
在敏捷实践中,有个实践叫做 Spike。 值得玩味的是国内敏捷团队把 Spike 仅仅理解为技术预研。
从某种意义上来说,所有需要决策、确认和沟通的内容都需要 Spike。 理想情况下,如果产品经理/BA/TL 在迭代启动后休假团队仍然能继续跑下去,就说明跑在前面的人做的非常出色。
所以在 Scrum 中,Spike 分为:Technical Spikes 和 Functional Spikes。
Spike 的原意是穿刺。就像用钉子扎进坚硬的物体,使其裂开。 软件工程刚好符合这个隐喻。很多项目都是部分提前设计方案+剩下的人搬砖。
总结
敏捷团队的阵型可以看做钉子,整个团队根据认知能力分级。
- 认知能力强、经验多的人能混乱的场景和任务分解为有序清晰的任务。
- 认知中等人将有序清晰的任务分解为能执行、可操作的工作项。
- 认知普通的人只需要无脑执行可执行的工作项即可。
想要跑在前面则需要经验、判断力、预见能力人,如果有几个这样的人跑在前面,软件项目会轻松和顺利很多。
参考资料
[1] What is Spike in Scrum? https://www.visual-paradigm.com/scrum/what-is-scrum-spike/
[2] “预见性强”领导者的特质与成长路径 http://paper.people.com.cn/rmlt/html/2022-11/01/content_25950649.htm
[3] CPU密集型 https://zh.wikipedia.org/zh-hk/CPU%E5%AF%86%E9%9B%86%E5%9E%8B