我们印象中的面包机是这个样子的:
“烤面包机属于加热电器。其功能是在面包片附近生成足够的热量,以便对面包进行烘烤”
原理非常简单,有个开关控制通电,通过电热来加热。但是,如果我们要亲手制作一个面包机,需要花费多久呢?
话说,英国有个叫Thomas Thwaites 的艺术家在几年前,花9个月时间做了一个面包机。
嗯,没错,9个月……
如果依靠现代社会的完善体系,这件事情是很简单的。之所以耗时这么久,是因为他一切都是从头开始制作!
我们看看他到底是怎么完成的。
首先,他拆了一个买来的面包机,看看都包括哪些零件,预估了一下工作量,嗯……
大概400种零件,100种不同的材料:
看起来工程会很庞大……
但是聪明的 Thomas 经过一系列研究、简化和删减,把材料和零件大大缩减,看起来是一个可以完成的任务了。这是简化后的材料列表:
铜: 用来做插头和电线
钢: 用来做弹簧和烤架
镍: 用来做加热系统
云母和塑料: 用来做外壳
有了计划和方案,Thomas开始兴致勃勃地制作。
首先 Thomas 托人从一家朋友的铁矿,捎回了一箱铁矿石:
去博物馆找到了冶金学教科书:
有了理论,有了物料,集中起来!
Thomas 用吹风机和垃圾桶搭建了一个炼铁炉:
然后 Thomas 用这个炼铁炉炼出了一堆炉渣……
Thomas 的炼铁计划失败了。
幸运的是,Thomas 找到了另外一个专利——用微波炉加热并融化铁矿石!
经过30分钟的微波轰炸,Thomas 终于融化了铁矿石并且用融化的铁做出了面包机的框架。
接着,Thomas 从工厂搞来3大桶工业废水,将其中溶解的铜离子置换出来,变成铜:
做了3个插头:
最后需要准备的是制作面包机外壳用的塑料,然而 Thomas 打了30分钟电话,也没能成功说服油井工人帮他提一壶石油回来……
从石油DIY塑料的计划失败了。
但锲而不舍的 Thomas 又找到了一个专利——从土豆中提取塑料:
“一种马铃薯淀粉基可降解塑料薄膜的制备方法
Abstract
本发明公开了一种马铃薯淀粉基可降解塑料薄膜的制备方法。包括以下步骤:将60‑80份马铃薯淀粉、300‑400份去离子水混合成淀粉水溶液,在85‑90℃糊化;”
几天后,Thomas 再去看他放在室外风干的淀粉塑料时发现,塑料,已经快被蜗牛吃光了……
绝望至极的 Thomas 只好再寻他法。他去了一个废物回收站,拉回一箱废料。经过打碎、融化、铸模,最后终于得到了一个面包机的外壳:
至此基本上凑齐了所有的材料和零件,Thomas 开始正式组装面包机!
又经过几天紧张忙碌,最后成品大概是这个样子:
没有塑料外壳时,面包机里面的结构大概是这个样子:
接下来就是令人兴奋的试用了!
虽然没有开关…… 但能通电工作就可以了!
虽然面包机并不绝缘…… 但只要注意安全就可以了!
就这样, 在第一次通电后,大约过了5秒钟,面包机就融化了……
是的,融化了……
但是Thomas觉得这个项目,非常成功!!!并且为这个项目专门写了一本书讲述面包机的制作过程: The Toaster Project
即使是面包机这样看似简单的物件,其制作过程也是十分不易。在这个过程中 Thomas用到的所有东西如下:
这里还不包括被蜗牛吃掉的塑料……
不包括使用了现代的锄头挖铁……
不包括借用了现代的微波炉炼铁……
之所以讲这个故事,是因为作为一个软件工程师,我觉得,它跟我们每天的工作太像了。
面包机 | 明确要实现的产品 |
把面包机拆成400个零件 | 分析已有产品,了解详尽的细节/架构 |
裁减功能到5种材料 | 制定自己的开发计划,并按照发布要求删减目标功能 |
垃圾桶炼钢炉 | 着手开发,发现预先设计的方案无法实施 |
油井不让拿走一桶石油 | 在开发过程中难免遇到无法逾越的困难,临时切换方案 |
用微波炉融化铁矿石 | 在寻找解决方案时,突然找到好用的工具 |
没有开关 | 几经周折,开发出一个1.0版本的面包机,丑且功能不完善 |
不绝缘 | 几乎无法作为可靠产品来使用, 但总归是一个能工作的产品 |
5秒融化 | 第一次使用就挂了 |
这样看来,软件开发工作挺不靠谱是不是?
但实际上,大多数时候就是这样:
- 90%的研发项目都在走这个流程
- 90%的项目以失败告终
- 90%的代码生存时间不超过3年
然而,问题并不在于执行这个工作的人。
从Thomas 的实施过程可以看出,他是个聪明的小伙子,翻阅资料、想各种办法,但仍然耗费了长达9个月时间,还只是做出了这么一个几乎是废品的产品。
为什么一个非常出色的工程师有时也无法做出好产品?
这是上述故事里一个苛刻前提决定的——“从零开始”。
在面包机制作中,从零开始意味着Thomas无法借助整个人类社会构建的科技/工具体系来支持自己的工作(让我们暂时先忘了Thomas有点作弊性质地使用了微波炉炼铁),所有事情都必须由他自己完成。
如果抛开“从零开始”这个前提,那么,各种工具和组件立刻会改变Thomas的状况:标准化的螺丝、质量可靠的导线、3D打印机或塑料模具、钳子扳子……
这一系列的工具如果可以被Thomas使用,让可靠的零件有了保证、零件之间的接口标准化对接有了保证,即使是没有太多制作面包机经验的人,产出一个像样的面包机,也不再是一件难事,因为组装面包机的每个零件,都是高质量高可靠的,制作者的精力会集中在如何组装这些零件,而不是耗费在考虑每个零件是否正常。
回到我们日常的研发工作中,聪明的工程师无法做出高质量产品,原因是他必须依赖一个完善的工具体系。(可能叫做工程体系更全面一点,但我在这里不打算把话题扩展的太大,今天只讨论其中最核心的工具)。
软件工程就像人类社会一样, 绝大多数人的工作不是制作“面包机”这种最终产品,而是提供零件和支持:一个螺丝的国际标准化规格,粗细、硬度、螺纹数量和间距等,或炼钢厂产出的优质钢丝……
有这些可靠的支持, 一个产品的生产者才能做出优质产品。
如果每个产品负责人亲自准备这些基础工具和材料,恐怕无法避免的需要涉猎几十个甚至上百个自己完全不擅长的领域。以有限的精力挑战数十个领域,难免做出残次品零件。零件质量无法保证,最终产品质量也无从谈起。
而研发体系建设也像面包机项目一样,它的成功与否取决于是否能让一个工程师把精力集中在对业务核心的思考上。也就是说,取决于这个工程师背后是否有一个支撑他的完善工具体系。
现在我们就需要这样一个工具体系。
要想在竞争中胜出,就需要站在最高巨人的肩膀上,再上一步。
社区中已有的开源软件和市场上可购买的商用软件,都是很好的借力点,这是第一级台阶。
它们可以帮我们快速达到一个高度,但它们也是落后的,因为软件行业发展、更迭速度太快,每个人都在改进已有的东西以超越对手。
可以拿来就用的工具,给产品的平庸埋下了伏笔;
在已有工具(开源或商用软件)上做更多改进给产品的卓越增添了筹码。
在市场竞争中,我们不能等别人做好工具给我们用。所有人都能获取的东西,只是让大家一起提升平庸的水平线而已。
我们必须自己来构建超越现存软件的工具体系,这是第二阶台阶。
依靠自己和同伴,构建我们自己的工具体系,它会是很多个完善的细节积累的成果,足够稳定和超前,那它就是那个更高的肩膀,我们可以在这个肩膀上伸手去触摸更高的位置。
就像制作面包机一样,再聪明的人,也无法在没有支撑系统的情况下一下子制造出漂亮的面包机。 在这里,工具体系显得比个人智慧更加重要。
IT不同于传统业,信息的复制、经验的复制等,都不需要额外的有形成本,它的每个成果都可以“零成本”传递给其他人。所以我们有什么理由不尽最大努力促成和发挥出这种优势呢?
好的公司应该是能为一群有着共同目标的人提供一个高温环境,把每个人的智力融化成岩浆, 汇集到一起,再凝固成更高更大的山峰。
在技术研发方面,我们能为其他人做的,就是把我们的经验和思路,标准化成各种各样的工具、 零件,构成一个整体,就像Thomas 拿到的可靠零件一样,让其他人在这个平台上跑得更快、跑得更稳。
简单讲,公司的自我发展应该是小金字塔到大金字塔的演变,从最初几个工具支持一个产品,演变成所有工具支持所有产品。
如上图所示,从3个产品各自独立维护3个它们所需的工具(有重复),到5个工具共同支持3个产品,需要花费的精力从9个单位变成5个单位,从某种意义上来说,效率就从5个单位提升到9个单位。
互相支持就是为其他人提供可以用的东西,而且这个东西必须是可靠的。
就像一个精确符合标准的螺丝钉,可以让再次使用它的人免除后顾之忧——耦合紧密,无需担心松动脱落。这些”无需担心” 就是效率的大大提升,因为使用它的人可以把自己的时间投入到更有价值的地方。
但复用的前提是质量,高质量零件的复用促成效率的提升,而低质量的复用只能带来故障率的提升。
一个不能保证质量的环境是在制造“天使”,努力的“天使”们每天做的事情就是往地球上添加垃圾。这也就是为什么质量是体系化研发的基础,否则就是在努力燃烧生命去生产垃圾,浪费员工的生命,浪费公司发展的良机。质量和效率是因果关系,有了前者,后者便是一个无需追求的直接结果。
受早期互联网产品的影响(一类通常通过客服来弥补质量问题的产业),质量在行业里不太受关注,因为质量产生的影响需要几个月或一两年才显现出来。一般来说,短期质量下滑带来的问题都可以通过运营/客服来弥补,因为疗效快,短期收益越来越被重视。但长期收益被忽视,慢慢的运营/客服比重越来越大,直到增加100%运营/客服的投入却只能换来10%收益增长时,对质量的重视意识开始觉醒。
保证质量首先要了解质量。
质量是一个不太容易度量的东西,因为包含的方面太多,即使其他1000个细节做的都很好,一个细节的疏漏往往就可以毁掉一个产品。
早期产品只要有几个突出的亮点就够了。但随着产品的成熟,包括的环节越来越多、越来越完整,每个细节都变的非常重要,最短板的位置开始决定这个产品的质量。
如果要发现软件质量的问题,短期内没有非常好的方法,但长期可以用比较简单的方法量化出来—— 关注2个概念,代码的增长率和丢弃率:
- 增长率是一段时间内代码行数增加的百分比, 一般是业务增长造成代码量的增加
- 丢弃率是一段时间内代码被删掉的百分比, 一般是修复问题而造成问题代码的丢弃
如果增长率比较高而丢弃率比较低,那么这个产品的质量是比较好的,因为没有太多的重复劳动, 大部分精力都花在了创造新的东西上;如果丢弃率比较高,说明在研发过程中有大量修改,造成了重复开发,而重复开发代表发现问题后的修正行为,这时就需要深入研究下为什么最初产生了问题。
拿nginx举例,它现在已经是非常稳定的一个软件,13年内代码增长率 201%,丢弃率 48%:
- 13年前到5年前,代码增长率129%,丢弃率39%
- 最近5年内,代码增长率31%,丢弃率 11%.
- 最近1年内,代码增长率4%,丢弃率仅为1%
可以看出,最初是大规模的开发,也发现了不少问题(丢弃率39%),最近一段时间有些小的修补,产品总体非常稳定。
如何评判一个产品是否稳定可靠呢?应该符合这样的标准:
- 年丢弃率在 10% 以内
- 年增长率高于丢弃率,例如10倍左右
短期来看,如果增长率是丢弃率的10倍左右就非常健康了。
这里说的短期,也不是指非常短,至少要包括一个反馈周期,也就是能检测出产品问题的一个时间周期,可以是测试/review的周期,也可以是POC试用/反馈/调试的周期。
这里的2个参数是检测方法,不能作为KPI或其他考核标准,否则就完全变了味道
于是,改进产品质量的方法也变得很直接。
Review下被删掉的代码都是什么、为什么删掉、当时的考虑哪里不全、漏掉了什么导致要修改。
长期行动,建立工具体系—— 基础代码库。
一般业务相关的代码会有非常剧烈的变化,这部分代码在最上层,对质量的影响不大,而它依赖的下层代码,对质量起着非常重要的作用。
拿我自己经历的一个项目举例:
- 2010年至今的代码中,有58% 已经被丢弃,那个时候刚刚上线,经历了一波快糙猛的迭代
- 2010年的一年里,44%增加 ,13% 丢弃
- 2011年的一年里,28%增加,16% 丢弃
- 最后一段时间的开发, 情况好很多,一年里,40%的增长,只有9%的代码被丢弃
这里有很大一部分是业务变化带来的修改,而频繁修改对保证质量是有阻碍的。因此基于产品对质量的依赖,后来开始将一部分基础工具独立于业务项目之外。这有2个目的:
- 独立测试方便,容易保证质量
- 方便共享
在日常提高产品质量的行为中,我会按照以下顺序去做,但当时间不够,必须做选择时,可以从左边最重要的方面开始:
代码可读性 > review > 文档 > 测试
以上优先级是根据长期收益来评估的,短期测试最有效。长期来说,可读性让一个工具的复用率更高,而每次复用就是一次效率的提升。
可能会有人有异议,例如对于测试的重要性排在最后一个。有TDD,也有反TDD,不展开了, 个人理解上:
- 对测试的依赖是最容易生产“没人敢动”的代码的方式
- 出色的可读性则是生产“人人都能修改”的代码的方式
毕竟测试是用来检查低级(已知)错误的。
巨人的肩膀就是我们自己的肩膀,也只能是我们自己的肩膀。
让自己的肩膀越来越高,越来越稳,为其他人提供一个坚实高大的肩膀, 是每个人的责任。
让每个人可以看到并抓到同伴的肩膀,登上下一个更高的位置, 是公司的责任。
希望每个工程师,都能制造出一个漂亮的面包机。
作者简介:
张炎泼(XP Zhang)
白山合伙人兼研发副总裁。
张炎泼先生主要负责白山云存储产品CWN-X的研发及技术团队管理工作。带领团队完成全网分布存储系统的设计与部署工作,将数据冷热分离,在Erasure Code方面实现技术突破。
张炎泼在2006年至2015年,就职于新浪,负责Cross-IDC PB级云存储服务的架构设计、协作流程制定、代码规范和实施标准制定及大部分功能实现等工作,支持新浪微博、微盘、视频、SAE、音乐、软件下载等新浪内部存储等业务;2015年至2016年,担任美团高级技术专家,设计了跨机房的百PB对象存储解决方案,设计和实现高并发和高可靠的多副本复制策略,优化Erasure Code降低90%IO开销。
张炎泼已申请9项国内发明专利,5项PCT国际专利。