之前曾经说过关于更新成本较大,之后如果有一些只是思考而不是落地实践后验证的产物的话更新可能会快一点,因此有了本期------以后就叫「瞎逼逼」系列了。
「瞎逼逼」系列不严谨,只是个人的一些简单粗暴学习后的粗浅的看法,请注意。
故事开始:工时计件制
众所周知,程序员不是一个计件工种,但程序员的工资又高,因此,老板们总得有一个考核办法,能够让牛马们心悦诚服的接受自己的工作成果。
最低端的不懂技术的老板,会像工厂组长那样,研究一个程序员每天的打卡时间:这个公式可能是「下班时间 - 上班时间 - 午休时间 = 工作时长 = 你对工作的上心程度」,如果粒度更细的话,可以计算你每次进出门的打卡记录差值,也可以在厕所装上计时器,再完美的扣除「带薪拉屎」的时间。
其实我自己也装过类似于 Timing 之类的用于记录电脑使用阶段前台应用的使用时间,也就是说公司只要愿意统计,完全可以再看看,你多少时间在上网冲浪挂机,多少时间写代码。甚至老板也可以像考场里的监考老师那样四处巡视,看看谁不在工位上。
最终毫无疑问,老板能够得到一个量化数据------你的有效工作时长是多少。但归根结底这也就是个乐子,你肯定不服啊------咱们多少页算得上是个脑力劳动吧,这个量化方法太像工厂拧螺丝的了吧。
强度升级:代码行数 / 需求数量 与 Bug / 事故率
接下来,稍微上点道的老板会想到一些新的统计方式,比如「统计你一周做了多少需求、写了多少代码」又或者根据你写的「Bug 数」、「事故率」来衡量你的专业水平。
在外行眼里乍一看,这似乎满足了「脑力劳动」的衡量标准,但实际上实施后,更容易变成「冲业绩」、「抢着做简单/小的需求」、「遇到事情互相甩锅」。
这个问题我们很好举出反例:
- 假设我的需求涉及到一个比较复杂的架构,我花了一周时间思考边界情况、挑选技术方案、最终用 100 行搞定了这个事情;另一个同事本着能用就行,随便复制粘贴了一个一千行的实现。
- 我这个需求复杂度较高,所以需要一周才能做完,而别的同事能力有限,老板只给他分配了一些边缘的小需求,一天就能做完。
- 我由于负责了一个百万 QPS 的核心业务或者一个迭代了好多年的项目,本身维护成本很高,测试也更仔细,更容易发现 Bug;和一个没什么人用的系统,没有安排测试。
这三个场景中,哪个人干了更重、更难的活?但如果基于这些标准量化,哪个人的业绩又更好呢?
而且「工时计件制」本质只是无端内耗,大家浪费时间。而这个升级版的考核方式让每个人的工作变得更加消极------众所周知,程序员不可能不写 Bug,出了问题第一时间应该想的是怎么样去解决问题,下次不再犯,而不是去追责「到底谁写的这个 Bug,你年终奖没了」。这样只会让更多的人不愿意承担责任,不愿意主动复盘。
当然,这里其实还有一些以数量计算,容易造假的内容,比如:「MR 数量」、「Commit 数量」等等。
量化再升级:函数重复率、与圈复杂度、代码当量
接下来一些更懂行的研发设计出了一些更高端的指标。
以函数重复率为例,上面的一个反例中提到「复制粘贴了一个一千行的实现」,那么我把「复制粘贴」给 ban 了不就行了吗,跟论文查重一样,你得保证你写出来的代码是有质量的,学会代码复用的。
不过,函数重复率更多的也是项目内的一些探测,如果有些人「恶意引用」其他库中的代码,而不采用包的形式引入,也不一定能被检测到。
圈复杂度也是类似,假设你的代码质量低下,完全没有考虑复杂度,属于编码一时爽,维护火葬场,那么相当于你的产出质量其实是不高的,因此有了圈复杂度这个定义。
圈复杂度这个概念其实早在 1976 年就已经提出了,详情可以参考这篇文章,写的很详细:kaelzhang81.github.io/2017/06/18/...。
一个最简单的计算公式是:V(G) = E - N + 2
其中,E 表示控制流图中边的数量, N 表示控制流图中节点的数量。
也就是说第一步:我们需要绘制出流程图,第二步,我们数节点数和边数(实践中肯定是依靠系统来解决这两步的),最终就能得到圈复杂度了。
而得到的量化数据值,我们可以代入表格中在进行打分:
圈复杂度 | 代码状况 | 可测性 | 维护成本 |
---|---|---|---|
1-10 | 清晰、结构化 | 高 | 低 |
10-20 | 复杂 | 中 | 中 |
20-30 | 非常复杂 | 低 | 高 |
30 | 不可读 | 不可测 | 非常高 |
这样看下来就比前两个只考虑数量、不考虑质量的靠谱的多。
同样的,当我们衡量一次变更复杂度的时候,也可以不参考代码行数,而是采用一个叫做「代码当量」的东西。很神奇,这东西其实刚提出没几年,而且是由一家公司提的,但他说的似乎又比单纯的代码行数要靠谱一些,关于这个名词可以阅读:「代码当量」指标解读看这一篇就够了。
简单的来说就是通过 AST 分析变更前后语法树的变动情况,然后进行加权打分来衡量你这次变更的工作量,其中,删除代码的权重就可以比新增和修改要低。这样对于一段代码的增删改和移动操作都能被以一种看上去更科学的方式量化。
这样确实有效避免了注释、Markdown 玩家以及 code style 专家混代码变更行数,可以更好地帮助你衡量脑力劳动量。
这就结束了吗?
就算我们上了强度,想要造假的人依旧可以造假,比如说,我就开个自己的分支,先大刀阔斧的改,跑不跑的起来不管,然后 MR 我合我自己,之后下一个 MR 再把这些都改回来,岂不是双倍的快乐。
对于公司级别的指标来看,这样的问题很难避免,无论是怎么样「科学」的量化指标,都面临道高一尺魔高一丈的挑战。
当然,我并不是完全反量化的,事实上,没有量化数据基础更容易陷入「向上管理优于一切」。在我看来不能以这个冰冷的数字作为一个人工作量的全部去考核,也不能完全以 Leader 一个人判断为准,更多的是基于 Leader 对每个人的工作分配辅以他的对应产出来决定,比如:我们确实不看 Bug / 事故数,但如果一个事故就是人为造成的,非常低端,甚至是由于不合规的操作导致的,那么必然会被追责。但如果一个事故只是因为大家都缺乏相关的经验,那么事后总结,下次注意就够了,不必追责到人。
此外,在上面介绍的考核指标中,我们还可以发现,似乎忽略了对于「需求调研」、「系统设计」、「代码自测」的评估,甚至有些团队在排期时都不一定算上了,而实际上这几点在软件开发过程中甚至比「动手写代码」更为重要。比如我一直倡导技术方案清晰化,要做到「这个方案拿出来,我叫另一个同学按照方案执行,和你自己想的一模一样」,在系统设计阶段就得想到可能存在的问题和落地的方案。
但是在实际工作中,大家往往会忽视这一部分,从某一种角度上来说也是因为这些工作很难被量化价值,每当这种时候,我都会想起扁鹊三兄弟的故事:
魏文侯问神医扁鹊:你们兄弟三人谁医术最好啊?
扁鹊说:大哥最好,二哥次之,我最下。
魏文侯说:为什么这么说?
扁鹊说:我大哥在人家未发病之前就把病根给除了,防患于未然,因此名气连家门口都出不去;我二哥能在人家病情刚起时就给治好,就好像他每次看的都是小病一样,所以他的名声不出当乡本土;我呢,看起大病来,又是在经脉上穿针放血,又是用些猛药贵药,又是开刀做手术,所以人人都觉得我的医术最高明。
总结
「瞎逼逼」系列第一期结束,文章中大部分都以个人 BB 为主,本文其实只是一个很理想的讨论,因为在实际(曾经)带领团队的过程中,即使我强调「不看考勤」和「不看 Bug 率」,大环境如此的情况下,大家的思维习惯也很难改变。(算不算一种「当 Leader 救不了中国码农」)