最近看到一个说法,说软件工程本质上是“手工作坊”,是知识手工业者的大规模协作。I can‘t agree more, 这玩意就是个手艺活,极大的依赖手艺人的个人能力。是的,你没看错,在这个软件定义一切的时代,在这些光鲜靓丽的App背后,是成千上万个手艺人堆出来的风格不同、形态各异、手法不一、带有强烈个人色彩的代码。截止目前,还没有一个有效的工业化、标准化生产软件的方法。
不信你去问问Google的工程师,问问Apple的工程师,问问阿里的工程师,问问华为的工程师…… 至少90%以上的员工会告诉你,他们的代码就是翔。Damn it,操蛋的软件工程!
1. 软件是“软”的
关于“软”这个特征,和陶艺很像,即使是初学者,也能捏出来一个能喝水的容器,但只有大师才能塑造精品。软件也是如此,如果从产品可用的角度看,这并不是一个门槛很高的行当,北大青鸟培训三个月,也能上手。但如果要在满足功能可用的基础上,还要满足非功能属性,控制复杂度,高效有美感,对不起,只有那些少数的匠人才能做到。
软件作为纯思维制品,其实现的“柔性”很大,这一点和工业产品正好相反,标准的工业产品缺少柔性,希望能做到柔性生产,从而满足消费者个性化定制诉求。软件则是天然柔性,很难标准化和工业化。同样的软件产品,你做和别人做会不一样。即使你自己做,同一个产品做两遍也会不一样,同样的需求,你不同的心情,不同的状态,构建出来的模型,搭的架构可能都不一样。所以软件研发,很大程度是取决于个人的能力,个人“手艺”。这也是为什么在信息时代,能诞生很多个人英雄主义的软件作品的原因,比如Linus的Linux,扎克伯格的Facebook等等。
1.1 消解措施:匠心
既然注定是个手工活,那就需要多一点的匠心。匠心是什么?阿里有句土话:匠心,就是把自己极致逼疯也要做好的心。鸡汤话就是你要长期主义,追求卓越,把自己逼疯,不停的锻造技艺,一年,两年,十年,二十年…… 可惜的是,国内35岁以上就不让写代码了,所以匠人不多。
2. 工程是“乱”的
很多人喜欢拿软件工程和建筑工程类比,这是典型的机械类比。在建筑领域,一旦建筑图纸确定,需要多少钢筋、水泥、工期,基本可以确定。后期也不大可能出现大的变更。但软件是“软”的,“软”到连需求是什么都说不清楚,即使你努力把需求做完了,老板也可能突然拍着你的肩膀说:“麻烦再改几行代码,我们还需要一个地下室,明天就要”。这种不确定性和随意性,是导致软件工程形同虚设的主要原因。
2.1 消解措施:敏捷
既然注定会变化,我们只能放弃强规划的迷思,增加应对不确定性的能力。这正是软件研发模式从大规划、大设计、长周期的瀑布(Waterfall),走向敏捷(Agile)的原因。然而过度敏捷容易滑向另一个极端——无设计,随便造。如何权衡短期实现成本和长期可维护性代价,没有特别量化的指标,主要靠经验,我个人即反对“大设计(Big design)”,也反对“无设计(No design)”,最好是足够的提前设计(JEDUF,Just Enough Design Up Front ),比如能预见到的下两个迭代的需求场景,我会综合纳入当前设计的考虑范围。实际上,变化并没有那么可怕,可怕的是你没有应对变化的能力和信心。面对变化,敢于重构才是敏捷的精髓。关于重构,我有两点心得:
重构一定要及时,船小好调头,一拖就变成later equals never,一拖就变成积重难返,一拖就变成技术债,一拖就变成万劫不复的深渊。
重构要有充分的测试做保障,重构不可怕,怕的是改出问题,天下没有无bug的软件,唯有充分的测试,能让你进入那温柔的良夜。
2.2 消解措施:方向大致正确
最近看了一本书《为什么伟大不能被计划》,说对于复杂系统,设定长期目标有时不仅无效,甚至有害。比如教育、孩子的未来。对一个7岁的孩童设定一个确定的30岁目标是荒唐可笑的。
所以华为才会提出——方向要大致正确,组织必须充满活力——的策略。意思是在产业方向和技术方向上,产业替代层出不穷,技术发展快速迭代,即使是行业龙头,也是暂时的,无法完全准确预测未来的方向,所以方向只能是大致正确。正是没有办法在方向上完全正确,组织必须要充满活力,确保战略的执行以及纠偏,才能走向成功。
所以越是不确定性的领域,我们越是要拥抱变化,要接受“朝令夕改”。软件工程,恰好就处在这样的边界上,作为工程学,他有一定的确定性,但作为思维制品(类比文学创作),他又有很大的不确定性。Agile是目前为止,应对不确定性的有效手段。
3. 指标是“骗人”的
研发效能度量,是软件行业经久不衰的争议话题。和对设计的中庸态度一样(JEDUF),对于指标和度量,我的态度也是中庸的。一方面,我相信“没有度量,就没有提升”(No measurement, No improvement),另一方面我也认可度量无效论,因为“你度量什么,人们就会想方设法的完成指标(You will get what you measure)”。
在社会学和经济学中,有一个著名的古德哈特定律(Goodhart’s law),表示一项指标一旦成为政策制定的依据,便立刻不再有效。政策制定者会牺牲其他方面来强化这个指标,使得这个指标不再具有指示整体情况的作用。记住这个定律很简单,记住GoodHeart就好了,因为有很多“好心办坏事”的案例,例如下面这个:
布莱尔当选了以后,他给英国的选民做过一个承诺,说我要求所有的医生,接到患者的预约电话以后,两天之内必须给患者约上看病。你们觉得这是不是一番好意?!
有一次出去演讲,底下就站起来一个妇女就骂他,说你让我们看不上病。布莱尔就很委屈说,怎么可能呢,我要求他们接到电话,两天之内一定要能够看上病,你们怎么会看不上病呢。我就解决这问题,是不是误会我了。
那个妇女就说,没有误会,就是这样。你让我们看病变得越来越难。布莱尔说,为什么会这样,那个女的说,因为我们现在根本就打不通电话。
古德哈特定律告诉我们,对于复杂系统的考量,不能简单的用单个指标度量,这样容易顾此失彼,好心办坏事。
3.1 消解措施:牵引
关于研发效率和质量的指标不可谓不多 ,关于质量常见的有代码覆盖率(Code Coverage),代码重复率,圈复杂度,千行代码缺陷率。关于效率的有需求交付时长(TTM,Total Time To Market),平均缺陷修复时长(MTTR,Mean Time To Repair)等等。
被吐槽最多的应该是代码覆盖率,很多公司将其作为硬性指标作为考核。其结果是研发人员,八仙过海各显神通,想方设法做覆盖,很多UT连assert都没有,这种覆盖即使做到100%,对质量提升也没什么帮助。还有的公司对代码提交量强考核,可是代码量并不等效于工作量和效率啊。
那怎么办?把这些指标都废掉?No,不能废,因为这些指标虽然不精准,但仍有很大的指导和牵引作用。比如一个系统的代码覆盖率不足10%,一个员工半年的代码量只有不到100行,对于这样的偏离,还是能暴露问题的。只是不要做强的KPI考核,否则就容易出现GoodHeart问题。
3.2 消解措施:结果指标
关于GoodHart’s Law,有一个经典的漫画说:“When a measure becomes a target, it ceases to be a good measure”。图中显示如果你用钉子数量衡量,员工就会给你1000个小钉子。如果你用钉子重量衡量,员工就会给你几个巨型大钉子。
实际上,这个例子可以通过结果指标来解决,对于企业来说,最直接的结果指标就是销售额,如果用销售额做指标,你甚至可以不用去关心员工生产的是小钉子,还是大钉子。因为我们的目标不是钉子的大小,而是市场需要什么样的钉子。
在研发效能领域也是一样,比如代码覆盖率是典型的过程指标,关于质量的结果指标是,线上问题数,质量好问题就应该少,故障就应该少。Apache有一个开源项目DORA ,对于研发效能,他核心只关注4个指标,而且都是结果指标。
比如发布频率(Deployment Frequency),一天发布一次,和一个月发布一次,其敏捷程度是不一样的。还有平均恢复时长(MTTR,Mean Time To Restore),易维护的系统,缺陷恢复就快,这个指标比千行代码缺陷率要好。而且DORA的这些数据都是从系统中自动获取,不需要人工干预,所以一方面避免为了收集指标给工程师添加额外工作,另一方面也保证了数据的客观性。
所以对于那些特别依赖指标的团队,两点建议,一个是尽量用结果指标,另一个是自动化、客观的指标数据收集。
3.3 消解措施:抽查
樊登说《混乱》这本书给他最大的洞见,就是对于复杂体系的考量到底应该怎么做。我们不能不考量,不考量的话我们没有安全感,也不知道哪个好,哪个不好。最有效的考量方式是随机性的抽查,最无效的考量方式是什么呢?是确定性的指标。关于确定性指标为什么无效,前面已经阐述过了。
抽查的确是一个不错的方式,特别是对软件工程师的绩效评估。我经常说技术经理是最难做的经理,销售经理管理下属,一个销售额就完事了。而技术经理对下属的绩效评估,完全是一抹黑。没有一个指标能“有效”的反映员工的技术贡献。展开看一下:
业务指标,A技术烂恰好赶上负责的系统业务发展很好,B技术很好负责系统的业务挂了。业务和技术最多就是相关关系,没有因果关系。
代码量,A提交了8万行代码,B提交了2万行代码。但B的代码简洁,高效,谁的贡献大?
代码缺陷,A全年0缺陷,B有100个缺陷。A全年基本在做运维的事情,代码没写几行。B承担了大部分的业务项目。如何衡量?
前文说过,技术指标最好只是做牵引、参考,不能100%作为绩效依据,原因就在这里。抽查的确提供了一个不错的新思路,我计划在今年的代码白盒检视,加入这个“抽查”的考察项。
我会让所有的研发工程师,提供一个亮点说明,叫你今年做的最有价值的项目,大概包含以下内容:
背景简介
研发时长
代码量
上线效果
你的突出贡献
可以看到,在这个考察里面,既有量化数字,也有定性内容。对于真实性,可以通过研发系统中的数据进行验证,对于完全一抹黑而言,结合定量和定性的综合考察,已经是照进“黑盒”的一抹光了!
4. 走暗路,进窄门
开篇我说软件难以标准化、工业化生产,实际上,所有的思维制品都是如此。所谓思维制品就是依靠我们大脑创作的东西,比如文学创作,诗歌创作,音乐创作等都是思维制品。然而,我们从未听说过文学工程,诗歌工程,音乐工程。即使现在人工智能如此发达,创造出的小说、音乐也是生硬的,缺少灵魂。因此,具有类似属性的软件创作,非要去搞工程,会注定蹉跎。
所以软件工程是一个窄门,超大型软件,需要成千上万的人共同协作。我们既需要个人英雄,也需要工程合作。虽然软件作为工程,问题多,困难多。但我们依然用这个“操蛋的软件工程”,构建了当今“软件定义一切”的新世界。吐槽软件工程,意不在贬低,而是在激励更多的人“走暗路,进窄门”,探索他,用正确的视角看待他,改进他。