既然软件是一门基于逻辑的科学,那我们不妨借助已有几世纪历史的经典力学来认识这一新兴学科。
来自讨论
最近在微博讨论软件开发节奏和粒度的问题时,提到“我一直想找能够手摸到沙子的沙漏,让大家亲自体验下使劲按沙子到底能不能加速沙子的下落,至今未找到,会议室的不敢毁”。
@哥很酷 :“找个漏斗不就行了,费那事”,
@joe阿牛 :“呐,挑战一下就发现你隐藏的假设了吧? 「人人都是狼性大漏斗」,这才是老板们通常的预期那!”
@哥很酷 :“重赏之下,一天能干25个小时的活”
@joe阿牛 :“又一个挑战,揪出另外一个假设:老板其实看重的是性价比,重赏?成本不就上去了么? 其实是没想通,好的开发流程和节奏,能够整体上达到较好性价比。 ”
从而引发了一场关于软件开发到底是沙漏还是漏斗的讨论。
力学中的漏斗和沙漏问题
经常,我们会把开发中的任务比作从漏斗中通过物料,即把任务比作物料,让其有序的花一定的时间通过漏斗。那么开发中的终极问题就是如何让物料尽可能快的通过。
我们先来看看经典力学如何解决这个问题:
在这里我们忽略物料与漏斗壁的摩擦力(注意,这里忽略的理由是,现实中摩擦力远小于其它力),固定细颈的直径,那么只有物料的高度会影响物料的下落速度(势能转化为动能),高度越高下落速度越快。
但是现实中是否是这样呢?答案是不一定。如果物料是流体,那么会是这样;如果是粮食,可能也一样;但我们几乎所有人却都见过违背这个假设的现象:当物料高到一定程度,漏斗竟然堵掉了——虽然每块物料都能单独通过细颈。或者我们为了加快速度,人为从上面施加压力的时候也会出现这种情况,为什么呢?
我们先来画一个单个小于细颈的物料的受力分析:
物料的受力无非是图中这两种,一种是合力,沿漏斗斜壁,一种是重力,垂直于细颈。细节不做赘述,任何一本中学物理教科书中都可以找到。
那多个物料就类似下面的图:
我们看到,在细颈正上方的物料只会受到重力的作用通过,漏斗壁附近的物料带来的压力可以忽略不计,而整体下落速度,受这个柱状范围内所有物料的重心势能的释放决定。所以,基于上图,我们会看到水、沙子(水分子、沙粒直径远小于细颈直径,可以视为流体)满足这样的结论:
“流体的速度与出口的压强有关与容器的大小、形状无关,而压强与水的深度成正比”
但是,上面提到的那种能够堵掉细颈的情况是怎么来的呢?
我们现在把物料的尺寸变大,直到直径与细颈的直径相差不是很大但又能单独通过时,就会得到如下的受力示意图:
当两个物料同时在入口受到合力的作用要通过细颈时,却因为受到了对方的压力而达到受力平衡,这时的结果就是两个物料都不会通过细颈(虽然单独它们都可以)。当然,现实中的物料并不是图中的正圆形,不规则的形状让彼此之间的相互作用力更大(接触面压力、摩擦力),更容易达到受力平衡。
所以,我们得出第二个结论:
“当物料间的阻力无法忽略时,通过漏斗的速度还要被阻力影响,阻力与压强成正比”
那这个结论就解释了我们为什么有时候会发现在物料颗粒比较大,尤其是同时物料的形状极其不规则的时候(或者受潮了),越施压,物料越难通过漏斗,这也类似上千人通过仅有的一个安全出口的撤离速度远小于这些人排成一队跑步过门。
既然如此,那我们是否能将沙漏细颈放大,看成是一个阻力无法忽略的漏斗呢?答案是肯定的。
换句话说,漏斗与沙漏所代指不同的原因是,它们与物料的颗粒比率不同,所以物料通过的情况是不一样的。
压力曲线
那根据上述结论,我们就可以画出流体漏斗和沙漏的压力-速度曲线:
软件开发是漏斗还是沙漏?
好了,至此带大家复习了经典力学,并带大家体验了下生活(上面那些实验,有兴趣的各位可以亲自试试),那把话题转回我们真正要讨论的问题上。
软件开发中,任务与程序员的关系,到底是漏斗还是沙漏呢?
为了回答这个问题,我们需要先寻找这种类比中跟速度的关键点:
- 漏斗的细颈尺寸
- 物料的颗粒大小
- 物料之间的阻力
那对应软件开发(我们假设任务的完成是单向向前的),这三个关键点则是:
- 团队开发速度
- 任务划分粒度
- 任务之间的耦合度(任务清晰程度)
而我们把程序员完成一个任务看作是一个物料通过漏斗时,对于单个程序员的情况则是:
- 程序员单独持续解决一个任务的时间
- 一个任务完成所需的时间尺寸
- 一个任务需要其他任务配合的时间耗损
根据人的典型生理特征,程序员能够持续单独解决单一问题的尺寸,最多只会持续2个小时(详见各大研究报告),即便是某些精英,总不能超过20小时(世界上睡眠最少的人,除了变异人种,不会少于4小时,注意是每天),而一段有效的工作时间,最小应该是5分钟。
一个超过2小时的任务不在少数,而少于5分钟的任务一般不会将其叫做任务,也即,几乎不存在流体这样粒度的任务。所以,我们看到,对应上述的漏斗参数,
软件开发实际上是一个物料和出口直径尺寸相差并不悬殊的沙漏。
狼性大漏斗?
既然类比成立,那为了提高开发速度,我们首先会想到的是增大沙漏的细颈直径,也就是提高程序员连续工作的时间。
但是,我们是否可以无限制的增大这个直径呢?No。人作为一个会疲劳的精密机器(注意,这句话是讨好资本家的),无法无限增大持续工作时间(无法正确完成工作不属于持续工作),因此,我们认为程序员这个沙漏的细颈尺寸是有最大值的。
如果强制提高细颈直径,那我们得到的结果很可能就是——坏掉的沙漏。
当然,所谓重赏之下必有勇夫,任何上限都不是问题,但既然重赏了,为啥不用更高的价钱去买个好沙漏呢?
减少任务阻力
既然细颈的直径有最大值,我们不妨将其作为沙漏的固定值,那么根据上面我们对沙漏的受力分析,看到,阻力在整个过程中不但不可忽略,而且是影响速度的最重要的参数,那么我们不得不关注软件开发过程中的阻力——尤其是造成沙漏堵塞的阻力。
那么这些阻力会有哪些呢?
不切实际的压力
从沙漏的压力-速度曲线图中我们可以看到,由于阻力与压力存在正比关系,那么当压力到达一定阙值,阻力会直接导致出口堵塞,开发速度变为零甚至负值(产生新的任务)
过大的任务粒度
物料颗粒大于细颈直径是无法通过的,这个毋庸置疑。而小于细颈的颗粒太大也会造成颗粒之间的阻力。
当然,我们看到虽然开发中的任务几乎无法达到流体那种与粒度,但我们也看到,减小物料的尺寸,可以减小它们之间的阻力,那么任务尽量小——只要它完整(对于任务的验收及完整性讨论会在另外的话题进行),会提高开发速度。
过紧的任务耦合
任务耦合就好比在物料中加入了水或者磁性,这种阻力让整个开发任务变成了一个黏糊糊的整体,不但难以通过沙漏颈,还很可能粘在沙漏壁,像噩梦般挥之不去。
开倒车
做到一半的任务临时更改需求,是一件比安全出口走到一半的人要原路返回一样讨厌和危险,不但不会增加任务速度,反而会造成踩踏、信任、回流等高成本问题,甚至是隐患。
减少无效投入
有效减少物料内部阻力的手段其实很简单,减少单个物料颗粒偏离出口方向的作用力,也就是说,对最终结果起直接作用的力,只有出口方向的分力,那么,减少无效投入(浪费)是节省成本的关键。
伪多任务
让一台机器能够并行进行多个任务,是让生产率加倍的最有效办法——这是现代多任务计算机给人们带来的最普遍的认识。理所当然,人们也会认为人也是可以多任务的。
但是我们都知道,多任务操作系统在多核CPU出来之前,早已经问世,操作系统的多任务是用CPU时间片模拟的伪多任务——人的大脑也是如此。
既然是伪多任务,那么在PC指针在完成一个时间片启用新的任务的时候,必然需要重新恢复这个任务所需要的上下文环境,这些上下文一般是存储在内存中——如果内存足够大。由于内存的速度明显高于IO,因此这一上下文切换过程不容易被察觉,而如果你的内存够小,还是会感觉到这个过程的。
简单的说,伪多任务在上下文载入时间损耗远小于任务处理时间的时候才是有用的。
回过头来看人脑,它也是以时间片的形式来模拟多任务,但是这个模拟通常时候不是很稳定,因为意识流的存在,人的思维更容易进入一个大片时间片处理单个任务——这也是最对单个任务最高速的处理方式。
同时人脑是一个缓存很小的高速单核CPU(当然,如果你举出来那种凤毛麟角能左手画圆右手画方的超人,也只有双核),所以对伪多任务的上下文载入时间不可忽略,上下文尺度不变,越频繁的任务切换,带来的损耗越严重。
很多研究都表明,人脑从一个任务切换到另一个任务需要的上下文载入时间(完全恢复现场)一般不会少于5分钟,那我们可以认为,任务场景转换时间间隔少于5分钟,伪多任务已经不具备可用性——如果你一定要这样做,那结果便是在不完整的上下文环境中完成了任务,出错是一定的。任务场景转换间隔增加到10分钟,任务处理时间也仅仅是等于上下文载入时间,伪多任务依然是低效的。
所以我们看到,“番茄工作法”把任务转换间隔设置在了25分钟。
以跟头摔多会成长为由的乱搞
对于那些一味喜欢“埋头苦干”“代码成山再修坝”的教派不多做评论,但对于漏斗出口方向之外的其他方向用力,不但会得到较小的分力,甚至会增加阻力,这是我们尽量且有办法去避免的(并没有说上述行为是坏,只是有比它们更好的方法)。
知识分享和传播,是避免过多内耗的有效手段。以建立自激知识圈为目标的失败才是值得投资的地方。
后记
- 本文中开发与沙漏的对比,忽略掉了很多并不能在这个层面影响讨论的细节,最多是从一个近似模型来讨论主要问题,所以,讨论只限文中的问题领域。
- 从漏斗和开发任务的类比中,我们还看到了两个神话背后的本质:人月/人件是建立在流体形态任务上的——这种美好愿望无异于共产主义。
- 经典力学只讨论了二维制约下的粒度问题,而在多维制约下,就需要“电磁波共振调谐”来解释为何任务粒度需要匹配问题域粒度,这个就不展开说了。
沙漏是个讨巧的设定,普通的流体显然比“沙子流”具备更复杂的物理的特性,从而带来更复杂的力学结构。比如说,气体喷射速度不仅和容器(团队?)内部压力有关,也和外部的气压有关;流体的分子之间,显然一定要考虑分子or易变“晶体”间的粘度。
显然人与人之间并不是散沙。