其他
工程师分享:战斗在0与1的世界,将代码写到极致
我与代码结缘要从游戏说起。大学时代,大多数男孩都有一颗爱打游戏的心。当看着室友们飞速地敲打着键盘和鼠标、显示器上呈现出各种炫酷的画面时,那一刻,我真的非常好奇:软件真是个神奇的好东西!
往后三个月,我一直都致力于编出一款赛车小游戏,那时才第一次发现:软件真的有非常强大的创造性。那一个个字母组合在一起成为映入眼帘的左/右拐、加速/刹车,仿佛是在盖一座房子,从设计到施工,一砖一瓦地构造自己的想象。后来,我开始关注2D/3D游戏,开启了“各种搜”模式:游戏类库、引擎代码、各种社区/论坛中“摸爬滚打”,学习并开始PK。做游戏,让我对软件的热爱不断升级。在大学毕业论文答辩时,因为编程,我的成绩成功晋级全校前十,那种喜悦和激动难以言表。
来华为前,我在一家全球性的软件设计与咨询企业工作,这里工程师文化浓厚,追求极限编程,敏捷理念、开源思维、Tough精神、极客追求、Idea变现……使我对软件的认识更加深入,能力不断提升,而这些后来一直贯穿在我的职场生涯中。工作9年后,2016年底,我来到华为西安研究所。
软件开发人员都知道重构的意义,当一个系统修改代码成本太高的时候,就不得不面临重构。
初到华为,我感受到一种明显不同的氛围。在华为,更加注重按照既定的计划完成交付、使命必达,遵循计划大于响应变化,“如何将代码写到极致”的问题似乎碰撞不多。
对于一个代码发烧友,我的技术洁癖的劲头又上来了。我发现所在项目的软件架构版本、语言版本都很老,由于没有测试框架保护,新功能经常会引入问题,重构更是无从下手;即使修改一行代码也需要全量编译,每次编译时间高达5 分钟;无法本地调试,由于环境代码是编译过的,所以也无法远程调试,调试环境是公用的,使用需要排队,有时为了验证特性需要等很久。那时,我就在想:“如果能解决这些问题,那代码开发调试和自验证的效率都会大幅提升,也会节省很多开发环境。”
为了让项目组更加信任自己的想法,我决定先完成新的代码框架开发。每天下班后都会投入其中,两个月后,我终于有了向大家“Show Case”(效果演示)的勇气和实力。这个大胆的尝试得到了整个项目组的认可。在一个月后的新项目中,它迎来了真正的战场。
那天项目主管找到我:“嗣健,这次新项目,你敢不敢用新的框架彻底替换老的React 框架?”——这个问题,令人惊喜,同时又极具挑战!
我问同组的兄弟们:“敢不敢?”
“你敢,我们就敢!”——这种信任,令人惊喜,同时又力量倍增!
于是,说干就干!当然,成功的路哪能一帆风顺。就在完成替换的第一个月里,各种安全问题、历史埋藏的大坑小坑一个个都蹦了出来。在那一个月里,在压力中我们憋着一股劲儿,尽管有一些质疑声,但我们依然坚信:问题必然会收敛!令我们意外的是,这个收敛竟来得如此之快——在完成替换的第二个月,整个系统逐渐趋于稳定。
在后续的日子里,项目组的兄弟姐妹们在自己的桌面云上就可以开发调试,从曾经的“先前端再后端”到现在的“前后端并行开发”,从曾经的“测试一个场景重出一个版本”到现在的“只需替换一个组件就是一个场景”,这也为本地模拟更复杂的测试场景带来了可能。代码重构中,对数据库差异层和通用逻辑层进行分层解耦,精简多数据库场景下生成动态SQL(Structured Query Language,结构化查询语言)的业务代码,重构后的代码量从96K下降到37K,大大降低了代码缺陷率及维护成本。
也许,一个勇敢的小改变,真的可以带来明显的质量提升及效率提升。
某天,团队的一次代码检视会议上。
“小张,你提交的上帝类(被多个特性所引用的类)代码不符合公司的编码规范,竟然有1000行!这必须得重构呀。” 团队主管说。
小张辩解道:“这个类是老代码,又不是我写的;况且之前也没有评估这个工作量,我估计这个迭代版本重构来不及。”
“小张,对于修改的类要有责任人;如果时间不允许的话,我们有专门的重构管道,这个迭代做不完可以排到下个迭代来完成,先给你提个问题单,跟踪起来。好,这个类有哪些Bad Smell,大家一起来说说。”团队主管启发大家。
过大的方法、基本类型偏执、发散式修改、无效的注释……大家你一言,我一语。
在实践中,我们总结出了提升检视效率的三个步骤:第一,Show Case,你做了什么;第二,讲理念,怎么设计;第三,看小步提交代码,从逻辑、风格、规范等方面全方位去找问题。
三步法逐渐得到固化,我们的检视从原先的一个小时缩减到了半个小时。在接下
来的检视中,你会发现那些平日里沉默腼腆的同事在这里成了主角。
某天,我的徒弟小顾组织代码检视会议。
“小顾,这次的功能写得很简洁哈,再也不像你刚入职时的Ctrl+C(拷贝)、Ctrl+V(粘贴)啦!”
小顾不好意思地说:“客户提出,某些功能上华为的代码量太庞大了。作为研发人员,功能实现是一方面,代码本身的质量也非常重要,多想一步,代码其实可以写得更好。”
“小顾,你的代码测试用例还是自动生成的吗?可不要只为覆盖率啊……哈哈哈……”大家笑了起来。
“当然不是自动生成的,那可都是我一行一行码出来的。我们先来检视测试用例,之前项目组的防护理念测试专项赋能中,我可是每场都记满了笔记啊。来,大家一起来看看……”小顾说。
为了快速达成代码的高覆盖率测试,人们却往往不自觉地加速了测试代码的腐化。我们也被测试覆盖率困扰了很久,一直在覆盖率与高质量测试之间纠结……
那天李哥问我:“我们的测试覆盖率那么高,为什么问题单数降不下来?”
“我们的测试用例大部分是自动生成的,没有真正从业务逻辑出发,所以这些测试都是无效测试。要想改变现状,就必须让大家写出真正有效的测试,一方面需要给大家赋能、如何写出高质量测试,另一方面我们要摒弃任务式追求覆盖率的习惯。”我答。
李哥认可了我的观点。那天,我们聊了很久,具体讨论几个项目团队的现状、分阶段实施的操作细节,以及由此带来的成本投入及风险应对。一周后,各个团队就开始行动起来,踏踏实实地落实有效测试。
这些是我们代码检视过程中经常发生的情形。在团队中代码是集体所有制,当你在修改其他人代码的时候,那你就成了它最新的主人,慢慢地就形成了代码主人翁意识。我们约定:代码检视会上没有领导、没有权威,大家摆开阵势后,有的就是畅所欲言、激烈PK,工程师文化也逐渐浓郁起来。
在激烈的检视对阵辩论时,我们还会采用好用、适用而且强有力的“武器”,那就是:“编码规范”“集体检视”“代码坏味道”。
“编码规范”,就如同开车上路时要遵守交通法规,红灯停、绿灯行,违规就要被严罚。在公司级编码规范基础上,我们部门也推出了自己的编码指南,这就好比在到达目的地的路上提供了导航,能够避免司机少走弯路。
而“集体检视”就如同全员都是交通警察。再好的规范都需要有人监督执行,它能互相监督、信息共享,当司机出现违反交通法规的行为时,他能够第一时间被其他司机提醒,及时改正错误驾驶动作。发现、提醒问题最多的那个人很快就成为团队的法规领袖。
“代码坏味道”,顾名思义,比如说当食物快要腐败时,往往会散发出一些难闻的味道,通过辨别,我们可以针对不同的坏味道做出相应的措施。代码的道理也一样,如果一段代码不稳定或者有一些潜在问题,那么代码往往会包含一些明显的痕迹。我们会通过识别代码中的坏味道来精确实施重构,从而避免代码的持续腐化。
通过采用业界优秀实践方法和实战磨砺,大家逐渐明白了什么是高质量的代码,什么是需要坚持的,什么是需要摒弃的。在这个过程中,大家的能力潜移默化地得到了提升,每个人的知识库也不断丰满,就像小顾,现在他既是Web 前端的一把好手,同时也是大家公认的DBA(Database Administrator,数据库管理员)专家。
也许你不难发现,大多数的软件开发工程师都像金庸小说里的高手,低调、话不多却身怀绝技,他们的战场在自己手里的0与1世界中,在“你的问题不闭环就休想提交”的“执拗”中。在我看来,写好代码就是在争论与吵架中,让每个人的思维得到碰撞,让问题得到最完满的解决,它不需要东方美女式的一致标准,只需制定出真正适合团队的一套运作共识。
可信,它不是一蹴而就的事,更不是一个人就可以扭转乾坤的斯诺克。就像一波浪潮,它需要万千水分子共同发力。各类可信工作开始运作后,组织的支持就变得格外重要了。
为了让可信有效落地,部门预留了10%~20%的可用于重构的工作量。作为架构师,我双周会组织一次例会,大家将近期问题抛出来,识别出其中的共性问题;同时,软件总工程师也会例行获取团队的问题,当然也包含一些好的创意点子。这些问题或点子经过评审后,大部分任务会在部门季度审视中落入管道,而小部分任务也会转入“极客连”进行闭环。我们会将工作量进行分解,这样一个任务通常一周投入3个人就可以实现,而参与者则可能获得“极客装备”的奖励,在后续的评优考核中优先考虑。而为了进一步有效减少共性问题,我们还建立了部门CBB(公共组件),通过开源运作,带领我们模块架构师组的成员孵化出5个CBB,目前均已经投入使用并取得了不错的效果。
经过持续的实践积累与反复迭代,我们的交付结果及人员能力都得到了较明显提升,支撑多个下游产品达成商用挑战目标,并获得了公共开发部的金质奖。我们把在可信落地的一些实际做法进行了总结,由我贡献思想、部门HR 刘姐协助结构化,《可信落地的具体实践探索》一书正式出炉,其中的方法和案例也很快在多个团队展开推广与学习,帮助更多的团队提升可信落地效果,也受邀在深圳、西安等多个部门进行过分享。
有小伙伴问我:“如何提升自己的软件技能?”
我想说的是,要想发挥编码人员的最大潜能,个人努力最重要,但还需要成长的土壤:
第一,信任是对一个人最大的激励,一句“相信你!”胜过许多华而不实的赞许,而它也是一个组织的基础,与其防着他做,不如放手让他做。不要惧怕未知的风险,不要担心挑战的艰巨,坚持不懈、聚沙成塔。
第二,每个人都是平等的,每个人都可以充分发表自己的观点,不要在团队中刻意树立技术权威,过于相信权威对团队、对个人来说都会是有弊无利的。
不知你是否听过“飞轮效应”——为了使静止的飞轮转动起来,一开始我们必须使很大的力气,一圈一圈反复地推,每转一圈都很费力,但是每一圈的努力都不会白费,飞轮会转动得越来越快。当达到一个很高的速度后,飞轮所具有的动量和动能就会很大。
人总是习惯于惯性而不是主动改变,可信变革正处于飞轮效应的启动阶段,我们会遇到很多的困难,需要我们聚集合力,用很大的力量才能让它飞速运转起来。努力是会被看到的,付出是会被感受到的。放手去干,我们终将看到不一样的改变。
-END-
推荐阅读
【01】世纪性大问题:C 语言会比 C++ 快吗?【02】乔布斯的简历120万被拍卖,HR 看了想打人……【03】编程,它到底难在哪里?【04】操作系统生态战争【05】Linux C/C++定时器的实现原理和使用方法