你为什么疲于应对各种bug?

发布于 2023-11-26 | 更新于 2024-03-03

在编程之海洋中,现网之Bug犹如潜伏的幽灵,常常在不经意间跳出,扰乱开发之团队的平静。这些幽灵之所以能游走于代码之间,皆因那些看似风趣而实则荒谬的开发习惯。我等常在不经意间,以一种看似合理却又布满陷阱的方式,编织了这一网络。

在这软件开发的世界里,表面看似光鲜,实则暗藏玄机。诸如急于求成的代码编写,又或是频繁更改需求而不顾整体架构之稳固,这些习以为常的做法,竟是制造Bug的温床。

每当夜深人静之时,这些代码之幽灵便开始其夜间的巡游。它们或悄然无声,或大摇大摆,总在不期而至。开发者们日以继夜,却难以将其一网打尽。于是,这场与代码幽灵的较量,便成了开发者不得不承受的宿命。然而,唯有深入探究,方能寻得破解之道,让这些幽灵无处藏身。

image-20231118131234893

在软件开发的世界里,现网Bug就像是永不消失的“幽灵”,不断地困扰着开发团队。而这些Bug的源头,往往隐藏在那些听起来充满幽默和荒谬的日常开发实践中。我们一起探讨下软件开发业界中那些看似合理,实际导致各种问题的事情。今日,吾等不妨共同探讨一二。

“快速修复”成了常态

想象一下,每次产品经理走进开发团队,都是带着“我们需要这个功能,而且是昨天就需要了!”的急切心情。开发团队为了应对这种突如其来的需求,开始编写快速但不规范的代码。这些代码就像是用胶带和超强胶粘合的,看似牢固,实则随时可能崩溃。

他们像是时间管理大师,总能在最后一刻交付功能。但问题在于,他们的代码就像是用绳子绑在一起的桥梁,一眼看去很壮观,但只要一有风吹草动,就危机四伏。

image-20231118214459153

解决方案

《持续交付:发布可靠软件的系统方法》(“Continuous Delivery: Reliable Software Releases through Build, Test, and Deployment Automation” by Jez Humble and David Farley, link) 中提倡的持续集成和自动化测试策略可以帮助团队逐步构建稳固的代码基础。

基于团队的具体人力资源和技术方案,我们需要对预定的上线时间进行一个现实和全面的可行性评估。这包括对各项任务的时间需求、潜在的技术挑战以及可能出现的意外情况进行综合考虑。在此基础上,应该向相关利益相关者明确提出任何存在的风险,确保他们对可能的延误或问题有充分的认识。

此外,特别需要注意的是,我们应该规避在业务快速增长阶段由于系统故障频发而造成的业务中断。任何在项目早期未能妥善解决的质量问题,都可能在后期业务扩张时放大其影响,甚至导致严重的业务损失和信誉风险

因此,我们应该确保在整个项目开发周期中,持续关注和提升项目的质量。这不仅包括代码质量的控制,还包括对项目管理流程的优化,以及确保团队对项目目标和时间表的共同认识。通过这样的方式,我们可以最大程度地减少项目风险,保证项目的顺利进行,从而支撑业务的健康发展。

遗留代码的谜团

小李写了一大堆代码后离开了公司,留下了一堆谜一样的功能和注释。新来的老李看着这些代码,就像在解读古埃及象形文字一样困惑。每次尝试理解或修改代码,都像是在玩俄罗斯轮盘赌。老李惊呼:小李把我坑惨了。

image-20231118215248437

如何避免代码成为谜团

《重构:改善既有代码的设计》[1]一书提供了一系列实用的方法,帮助团队逐步理解并改进现有代码。开发团队在编码和迭代过程中,需要保留优化代码的习惯,避免写出有坏道的代码。

这里IT宅也整理了一份重构速查表,帮助大家快速查找需要的重构技巧:重构速查表[2]

为了确保团队代码的质量和一致性,除了提升个人的编程技巧外,采用标准化的工具来加强代码质量控制也至关重要。例如,部署SonarQube代码质量扫描工具,并集成阿里巴巴Java开发规范的规则集,能够有效地促进编码规范的遵守。在此基础上,我们可以设置工作流程,使得每次发起合并请求(Merge Request)时自动触发增量代码扫描。这不仅能够即时发现并指出本次提交中不符合规范的代码,还能迅速通知开发人员进行必要的修复和调整。通过这样的自动化和标准化流程,我们能够在提高开发效率的同时,确保代码库的健康和一致性,从而在整个软件开发生命周期中维持高水平的代码质量。

此外,代码审查是维护高质量代码的另一关键环节。以Meta(前Facebook)为例,其代码审查原则中明确指出:代码完成后尽快进行审查能够带来更佳效果,同时建议每次审查的代码量保持在合理范围内。因此,代码提交后的及时审查是实践中的最佳选择。随着人工智能技术的进步,我们能预见很快就能够实现高度定制化的审查规则,让AI承担起代码审查的重任。这不仅能提高审查效率,还能在一定程度上减少人为的疏漏,为软件开发带来更加精确和高效的质量保障。

更多关于代码审查的相关介绍,可以进一步阅读IT宅的这篇文章:Facebook代码评审机制与版本管理[3]

而关于遗留代码怎么去接手,我们后边再详谈。

“软件升级?那是什么?”

团队使用了一个非常棒的第三方库,但自从2009年以后就没人更新过了。这个库就像是一块古老的化石,虽然珍贵,但放在现代代码中就显得格格不入。这些技术已经无法跟上现代软件的步伐,就像是试图用蒸汽机拉动高速列车。

image-20231118215428013

解决方案:定期进行技术审计,确保所用技术既现代又高效。关键在于建立一种积极更新和持续改进的文化,促进团队对现代和高效技术的采纳:

  • 建立代码审查和升级机制:实施定期的代码审查流程,包括评估所使用的第三方库的版本和安全性;
  • 鼓励持续学习和技术分享:定期组织技术分享会议,鼓励团队成员学习和分享最新的技术趋势。这可以增强团队对新技术的认识和接受度;
  • 设置定期更新策略:制定明确的库更新策略,例如每季度或每半年审查并更新所有第三方库;
  • 引入依赖管理工具:使用像Maven、Gradle或npm这样的依赖管理工具,它们可以帮助跟踪和管理依赖库的版本;
  • 开展培训和工作坊:为团队提供关于新技术和最佳实践的培训,增强团队的技术能力和对新技术的适应能力;
  • 激励更新和改进:为积极推动技术更新的团队成员提供奖励和认可,以激励团队成员关注和采纳新技术;
  • 逐步淘汰陈旧技术:制定长期计划,逐步替换掉那些过时的技术和工具,以减少对陈旧库的依赖。

这里强烈建议采用DDD编写业务代码,保证业务代码与外部基础设施解耦,保证基础设施升级的可行性。这些策略需要团队领导的支持和团队成员的共同努力,以逐步改变团队对陈旧代码库的依赖习惯。通过这种方式,保持团队技术的先进性和项目的可维护性。

个性化编码风格的时装秀

每个开发者都有自己的编程风格,就像大厨有自己的秘制配方一样。问题是,当你把所有人的“秘制配方”混合在一起时,最后得到的很可能是一锅难以下咽的杂烩。

在这个团队中,每个人编码就像是在做时尚设计,各有特色但缺乏统一。结果,代码库就像是时装秀的舞台,多姿多彩却毫无规则。

image-20231118111853201

在这个五彩缤纷的舞台上,设计师们可能会欣喜若狂,仿佛孩童在糖果店,眼前的每一种颜色都充满了无限可能。然而,对于那些肩负维护项目重任的研发人员而言,这简直就像是一出精心编排的灾难大戏。每个业务细节就像是一个有着自己独特癖好的角色,要求研发人员像是在玩一场没有规则的猜谜游戏,猜对了,代码运行顺畅;猜错了,就得准备迎接一连串的Bug攻击。这场游戏,既考验着研发团队的专业技能,又考验着他们的心理承受能力。

解决方案:实施《代码整洁之道》[4]中的编码规范,建立统一的代码风格,保证代码的整洁和一致性。

“只是加个小功能而已”

产品经理说:“我们只是想加个小功能,应该很简单吧?”结果,这个“小功能”像是在高楼上加盖了一层,但忘记了加固地基。随着功能的不断添加,整个系统就像是一座摇摇欲坠的摩天楼。

image-20231118220017759

产品经理就像不断增加新房间的建筑师,每次会议后,开发团队都要在原有的结构上增添新的功能。最后,产品变成了一个功能丰富但结构杂乱的豪华大宅,充满了隐藏的走廊和秘密房间。

解决方案

可以参考《User Story Mapping》[5]中的优先级管理帮助团队聚焦于核心功能,保证产品的合理发展。在讲清楚用户全链条故事的同时,进行需求拆分。聚焦于故事整体,不要过早陷入细节,然后探索细节和可选项,最后围绕故事链条的机会点,寻找我们能做的事情。

测试环节的隐形斗篷

由于时间紧迫,测试阶段经常被忽略。开发团队像是在玩一场没有安全网的杂技,每次上线都充满了惊险。在这个团队里,测试环节就像是《哈利·波特》中的隐形斗篷,神秘而不可见。每当新功能发布时,总会伴随着意想不到的“惊喜”。

在我的编程征途中,常有这样的情景:开发同仁们似乎将自我验证视为可有可无的修饰品,轻轻松松地将代码像送快递般递给了测试团队。测试人员,他们就像是在一个充满了未知陷阱的迷宫中探险,每走一步,就可能踩到一个Bug地雷,搞得他们的心情像过山车一样跌宕起伏。

事实上,根据《代码整洁之道》(“Clean Code” by Robert C. Martin)等专业书籍的指导,开发完毕后进行严格的自测是每个开发者的基本职责。它不仅能提高代码质量,减少测试人员的负担,还能显著提高整个项目的效率和可靠性。

解决方案

《测试驱动开发》[6]的方法能够确保每个功能都经历了严格的测试,减少Bug的产生。

除此之外,搭建自动化测试平台,保证每次发版功能能够回归。版本版本合版之后,能够被再次重复验证,确保程序无bug,以及上线配置的正确,同样至关重要。

文档是什么?能吃吗?遗留系统如何接手?

开发过程中几乎没有文档记录,新成员加入项目就像是被扔进了一个没有地图的迷宫。他们只能依靠碰运气来探索正确的路径。

image-20231119234722519

解决方案:可以参考《Living Documentation: Continuous Knowledge Sharing by Design》[7]中的文档编写原则,确保信息的清晰传递和持续更新。

如何接手文档缺失的遗留系统?

TODO

我想要的不多,只是…

产品经理提出了一个似乎很小的需求:“我们只是想在主页上加一个实时天气预报。”但没过多久,这个需求就演变成了包括温度、湿度、风速、空气质量、星座运势、甚至是未来五天的天气趋势。开发团队感觉就像是被要求从造一把椅子变成建造一支航天火箭。

image-20231118214200294

解决方案:

  • 明确和限定需求范围:与产品经理和利益相关者一起明确需求的初始范围,并设定明确的界限,明确需求是完整可行的。让所有人都理解增加新功能的影响,包括开发时间和资源;
  • 优先级分析:对需求进行优先级排序。识别哪些功能是必需的,哪些是可选的,这有助于团队集中精力在最重要的功能上;
  • 迭代开发:采用敏捷开发方法,将大型需求分解为小的迭代。这样可以逐步构建和测试功能,而不是一次性开发所有内容;
  • 持续沟通和反馈循环:与产品经理保持定期沟通,确保需求的变化得到及时沟通和反馈。这有助于避免误解和避免最后一刻的变更;
  • 变更管理流程:建立一个明确的变更管理流程,任何需求的修改都需要经过评估和批准。这有助于控制需求膨胀;
  • 使用原型和MVP(最小可行产品):开发原型和最小可行产品,快速获取用户反馈,以确认需求是否符合用户的实际需要。产品经理需要在用户的需求和产品的长期发展之间找到合适的平衡点,确保产品既能满足当前用户的需求,又能保持清晰的发展方向和创新能力。在开发中短期需求的同时,注重产品核心价值和长期改进相关工作的开展
  • 教育和管理利益相关者的期望:向利益相关者说明需求变更对项目时间线和预算的影响。管理他们的期望,让他们了解持续增加需求的后果;
  • 技术和架构灵活性:构建灵活的技术架构,使得在不影响现有功能的前提下,可以较容易地添加新功能;

别人有的我们不能没有

产品经理说:“我们的竞争对手发布了一个很酷的功能,我们也要一个类似的。”问题是,竞争对手的那个功能基于一项已经过时的技术。开发团队尝试实现这个功能,就像是被要求用打字机编写代码。

image-20231119100032451

**解决方案:**与产品经理沟通,强调现代技术替代方案的重要性,并探索如何用更新、更有效的技术实现类似功能,同时保持产品的竞争力和前瞻性。

无尽的增长

每个季度,产品经理都会添加一些新功能,但从不移除旧的或不常用的功能。随着时间的推移,产品变得越来越庞大和复杂,像是一个永无止境增长的怪物。开发团队试图维护这个庞然大物,感觉就像是在为一头永远不会停止增长的巨兽梳毛。

image-20231118221439097

**解决方案:**实施定期的功能审查和剪枝,与产品经理合作确定哪些功能是必要的,哪些可以淘汰,以维持产品的可持续性和高效维护。


在软件开发的广阔领域内,无论是应对快速修复的紧迫需求、挑战遗留代码的复杂性,还是在技术选型中避免潜在的陷阱,都需要依赖于深思熟虑的策略和恰当的方法论。关键在于,我们必须逐步构建一个更为稳健、透明且易于维护的代码生态,同时发展和规范化我们的研发流程。这不仅是技术上的升级,更是作为专业工程师素养的显著提升——从单打独斗的编码者转变为拥有系统思维和工程管理能力的专业人士。

尤其在当前这个人工智能技术迅速发展、影响深远的时代背景下,我们必须积极利用AI技术来弥补我们知识体系中的不足。这样,我们不仅能够显著提升自身的专业能力,而且能够更有效地应对日益复杂的挑战,从而在技术创新和应用领域中扮演更加积极和领导性的角色。通过与AI技术的深度融合和互补,我们可以拓宽视野,提高解决问题的效率和创新能力,实现个人职业发展和行业进步的双重跃升。

如果这篇文章触及了您的心弦,希望您能分享转发。让我们一起将这些重要的话题传播出去,唤起更多人对这些关键问题的关注和思考。您的每一次分享,都可能成为推动改变的力量。

References


  1. Martin Fowler. 重构:改善既有代码的设计. 熊节,译. 人民邮电出版社 ↩︎

  2. 重构速查表. Retrieved from https://www.itzhai.com/columns/refactoring/ ↩︎

  3. Facebook代码评审机制与版本管理 ↩︎

  4. Robert C. Martin. 代码整洁之道. 韩磊,译. 人民邮电出版社 ↩︎

  5. Jeff Patton. User Story Mapping:Discover the Whole Story, Build the Right Product. O’Reilly Media ↩︎

  6. Kent Beck. Test Driven Development: By Example. Addison-Wesley Professional ↩︎

  7. Cyrille Martraire. Living Documentation: Continuous Knowledge Sharing by Design ↩︎

本文作者: arthinking

本文链接: https://www.itzhai.com/articles/why-are-you-struggling-with-bugs.html

版权声明: 版权归作者所有,未经许可不得转载,侵权必究!联系作者请加公众号。

×
IT宅

关注公众号及时获取网站内容更新。