黑白色的华为(8)- 从加法到减法
软件的开发模式
讲了宏观上软件的开发模式,我们再讲讲微观上的开发流程,这个在华为也是一个有趣的话题。无论多么宏伟的规划,实际的工程是一行行的代码敲出来的(当然,我们很多时候是Ctrl-C + Ctrl-V出来的)。工程实践上的偏差会毁掉所有的构想。很多时候构想是廉价的,工程实践是无价的。
如果要描述的话,在华为里写程序是一个奇妙的旅程。奇妙的地方在于:
n 看似流程严谨,实则千疮百孔。
n 千军万马写代码,仔细一看,全毕业生。
n 有些外部公司极端重要的岗位在华为没有。
但是奇妙的地方在于,虽然千疮百孔,但是华为这样子却征服了世界。存在即合理。我很难解释这背后的逻辑。虽然也和不同的人讨论过,很多人的感觉是华为是通过人拉肩扛走到这一步的,不过似乎也不尽然。从我的眼睛里看到的,华为,乃至国内的软件开发能力距离西方企业相差甚远,但是包括华为在内的国内公司却在高歌猛进,PK掉了很多我认为的研发能力远超华为的西方企业。变成了一个“你用成功证明给我看你是对的”悖论。最后变得我自己都说不清为什么了。
我不想过多的讨论上面的问题,一个可能的合理解释是,华为还没有走到真正的世界前沿,很多问题还没有真正的碰到。当一个最糟糕的老大的难度也远远大过当一个最优秀的老二的难度。类似英国UK 的事情可能就是我们在迈向老大的路上面临的洗礼开始。因此,我想我们还是需要认真的讨论一下开发模式的问题。
我喜欢从具体的事情开始来讨论问题,至少从一个程序员的眼中来解剖一下我们的开发过程。华为内部几乎对软件开发哲学有着近乎偏执的研究热情,我已经不知道听到和学习了多少种名目繁多的开发理论,方法,实践论。可能收到最多的讲座邮件就是软件工程方面的了。不过最后我倒是得出了一个有趣,但是得罪人的结论:
至少有一点是肯定的,公司传授软件开发哲学的大部分人是不真正上手写程序的,他们把事情搞复杂了。
也就是说,站在你背后背着手指导你怎么写程序,怎么开发程序的一批批软件开发哲学导师可能已经记不清程序语法长什么样了。只有专心写书的武学大师才能发明“白鹤亮翅”,“降龙十八掌”,“天龙八部”,“凌波微步”。才有了“崆峒派”,“少林帮”,“武当系”。真正上了搏击擂台,天下的功夫都简单到一两个招式了。
因为一直在一线干活。我觉得衡量软件开发体系和流程是不是完善,合理,高效可以用三个基础指标来衡量:
1. 在任何时候,从现网中随机抽取一个软件版本,还能不能找到与之对应全部的源代码。
2. 任何时候,在代码仓库中的任何一个commit,是不是都有明确的bug ID和需求ID对应(是修正一个特定bug还是完成一个feature)
3. 开发工位是不是安安静静的。
我们先谈谈指标1和指标2,再来说说指标3。1和2是软件质量的最基础的工作,没有1和2,软件质量无从谈起。而3则在一定程度上是在基本质量基础的条件下,如何能把软件质量做到更好。
低级的致命错误
先从一个实际的例子出发吧。2015年刚进公司,给的第一个任务是ARM64配套软件栈,其中有一个客户是阿里,15年底阿里的某个部门想要移植一个线上业务到ARM64,于是我们选派了一个很出色的工程师到阿里协助他们做这个事情,我印象中一共干了4个多月。前4个月和阿里的工程师一起干了一件非常伟大的事情:终于把阿里要迁移的现网业务相关部件的代码都找齐了,少量找不到的代码凑合过去,完成了这个业务程序ARM64版本的重新编译。最后花了不到两周时间完成了测试。
不要笑话阿里,我相信华为这种事情也不会少。除了找不到对应的代码了(并不是代码不在了,代码还在,但是无法找到原始的二进制对应的那个代码基线在哪里了),还有很多低级错误不也是让领导层愤怒异常么?
几乎代表中国最高IT开发水平的两大科技公司,阿里&华为,业务和代码对不上了,代码找不全了。这种让我这种外来的和尚目瞪口呆的事情后来证明不是个例,是相当普遍的现象。见微知著,从这一点上能看出来国内整体的软件研发能力和水平距离西方公司的差距有多大了。
回到前面所提到的指标1,2,其实这是一个问题的两个方向。这个问题就是:代码和业务必须有明确的对应关系,他们之间具有明确的可回溯性。
对于指标1,很大程度上是和“敌人是规模”章节中的代码的组织形式相关的。一般来说,一个release的版本从实体上表现为一个交付件,里面包含了非常多的安装件和程序体。但是在代码层面,则表现为一条git库中的波浪线。所谓是否能把现网运行的某一个版本的所有源代码找全,是指你是否在git苦衷能找到对应的那个版本线,那根软件世界最重要的线。让我们把那副图再重温一遍。
这也是为什么在上一章,我非常细致的去讲软件名称,软件版本,git库的布局这种在华为没有任何人关注的事情,但是,恰恰是解决了这三个最基本的组织形式,才能做到现网的任何release可以在代码库中做到可回溯,而可回溯是软件质量最重要的属性,没有之一。代码都找不到,找不全了,还谈质量,不是很搞笑么。
对于指标2,则是可回溯性的另外一个体现,它的目标也是非常清晰和简洁的,git库中的任何一个commit必须是有来源的。为什么要设定这个目标呢?恐怕得从我们对git这个工具体系来说起。
Git—不仅仅是代码仓库
我要单独为git写点东西。大多数人认为git只是一个代码仓库而已,和曾经公司使用的SVN没有啥区别。如果只是这个认识,基本上是对现代软件这种大协作,大分工开发的不理解。
其实大家不妨想一想?在当代软件开发中,动辄几百万行的规模,内核都超过2000万行(而且这2000万行的复杂度和交联度是一般软件难以企及的),这些工程师和开发者天南海北,互相既不不见面,也不打电话。是什么让这么多人协作完成了这么复杂的Linux的开发呢?其实魔法就是Git。
在华为大多数人的认知中,代码库就是存放代码的,或者软件=代码。这个观念显然是错误的,这点在上一章“敌人是规模”中已经有所展示。软件的本质是信息的集合体,但是信息绝对不是只有可执行程序。比如我们上一章讲到的,一个程序安装到哪个路径就是一种信息,这种信息不是代码,但是在一定程度比代码本身还重要。我们将这种信息附着在了安装包中。可这里有一个问题,软件包当然是由CI工具做出来的,那么这种路径信息平时存放在哪里呢?实际上,这种信息也必然是存放在git仓库中。因此,git本身实际上承担了软件所有数字化信息的存储工作。
因此,Git不光是一个代码仓库,更是各种信息的保存库,更是一个协作平台,还是软件版本管理工具。很多人不知道的是Git是Linus本人开发的,没错,就是Linux的0号大神,爱骂人的Linus。Linus不但为世界奉献了一个划时代的操作系统,更是用git彻底的改变了软件开发的模式和协作方式。
一个搞操作系统内核的大神亲自下场去写一个代码管理工具,这在一般国人的眼里都觉得是大材小用。这个问题很大程度上反映了中国和西方对于工程实践方面的巨大认识差异。总体上我感觉西方社会对“工具”这个层面具有非常高的认同度,没有人认为开发一个好用的工具是一个低档次的工作。他们对自动化,工具化的认同是深入骨髓的。他们会不断打磨手里的工具。一如我刚进入WindRiver的时候,要搞WRLinux,前面半年一直在调试团队,打磨产品线的感觉很类似。
如果扯的稍微远一点。我记得我在上博士的时候,有一次算法讨论课,有一个博导讲起麻省xx年的优秀博士论文是写了一个C++库,把行业内的遗传算法等一些常用算法用C++实现了出来,然后封装成了一个很好用的数学库提供给全世界用。让我印象极其深刻的是这位博导最后的一句话:就这点活竟然是麻省理工年度优秀博士论文?这就是东西方对于工具认知的差异。中国的大师们宁愿用佛学把软件工程解读成为一门玄学,也不愿意真正做一个工具来解决这个问题。
扯远了,让我们回到Git,对于我来说,面试的时候总是会问git的几个常用命令,如果非常熟悉,那么大体上这个工程师水平不会是很差,甚至他可能在github还有自己的工程项目。如果完全不了解git,大体上这个工程师的能力肯定是很局限的。
讲了这么多git的内容。要回到我们的第2个原则,既然git是软件所有信息的存储地,那么也就意味着,如果git中出现了任何的错误信息,那么,这种错误信息就一定会随着CI系统,随着构建系统发布出去,最后deliver到客户手里。因此,对于软件质量控制的第一个核心关键点就是:任何进入git的信息都需要有明确的来源,并且有相应的原因和理由。
这个基本要求很大程度上也和安全可信是强相关的。要做到系统安全,第一要素不在于加装了多少层的安全防护机制,而在于要保证系统内所有的部件有明确,可信的来源。一个系统上运行的部件都不知道从哪里来的,安全还靠谱么?
还有一个维度说明git里信息的干净程度的重要性,那就是测试,一般来说,华为的软件测试团队的工作流程是在CI从git库中取出代码构建成为系统后进行测试。通常这种测试我认为只能做到功能层面的测试,几乎不可能要求测试团队能找到系统中的大多数bug。因此整个测试团队的定位更多是验证式测试,而非是公司希望的“找到尽可能多的Bug”。事实上,一旦有问题的信息,无论是代码也好,还是其它方面的有害信息进入到git,整个软件质量基本上就很难控制了。因为git的数据随着时间的增加呈现指数增长,越来越难于找到这些问题了。所以,我一直的观点是软件质量的把控重点是信息入库前,而不是信息入库后,更不是苛责测试团队把所有问题找出来。
这两个指标基本上是软件质量最基础性的东西了,如果做不到1和2,谈何软件质量保证呢?那么对于这两种指标的把控,别的公司是怎么做的呢?是不是有很多我司梦寐以求的黑科技呢?比如存在某种神秘的代码检视系统,把所有的bug一扫而光。下面就结合WR来看看这些黑科技吧。
开发“黑科技”
WR算是硅谷很小的一个企业了,但是当我和很多来自其他西方公司的专家聊起来的时候,发现这些西方公司,无论大小,对于软件开发的流程和认知都是大同小异的。当我和他们讨论的时候,虽然有些岗位的名称不一样,但是大体的流程和职责是类似的。即使WR这样的小企业,其开发流程的顺畅程度也很不错,这很大程度体现了美国软件开发的底蕴。底蕴不是放在书橱中的经典,是实际工作中的一些简单动作。
那么就让我们解析一下WR的开发流程,看看这些公司有什么“秘而不宣”的“黑科技”和大招。下图就是WR的大体的研发流程
1. 开发团队有两个,一个是dev团队,一个是sustaining团队。一个主要负责特性开发,一个主要负责问题的修复,安全修复等。一个负责2.0,3.0,4.0等基础版本的开发。一个负责2.X,3.X,4.X等后续版本的开发。
2. 所有的开发内容需要经过tech reivew,一般分为两层。
a) 一层是特性review,比如网络的patch就发给网络的技术负责人进行review,ARM架构相关的patch就发给ARM相关的技术负责人review。
b) 通过第一层以后会发给所有工程师的大群,看看是不是会和别的部门有冲突。
c) 第一层review是必须通过才能走到第二层review,第二层review是没有人反对就通过。
3. 经过了tech review的patch会发送给一个叫gate keeper的组织进行实际的代码入库。这个过程内部叫做GK,比如一个电话打给测试:GK了,赶紧安排人测试,xx前要上线。
这就是全部的过程,没有秘密,也没有什么黑科技,和我们流程看起来没有太大差别。唯一不同的地方就是有一个gate keeper的角色。
而这个Gate Keeper的角色我认为就是整个过程中的“黑科技”和“核心竞争力”。我认为是整个风河公司最为重要的技术岗位,对于公司产品稳定开发的作用甚至要超过CTO,这个gate keeper的工作主要包含如下内容:
1. 实际操作git push这种入库动作。
2. 检查入库的代码,信息的格式是否符合要求。
3. 将入库的信息和需求单,bug单对应起来。
4. 维护clearquest中的需求,buglist等和commit之间的对应关系。
5. 维护不同分支的对应关系。
6. 维护git库中的tag信息等。
7. 检视patch对分支的影响范围。
8. 产品release的实际操作者。
9. 。。。。
简单讲,所有码农不想干,不乐意干的事情都甩给gate keeper去干。这绝对是风河公司第一苦力工种。为了缓解gate keeper的劳动强度,我们甚至专门给gate keeper配置了一个外包的RM(resource management,通常是一个细心的小姑娘)来帮助他去做一些辅助性的工作。
所以,如果你是一个码农,在风河工作的日常是怎么样的呢:
1. 你的电子邮箱中(clearquest联动的)会在每天早上收到一些问题单,或者需求单。所有的需求单都是放在clearquest系统中。
2. 从clear quest中选择一个需求单。开始工作。
3. 如果开发中出现疑问,比如无法复现问题的现象,或者需要提交者补齐相关的信息等,将疑问提交到clearquest中,打回给提交人,由提交人进行相应的补充以后再继续。如果证明是一个fake bug,关闭需求单,goto 2
4. 你依照这些需求单在自己的开发环境中进行开发。做好patch,自己进行验证。
5. 提交给第一层review进行技术review。通过了再提交给大群的列表进行审视。
6. 如果tech review不通过,goto 4
7. 如果tech review都通过了,那么就把patch提交给gate keeper。
8. Goto 2
大体上,工程师除了和代码打交道以外,无须关心太多其它的事情,所有的一切都通过电子流进行沟通和存档。和一线FAE的交流记录都是通过clearquest中的沟通系统进行保留。这样有非常明显的好处:
1. 所有的问题单,需求单都有很清晰的记录。后续如果有类似的问题,或者需要一线故障,讲一个需求单号给到他人,相关人就能很清晰的还原整个的开发过程,知道里面的关键点。
2. 工程师专注在代码,很少关心代码外的世界,做完代码提交出去以后,剩下的时候都由专业的团队来完成。
这里留一个小小的Quiz吧,结合前一章的内容,大家可以猜一猜WR的开发团队和sustaining团队各自都工作在什么git分支上。
因此,一个git,一个clearquest,两个简简单单的工具,使得整个开发流程井然有序。和其它外来的专家沟通,西方大多数软件公司的流程都基本类似,岗位也近似,只是名称有所不同。
讲完了风河的做法,那么我们回头再审视一下华为的开发过程。看看到底是什么导致了现在开发中出现的诸多问题。而风河公司的这种流程本质上是怎么解决软件质量问题的呢?
从加法到减法
现实中,华为的开发流程管理是一个做加法的过程,每当觉得某个地方可能有质量隐患,那么就加一个工具,加一个流程,加一层审计,殊不知,每多加一个流程,多加一个工具,这个流程和这个工具自身就会引入新的隐患点,而且会更多。
你把一个立方体砍掉一个角,难道就从8个角变成7个角么?不是,是多出了2个角,变成了10个角。我们的开发流程管理越来越类似砍角游戏了。正确的方式应该是从加法变成减法:
从一个工程师的角度来说,软件开发流程的核心是如何能够让工程师尽可能减少非代码开发以外的操作和时间。工程师的非代码操作时间越多,空间越大,效率越就低,就越容易出错。如果工程师每写一行代码,都需要搬出一本书的流程来一项项梳理自己的做法是否正确,把这个工程师出错的概率乘以8万,我们自己都可以想象到出错的概率有多大。
什么是非代码操作:
l 写文档。
l 维护版本分支。
l 操作git的tag
l 接听电话
l 手动做任何非代码的事务,比如关联代码的request ID。
l 。。。。
理论上一个完美的工程师工作模式是按照电子流接受任务以后,完成代码和在自己代码分支上的测试,提交给review。剩下的事情都不应该是码农来干预,每多一次干预,整个系统就多一份出错的概率。当码农的群体规模达到一定程度以后,系统就会逐渐失控。
有人可能会反驳说写文档应该是工程师的事情。我的观点是:
1. 代码文档基本没有意义,除了少量提纲挈领的代码注释以外,再多的注释也无法让受众理解代码逻辑。
2. 用户文档,手册,白皮书是一门学问,不是工程师能写出来的。码农是写不出优美的文档的,这个也需要专业的人事做专业的事情。码农连PPT都写不囫囵,还能指望他们写啥呢?
难道写文档也是一门学问了?我坚定的认为这是一门学问。我们固然需要爱因斯坦发明相对论。但是我们更需要一群高手写出教科书让本科生能理解相对论,难道让一般人去读爱因斯坦的论文么。
对于从加法到减法的转变,我举一个在WindRiver的例子来说明开发流程的优化。风河的开发流程也不是一夜之间梳理清楚的,也是经过一些坑以后逐步完善起来的。在很久以前,风河的工程师是可以直接操作git库的,或者说是在gate keeper的弱监督下操作git库。直到有一天:
一个平时大家就认为头脑不是那么清楚的工程师,解完一个bug,把代码checkin到代码库的过程中需要写comment,在comment中,这个可怜的兄弟把这个bug中附带的相关客户信息也一并写到了comment中。这个patch一入库,系统自动触发编译,构建,补丁发布等一系列动作,当然,照例,测试也没有发现这个细小的问题。结果导致comment中的信息随着patch的发布也发布给了全世界。还有什么比带着客户信息的bug fix的patch修正发布给全世界更糟糕的事情么?
这个可怜的工程师不幸是我部门的。我后来调整了整个部门的流程,所有的入库信息,哪怕是comment都订好了模板,同时入库的权利全都收归到gate keeper的手中,同时还专门找个一个rm(WR叫做resource management的角色),辅助他去做这些事情,相当于两道保险。所有的工程师再也不允许直接和git库打交道。自那以后,再也没有出过这种问题。
这就是一种减法:
1. 把码农手中的权利收缩的越小,整个系统出错的概率越低。
2. 把容易出错的地方的接触面,接触人数量收缩的越小,整个系统出错的概率越低。
也许有人会关心这个可怜的工程师的命运,还好,我没有为难那个倒霉蛋,事发以后他还在我的那个部门,唯一的变化是我把他调到我能看见他的位子上了。
我认为,如果制定一个规则,很多工程师都做不到的话,这不是工程师的问题,是规则本身的问题。没办法要求所有工程师永远不手滑。
工具和流程陷阱
除了入库收口以外,在WR的流程中,还有一个非常重要的信息是开发信息也是一种重要的资源,也需要持续的数字化,可查询化,简便化。而这个的标志就是衡量指标3,开发工位是不是安安静静的。
无论做硬件还是做软件,华为的各个开发工位都是人声鼎沸,嘈杂异常,和菜市场的感觉差不多,除了拉通对齐端到端以外,我们开发过程和开发流程中工程师依然要不断借助电话这一原始的工具来进行交流和沟通。但不幸的是,电话完全不具备信息保留的功能。开发过程中,每多打一个电话,那么就意味着开发过程中的一份信息丢失了。意味着某些信息就留存到了某些人的脑袋里,而不是数字化了。
在WindRiver的时候,我也吐槽过当时公司的开发软件,不好用。但是现在回想起来,当时整个开发团队安安静静,我很多时候一天一句话都不讲,即使工程师离我一步之遥。所有的过程也是在屏幕上完成的。大家都对着屏幕工作,无须通过任何其它的手段进行沟通是开发有序化,数字化,可视化的验收标准。
而这一切的目标,都是在保障除了代码可回溯性以外,还要尽最大努力做到开发过程和动作的可回溯性。
我也说不清楚我们的研发工具体系到底出了什么问题。我曾经尝试过用我们的系统提交过代码,只记得那是一段无比艰难的旅程。后续的开发都转移到了codeclub上。
如果我过分抱怨我们的研发工具体系也并不合适,毕竟华为在这种体系的支撑下依然占领了世界。但是至少有如下的三个方面的原则我认为是需要重视的:
1. 研发工具的设计目标是围绕可回溯行进行设计。
2. 研发工具对工程师来说,不是越多越好,而是越少越好。
3. 工具和工具之间的衔接不能有手动操作,哪怕只需要程序员按一个按钮,那么他也一定会按错。
一个工程师如果在使用研发工具中即使拥有0.0001%的5个9的高可靠性不出错,乘以8万的研发人员也是8%的错误率。
一个工程师如果一年只出一次错,一个60人的工程团队就会每周都出错(一年才52周)。但是把某个容易犯错的步骤收口到一个工程师,那么一年出错的概率就只剩下一次了。
毕竟,我们面临的下面的一种状况
公司的研发工具体系支撑了公司走向了今天的辉煌,它适应的也许是硬件开发的时代和特点,但是对程序员来说并不友好。这个大课题还是留给公司相关的专业部门来解决吧。
说道开发,就不得不提一下在国内总是讲西方的一个词语“底蕴”。拿我们就来讲讲软件开发的底蕴吧。
软件开发的底蕴
这是一个很抽象的概念,但实际上又非常具体,我们总是很羡慕西方顶级公司不断能做出高质量的创新的软件。很多时候讨论的结果是有“软件开发的底蕴”。但是这个所谓的底蕴到底是什么呢?
首先,我认同这些创造,这些伟大的软件产品是来源于西方公司深厚的软件开发底蕴。但是,我并不认为这个底蕴具有任何的神秘感,是西方公司有什么魔法的流程,魔法的工具,魔法的设计。
WindRiver算是一个很有趣的例子,它是西方老牌传统的软件公司,规模也不大,但所谓麻雀虽小,五脏俱全。从我上面所展现的WindRiver的整个流程和工具体系,绝对看不出任何所谓的“秘密武器”,华为完全不缺乏这些东西。差的是:
1. 同样的工具体系,流程规划和设计的合理性。
2. 工具的精细程度,易用程度。
3. 开发群体中大多数人的遵从度。
4. 对软件工程化认知的理解。
第1,2两个因素我认为容易赶上,只要弄清楚,加上有耐性,总还是有一天能建立起来的。难的是第3点和第4点。
对于第3点,当一个群体中的大多数人对相关的工具,流程,体系具有普遍一致的遵从度以后,这就是底蕴,后面进入的人就会很顺利的融入这个体系中。
对于第4点。以工具为例,如果从博导,到公司CEO,到部门经理,到team leade都不认为做出一个非常好用的工具是一个伟大创举的时候,你如何能创造出一个伟大的改变世界开发模式的工具呢?没有一个实际好用的工具作为载体。那么多圣经般的开发哲学除了供奉在殿堂之上,还有什么意义呢?
从学校到公司,我整体上感觉国内将软件专业变成了一门“科学”,但我认为软件专业整体上是一门“工程学”而非“科学”。以现在大火的AI为例,AI中的算法是数学家的范畴,是“科学”,码农的专业是将这些“科学”用工程的方式翻译成一个个实用,好用的软件实体。发明这些AI算法不是码农的职责范围(数学好谁还做码农呢?),但是同样是翻译,google的tensorflow的翻译能成为世界AI软件的“范本”,这就是工程学的杰作。这种软件的工程思维和华为把软件想象成为一种“神秘科学”,要求各级软件工程师写出别人写不出来的“黑科技代码”完全不同。
所谓底蕴,对于软件开发,好像也不外乎这些了把。
总结一下
最后总结一下,我相信这个总结应该是所有章节中最容易的了。
软件质量应该围绕一个核心,三个基础衡量指标展开。
一个核心是:软件质量的核心是可回溯性,所有软件质量的动作都是围绕可回溯性展开,保证可回溯性。
三个指标是:
1. 现网业务和源代码的完整回溯性。
2. 源码库中的代码和需求输入的完整可回溯性。
3. 开发过程中产生的信息的完整可回溯行。
具体实施中,应该围绕Git这个全球统一的开发协作平台来设计开发流程,所有的质量工具的开发应该最终是以Git为核心来进行设计。
软件开发的核心是:如何能够让工程师尽可能减少非代码开发以外的操作和时间
工程师和开发工具的关系是:工具越少越好,接触面越小越好,尽最大努力杜绝手动操作。
逐步建立工具化的文化认知,西方成熟的软件开发底蕴很大程度上体现为工具文化,以及构建在工具之上的流程遵从文化。
但是。无论是什么样的底蕴,但是无论多么好的流程,工具,认知,具体的执行者还是工程师。没有一个优秀的工程师群体,再好的工具,再好的流程,再漂亮的PPT也无法达成最后的工程目标。我们下面就来谈谈工程师吧:码农的世界
本文来自博客园,作者:易先讯,转载请注明原文链接:https://www.cnblogs.com/gongxianjin/p/15703752.html