2018-10-04 难以估计的工作量

本篇,让我们尝试用科学的方法进行一些讨论,为什么工作量往往难以估计,为一个Delay的项目加人通常是下策,为什么重构有用,以及为什么好的设计至关重要。

定性分析

研发效率 R 随着代码量 C 的增长而递减
-- John Adhoc

定量分析

研发效率本身是难以度量的,但为了讨论起见,我们不妨定义几个变量,并试着加以讨论。

  • C 当前的代码总量,业界通常以行数计。
    注:此处不考虑不同编程语言的差异,假设有统一的语言(PHP除外)
  • Ce 当前的有效代码总量,指实际产生价值的有效代码。

打个形象的比方,C 好比一袋薯片,包装完好,膨胀十足。 Ce 好比打开了包装,瞬间泄气,发现包装里一半是空气,其真正有效的薯片总量远远少于包装给你的预期。之所以严格区分, CCe,本质就在于通常人们直接见到的工作量由C 决定,那就像人月神话一文中提及的,码农的工作产出其实是非线性的,即真实的劳动价值无法用直接观测可得的C决定。

由此,我们可以定义研发效率函数 R = d(Ce) / d(C) ,即假设 Ce 是相对于 C 的函数,则 R 对应其导函数,基于我们的定性假设,R 是一个 减函数,即随着C的增加,研发效率是递减的。

  • Rc 表示当前代码规模 C 下的生产效率,即在当前规模下,每增长单位代码行数,所能实际产生的有效代码行数。

举例来说,假设以10000行代码为基本生产单位。下表是一个具体的例子(注意到研发效率随代码规模增加而递减),假设 R = 10000 / (10000 + C) 的情况(这是一个假设,实际中,也较难衡量R函数的实际曲线,在此我们使用一个双曲线函数来估计,从笔者的经验来看,这不妨是一种可能合理的近似):

C Ce 当前研发效率:Rc 每再增加10000行代码能获得的有效代码
0 0 10000 / (10000 + 0) = 1.0 10000 * 1.0 = 10000
10000 10000 10000 / (10000 + 10000) = 0.5 10000 * 0.5 = 5000
20000 15000 10000 / (10000 + 20000) = 0.33 10000 * 0.33 = 3300
30000 18300 10000 / (10000 + 30000) = 0.25 10000 * 0.25 = 2500
40000 20800 10000 / (10000 + 40000) = 0.2 10000 * 0.2 = 2000

提升研发效率的方法

我们换个思路,将上表的最后一列置换成:增加10000行 有效代码 所需要的代码量:

C Ce Rc 在当前规模下,增加10000行 有效代码 所需要新增的代码量
0 0 1.0 10000
10000 10000 0.5 ~30000
40000 20800 0.25 ~70000

我们注意到一个算不上惊人的事实,假设一个码农的生产力为 10000行代码 / 月,注意到在项目初期,代码规模较小的情况下,完成10000行有效代码的工作时间为 10000 / 10000 = 1 人月。 之后再增加10000行有效代码,工作时间为 30000 / 10000 = 3 人月。 突然暴增3倍。 进一步,如果在此基础上,再增加10000行有效代码, 则需要工作时间为7人月,几乎一定会导致项目Delay。

在现实生活中,我们把每10000行代码视作产品的一个新增功能。 则对应每增加一个新增功能,对应的工作量远远超出直觉(项目经理/项目经理的预期)。 造成这一困扰的主要原因只有一个,即 R 随着 C 增长而下降。

避免这一困境(项目要延期)的方案:

  1. Ce 不变的情况下,减少当前的 C ,这相当于间接提升 R
  2. 提升 R
  3. 提升 C 的增加速度

对应现实,方案1通常意味着功能回归情况下,代码重构,清除冗余。 方案2通常意味着架构变更,模块解耦,使得开发能够并行。方案3,意味着加人,但相对而言是性价比较低的策略。显然,1,2是上策。 3是下策。如果非要选择3,建议和1,2中的某一个选择并行。

为什么重构是必要的

劳动人民在田间劳作,每年收获农作物。土地也需要恢复,肥力会下降。所以有经验的农民往往会交叉种植不同的农作物,并适当修养土地,才能保证来年更好的收成。在业界,这一现象,叫做重构。

C Ce 当前研发效率:Rc 每再增加10000行代码能获得的有效代码
0 0 10000 / (10000 + 0) = 1.0 10000 * 1.0 = 10000
10000 10000 10000 / (10000 + 10000) = 0.5 10000 * 0.5 = 5000
20000 15000 10000 / (10000 + 20000) = 0.33 10000 * 0.33 = 3300
30000 18300 10000 / (10000 + 30000) = 0.25 10000 * 0.25 = 2500
40000 20800 10000 / (10000 + 40000) = 0.2 10000 * 0.2 = 2000
40000 22800 0.20 此时选择重构,缩小代码规模至 23000,生产效率恢复到0.30
40000 22800 0.30 3000 (如果不重构,则为2000, 提升50%效率)

上表展示了重构造成的差异,本质上是通过减少代码规模,使得研发效率函数右移(对应的是效率回到了之前小规模代码的程度)。 定量的计算,使得重构的价值可以被衡量,注意,在日常工作中,经理们往往不容易被码农的经验直接说服,通过一些看似“科学”的计算方式,可能更容易争取到空间,这背后的动机我们放到之后的章节中再讨论。

由此表也可以看出,重构的时间是非常关键的,在不同的 C 规模下,选择重构,对应的生产效率的提升百分比差异是相当大的(有兴趣的读者可以自己计算,在表格不同行选择重构意味着什么)。

最后,请注意这里讨论的假设:

  • 重构总是顺利的(事实上总不是),将代码规模下降其实是一件远比增加代码困难得多的事情。
  • 重构其实是需要代价的,这就是研发需要平衡的,即重构需要的工作量和带来的生产效率的比较,上表中,50%的效率提升,如果对应重构需要的工作量仅为3人天,则显然是划算的,反之,如果对应重构的工作量就需要1人月,则不如将这1人月继续投入到水深火热的劳作中去,带来的收益更大(即重构可以推迟)

为什么设计如此重要

最后强调一下设计的重要性。

设计的本质,就是降低系统协作的复杂性。
好的设计,可以使得 研发效率曲线 R 下降的更慢。这是设计好坏的有且唯一的评价指标。
-- John Adhoc

再举例来说,假设以10000行代码为基本生产单位。下表是一个具体的例子(注意到研发效率随代码规模增加而递减),假设 R = 10000 / (10000 + C / 2) 。(这次我们聘请了经验丰富的设计师,做了充分且有效的架构设计,使得研发效率下降变慢)

C Ce 当前研发效率:Rc 每再增加10000行代码能获得的有效代码
0 0 10000 / (10000 + 0) = 1.0 10000 * 1.0 = 10000
10000 10000 10000 / (10000 + 10000 / 2) = 0.67 10000 * 0.67 = 6700
20000 16700 10000 / (10000 + 20000 / 2) = 0.5 10000 * 0.5 = 5000
30000 21700 10000 / (10000 + 30000 / 2) = 0.4 10000 * 0.4 = 4000
40000 25700 10000 / (10000 + 40000 / 2) = 0.33 10000 * 0.33 = 3300
50000 29000 10000 / ( 10000 + 50000 / 2) = 0.28 10000 * 0.28 = 2800
60000 31800 注意到,之前完成30000行有效代码,需要花费110000行代码,现在仅需要 60000行,效率提升接近1倍

从上表可以看到,仅仅是修正研发效率曲线 R , 从 R = 10000 / (10000 + C) => R = 10000 / (10000 + C / 2),即使得研发效率在生产30000行有效代码时,提升接近100%(有兴趣的读者可以继续计算,越往后差异越大)。 这就是 设计的力量

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,922评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,591评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,546评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,467评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,553评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,580评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,588评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,334评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,780评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,092评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,270评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,925评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,573评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,194评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,437评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,154评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,127评论 2 352

推荐阅读更多精彩内容