钢厂小伙在菊厂,能炼出怎样的火花?
史恭标
2021年7月,我走出校门,走进华为南京研究所的大门,成为了一名华为人。
我硕士学的是控制工程专业,主攻模式识别。简单点说,就是利用各式的“相机”(如光学相机、激光雷达等)与电脑软件算法代替人眼去自动观察、识别观测对象。其间,我跟着导师“上山下厂”,忙得不亦乐乎。在与某钢厂的合作项目中,我在学校忙碌了大半年,又驻守现场呆了小半年,带着安全帽和现场工人们同吃同住同干,成功搞定了废钢装卸自动化的大项目。我们利用设计出的软件与算法,通过高精相机和激光雷达传送的实时数据,精准识别废钢位置,指挥行车前后移动、定点抓取和装车,从而实现无人化、自动化废钢装卸。正是有了这次软件工程的实战经验,在参加华为软件岗的校招时,我才顺利通过笔试和面试,拿到了offer。
报到后,我正式加入“华为乾坤”设备生命周期管理团队。来到部门,我才知道,华为乾坤是一款面向行业客户的网络产品,可以为客户提供安全可靠的云服务能力。我所在的团队负责开发设备的管理平台,通过该平台可以让客户在云上便捷、快速地管理本地网络设备。
入职后,在组内一众大佬的带领下,我开始学习相关的基础知识。急性子的我并不满足于每天枯燥的练习,在我苦苦央求下,我拿到了工作生涯中第一个需求:支持不同客户,配置相应的操作权限。
“权限配置?这也不难啊!” 不等师父交代细节,我就急吼吼地直接上手撸起代码,短短三天就洋洋洒洒写出了两千多行代码。我信心满满地按下“commit”(确认)按钮,把代码提交给SE(系统工程师)常建强。
“强哥,我需求写好了,你帮忙看一下!”我走到强哥身边兴奋地说道。强哥一惊:“小伙子很不错嘛,速度很快呀!”他笑着打开我的代码,我则站在一旁,静待他下一波的夸奖。看了没两分钟,强哥脸上的笑容开始凝固,眉头越来越紧:“哎呀,你这个代码很学院派啊,一下子还有点看不懂咯!”我嘿嘿一笑,心想:“我写的代码,哪是这么容易就被你看懂的!”强哥挥挥手让我先回去,低头继续研究起来。
第二天一早,我在办公室迎面见到了强哥。还没等我开口,就听到他说:“我昨晚看了一遍你的代码,你留意下批注的代码审阅意见。”
“有这么多问题吗?需要你看一晚?”我心里嘀咕着,不解地打开电脑,一下子被满屏的审阅意见整蒙了 :“命名不好”“可读性差”“抽象提取,避免霰弹式修改”“边界条件考虑不足”……我有些不服气,凑合着改了几处问题,就草草提交了代码,心想:“这都是小问题嘛!主要功能没问题,这不就行了!”
但很快,问题单就像冷冷的冰雨狠狠地砸向我。转测后,我“喜提”了9张问题单,我的第一个需求也名列当期转测质量倒数榜单的“榜首”。我开始尴尬地修改一张张问题单,我也逐渐发现正是因为我不屑于改正那些强哥指出的“小细节”,才引发一系列bug。我不禁责怪自己太“年轻”,也顿悟:“学院派”可能并不是一个褒义词!在校期间,我写代码向来是“高歌猛进”,大多数情况只验证可行性,很少考虑代码的稳定性与性能,更不会关注客户的实际使用场景。
我像是泄了气的皮球,一时间没了劲头。强哥似乎看穿了我的低落,走过来安慰我:“年轻就不要怕失败,更何况这都不算什么失败!”吸取了这次教训,我开始关注代码质量和规范,安下心来,扎扎实实地把iLearning上的《软件架构设计》《代码坏味道》《开发者自测试》等课程学习了一遍。我更加注意细节、重视代码架构和质量,从代码设计到开发,我都主动与SE和测试的同事们沟通,我还会在写完代码后做好充分的自测。认真修改好9张问题单后,这个需求总算经受住了测试的严格考验。
乾坤云设备生命周期管理团队合影(左一为作者)
随着高级威胁、勒索病毒的日益猖獗,华为乾坤团队规划了“云-边-端”协同的纵深防御体系,能通过强大的云上安全大脑,协同边界网络设备与终端安全软件,为客户提供安全的网络环境。
其中,“端”是指终端安全EDR(终端防护与响应),是一款安装在终端电脑上的杀毒软件。不同于传统杀毒软件“被动挨打”的防护思路,我们可以通过云端威胁情报、机器学习、异常行为分析等方式,主动发现内外部安全威胁,并自动化阻止、取证、补救和溯源,从而有效保障网络安全。
2021年下半年,为加速EDR研发进度,部门抽调了各领域专家和骨干组成终端防护预研小组。当时,“端”侧安全还没有落地,大家都没有“端上安全卫士”开发的经验,面对未知的领域都有些发怵。想到之前在钢厂实习时我做过类似的开发,我鼓起勇气向时任乾坤云终端安全团队的负责人王亮请缨:“我以前做过一些端侧软件,要不我来试试吧!”
本来,我还担心亮哥会因为我是个初出茅庐的小兵而犹豫,没想到他直接点了头:“太好了,果然是‘初生牛犊不怕虎’!团队在这个新战场上还没有太多的技术积累,这件事做起来肯定会很困难,但我相信只要你能扎进去、好好干,咱一定能做出成绩!”
亮哥的鼓励让我干劲十足,怀着既兴奋又忐忑的心情,我随即投入到“端侧安全”这个新战场。仔细研究后,我发现这件事远没有我最初想的那么简单:从软件的安装部署到网络通信,再到核心的采集、指令执行的能力,甚至整个软件工程的编译构建,一切都将是从零开始。一时之间,我竟然迷茫到不知从何下手。
静下心来仔细想想,我又给自己打气:我背后还有一支强大、靠谱的队伍。有什么问题,边问、边学、边解决就好了!调整好心态,我开始一边体验业界产品的功能和业务场景,一边研究同类开源产品的技术实现。
通过亮哥的引荐,我还辗转找到公司安全网关部门的张伟双、软件教练杜鹏和李钊等技术大佬,主动学习、了解产品的技术原理和实现细节。那段时间,我的脑袋里装满了“如何保证网络通道的安全”“怎样第一时间采集到攻击者的恶意行为”“怎样高效地执行云上杀毒指令”……等一系列问题。为了能第一时间约到专家,我蹲点等着专家的WeLink头像“变绿”,到专家工位“围追堵截”,甚至厚着脸皮约着专家去撸串。会议拉了一次又一次,肉撸了一串又一串,手上的难题也终于一个又一个被攻克。
其中,有一个问题让我印象深刻。在开发勒索行为检测这一功能时,我们发现在某些机器上的检测延迟非常高,夸张到勒索行为发生5分钟后,我们的软件才提示自动拦截,但这显然已经是“马后炮”了!
延迟时间这么久,意味着防勒索功能已经失去意义,我们必须要攻克这一技术难题。我们团队从头到尾排查下来,发现是“事件上报性能不足”导致了如此大规模的延迟。勒索软件一秒钟可能产生上千条异常事件,但云侧上传接口每秒最多允许我们调用十余次,这是百倍的性能差距。打个比方,这就像繁忙的高速公路上突然出现一个“龟速”收费站,只允许车辆慢慢通过,而后面又有车辆源源不断地涌入,马上就会出现几公里的“大型堵车现场”。
问题看上去很简单,我提出了扩建“收费站”的解决办法。然而,专家很快就驳回了这个思路,因为扩展的成本难以估量,会影响产品的整体竞争力。这个问题只得另想他法。
问题无解,下班后,我们一行人结伴前往地铁站。
“高速路上堵车,收费站不给力是一方面,但路上的车是不是也太多了?如果不能改造收费站,那有没有办法减少车的数量?”杜教练在月台上提出了自己的想法。
“可是,‘车’的数量怎么控制呢?有些性能很好的电脑,勒索病毒一秒钟就可以加密几百个文件,产生上千个事件,这些事件都得上报,这样才能准确判断出是否有勒索病毒。”我细细想了想,无奈地回道。
“那如果做一个分类器,先把这些‘车’归归类,做一些初步的信息提炼,有没有可能减少事件的数量?”杜教练继续分析道。
“这个路子肯定可以,但是我们端侧的分析模型还不健全,不具备信息提炼的能力……”我叹了口气,思绪开始有些混乱。
聊着聊着,地铁进站的播报响了起来。杜教练嘿嘿一笑:“这会晚高峰,路上肯定堵死了,幸亏坐地铁。”
嗯?我脑中灵光一现:如果我们也让那些“车”去坐“地铁”,是不是就可以大批量、准时到达目的地?
有了这个想法,我立马和杜教练讨论起来。巨量的事件如果按照顺序一个个上报到云上,必然会造成通道拥堵,但如果我们建一辆定时启动的“地铁”,让它们都按班次运行,一次就可以运送近千条数据,应该就能解决现在的困境!第二天,我们开始尝试这一解决方案,果然有戏!后续,为了更充分地提高性能,除了“定时启动”,我们还制定了“车满即走”的数据发送策略,进一步避免了高延时拦截的尴尬。
最终,我成功完成了挑战任务,顺利交付了第一版端侧软件。当一个恶意进程在靶机上产生高级威胁时,我们的终端软件瞬间能采集到它的行为信息,并上报给“云上安全大脑”。随后,安全大脑通过分析研判,迅速下达处置指令,收到指令的终端软件立即阻断恶意行为,并能将恶意进程隔离在安全区内,成功保护了终端设备的安全!
在这个新战场上,初出茅庐的我首战告捷,快速成长,荣获了华为南京研究所“年度优秀新员工”的荣誉,也成为了一名Committer(代码提交者)。这些荣誉和责任,更让我对软件开发保持敬畏心,时刻拥有对探索未知领域的无限热情与勇气,充满持续进步、持续成长的动力。
南京研究所优秀新员工颁奖(右二为作者)
2022年上半年,随着业务的快速推进、开发投入力量增多,我们的软件代码量开始飞速膨胀,从一开始的“精致小巧”变得臃肿起来。更令我们头疼的是,它似乎慢慢变成了一间“破败的房子”:代码分层混乱、业务间耦合严重,上新增功能时必须要非常小心,一不留神就会“牵一发而动全身”。在版本月度迭代中,常常要先花上半个月修复旧bug,再花半个月“写出”一堆新bug,这种情况让我非常抓狂。这些臃肿、甚至有些“丑陋”的代码,我越看越不顺眼。于是,我决心来一次彻底“翻新”:重构业务模块代码!
我将这个大胆的想法告诉PL(项目负责人)后,他震惊后仰:“够大胆啊!重构无疑是有风险的,你要思考好两个问题,已有的功能怎么保证正常?新代码的质量怎么保证?”
还记得,软件教练李钊老师曾为我解答“什么是好代码”的困惑,这个答案我一直牢记:“首先,让人看得不爽的代码一般都不是好代码!你看得不爽时,八成写代码的人的思路也不通畅。其次,好测试的代码一般都是好代码!好测试就意味着分层合理、功能内聚,而且测试周全的代码也很少出bug!”
记起钊哥的指导,我瞬间有了方向。首先,我把我所负责的业务模块内所有代码都捋了一遍,一边理解一边画出业务流程图,将让我感到“不爽”的代码全记录下来。接下来,我开始梳理哪些流程重复、哪些分层不合理,哪些地方可以补充测试用例……最后,我将这份“重构”思路整理成文档,分享到组内,让大家一起帮忙审核优化。
反复打磨之后,我开始正式着手重构。这次,我计划采用TDD(测试驱动开发)模式编写代码。我着重考虑了业务的使用场景,依此编写测试用例,在测试用例跑通后再重写内部逻辑。花了一个多月的时间,我成功将数据采集、指令执行两大功能的架构底座抽取了出来,重新帮“房子”打好了可靠的“新地基”。代码写完后,我还拉着软件教练一起反复优化,针对重构的代码逐字斟句酌地反复调整……
重构代码交付后,新问题引入为零,测试覆盖率由原来的不足20%提升到80%,软件性能也有了进一步的提高,我们还获得了总架构师的点赞。
有了这个“地基”,我们在拓展新业务时的确轻松了不少。截至目前,这个“地基”已经支撑20多项业务平稳且快速发展,它还让我荣获2022年ICT产品与解决方案“杰出工程师”的荣誉。在这次的重构中,我也将源自《代码整洁之道》、公司倡导的clean code方法论付诸实践,学到了很多东西,未来也会身体力行地持续追求好代码、输出好代码。
ICT产品与解决方案“杰出工程师”
入职两年多,怀着对软件的热爱,怀着对“工程师”这一角色的强烈认可,我从一个“学院派”的软件小白慢慢成长为一名“杰出工程师”,这个过程中有压力、有曲折、有付出,更有收获。正如《软件整洁之道》的作者Bob大叔所说:“做软件就像‘画画’,编程的本质是一门工艺。”我希望我能一直当好一名工匠,用手中的键盘一丝不苟地雕刻手中的代码。
我相信,我会心怀热爱,用代码勾勒出拥有无限可能的未来!
文章来源:心声社区