`
熊likecocoa
  • 浏览: 18609 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

如何避免脆弱的代码

 
阅读更多
遗留代码最常见的问题就是脆弱性。团队如要修改脆弱的代码库,必定伴随着巨大的痛楚。在我们 ThoughtWorks 开发产品的 10 年里,当我们年复一年地尽量保持庞大代码库的延展性时,学到了一些惨痛的教训。我想在本文分享我们从最大挑战中吸取的教训。声明:我写下这些思考,不代表我们已经搞定了所有问题。我们仍然要分担遗留代码的痛苦,和其它团队一样,我们每天都努力让它变得更好一些。

更新所有东东,要一直更新下去

你应该一直渴求更新依赖库和框架。好吧,或许现在已成为共识。但是,10 年前很少有人这样想。有些团队明白,升级是需要完成的、正确的工作,我只是怀疑,他们是否真地优先去做了。它一直需要你认真对待,不要拖到最后,变成技术债务。原因如下:

· 如果某项任务是痛点,就要经常去做。对于一直升级所存在的最明显的理由之一,就在于升级会是艰难的。常常存在不可预期的、一系列被破坏的依赖。工作量通常无法知晓。经常做,它就不再是问题。但是,和简单的避免痛苦相比,还有更重要的原因。

· 升级依赖项的另一个驱动力,在于修复安全漏洞。现在和 10 年前开发软件,有一个最大的不同,我们资源库、框架和应用程序的漏洞报告仿佛从未间断过。修复漏洞,差不多总是涉及到升级某些依赖项。为了快速修复漏洞,升级必须容易操作。

· 没有定期升级操作的团队,通常将其贴上技术债务的标签。尽管行业比 10 年前更乐意谈起技术债务,但是,说服项目经理偿还技术债务,仍然算得上非常艰难的对话。如果你的团队处于「一直升级所有东东的模式」,你就不用为了升级技术债务而展开沟通。

关于单元测试

遗留代码的主要痛点在于,做出修改需要花费多长时间。如果你打算让代码长期运行下去,就需要确保未来修改代码的程序员感到完全地开心。有一种处于优势的方法:极度快速、彻底的单元测试套件。

增加新功能、包括任何代码重构,每个周期大致描述为:编写失败的测试;写代码;显示绿色;搞定。如果你这样做了,你就能一直执行大量的单元测试,有时候是某一套针对性的测试、有时候是整个套件。如果测试不够快,开发周期就不会轻松。写代码的体验不应该是:做了一些修改,而运行测试却需要坐等 10 或 20 分钟。太差劲了。
确保测试套件快速运行,不只是与你的设计和代码有关。诚然,你可以做大量工作来加速测试,比如避免文件、数据库、套接字、海量对象图表生成等。但是还有另外的重要技巧,挑选有助于加速测试的框架和语言。如果你发现自己为了让测试更快、而修改了框架,那么,你需要考虑不同的框架。是的,当我正在开发传统的多页应用程序时,下次就不可能用 Rails 开发了。

还需要考虑应用程序的大小。当某个代码库处于一定规模时,就需要规划好切分方案。这也是让你充分理解某块代码的唯一方法。找到分割项目的切入点,这不同于学术上的工作,你需要投入大量时间折腾代码、研究各种地方、再设计、重构。一直让快速的测试套件迅速地验证你的工作,将使这份工作轻松几个数量级。
实际上,「几个数量级」更像是夸张。如果你需要切分庞大的代码库,并忍受着痛苦的、龟速的单元测试套件,嗯,你可能会被困住。我们正在痛苦地得到教训。因此,尽力确保单元测试要快,并且在开发机器上以单一线程运行。

「抽象分支」不应该是常态

运行时间长的产品,经历了很多技术领导。某些类型的技术领导,刚一接手,就抱怨现有产品的不足,并马上想开发新的产品。这没错。时髦的技术不总是糟糕的。对于长时间存在的代码库,它需要新的活力,产生足够能量,淘汰不能胜任的地方。我想提两个重要的点。

新接手的技术领导,在和团队一起工作两到三个月之前,不要轻易摒弃任何技术。有太多的情景需要理解。新接手的技术领导需要学会站在团队和代码库的角度考虑。团队和技术领导需要建立信任和节奏。短暂地停留是为了更好的决定。

利用抽象分支,是替换新技术的经典方法(长期分支的荒谬性之外):
· 组件 X 前面放置一个抽象。
· 组件 Y 做为 X 的替换品,被引入。
· 抽象智能地路由到 X 或 Y。
· X 逐步被废弃掉。
· X 被移除;或许抽象也被移除了。

有很多次,我都看不到这个过程能够顺利走完,因为移除旧组件最后 20% 的工作太难了。你简直想象不到,年复一年地用多种方式做这项工作有多么痛苦。它减缓了所有工作,还让士气消沉。抽象分支属于优秀的模式,他也是我做这种组件替换工作的唯一方式。但是,它需要团队的完全承诺,即,在既定时间内,淘汰旧组件。

技术债务会杀了你

仅仅因为我们这里过多地讨论了技术债务,并不能为偿还技术债务提供任何担保。有一点是肯定的,任由技术债务积压下去,只会使其变得无法偿还。「先放一放。我们先做其它紧急需求,它被记下来了,我们回头再搞。」,这话很容易说出口。同时,它可能算得上明智决定。但是,那些所谓的紧急需求永远没有结束的那一天。紧急清单只会越变越长。
状况会恶化下去。据我经验看,当技术债务积压增长过于频繁时,团队将趋向于放弃偿还,团队感到失望,开发人员不能达到流动,业务也获取不到新的价值。关于如何避免不可逾越的技术债务,我做过一些思考。

一个良好的开发团队,不会一而再、再而三地以技术债务为借口。当团队意识到,同种技术债务重复出现时,就必须向前推动,并很快将其融入到日常工作中去。

我的同事 Badri 建议,团队必须就共同承担技术债务达成一致。任何人无权让代码库变得更糟、而让整个团队随后为此买单。

更重要的是,技术领导和产品领导需要彼此信任。双方都不应该玩「我说了算」的把戏。好的技术领导理解业务的优先级,好的产品经理看重能够交付的价值。双方均需要探讨风险、成本和收益。如果你无法交付,你的技术债务就转变成了业务问题,对每个人都没有好处。

显然,为了编写长期存在的代码,一个团队还有大量工作要做:为阅读代码的人写代码,不要自作聪明,经常想想你未来的同事。我乐于听到你的想法。(作者:腊八粥来源:腊八粥​)
分享到:
评论

相关推荐

    郁金香代码注入器

    然而,对于非专业人士来说,使用这些工具可能会触犯法律,因此在未得到适当授权的情况下,应避免使用类似郁金香代码注入器的工具。 总之,郁金香代码注入器是一个涉及到高级编程和网络安全的专业工具,其核心功能是...

    代码审查工具源码合集

    flawfinder-1.31.tar.gz包含了该工具的源码,通过阅读源码,开发者可以理解它是如何快速扫描代码并标记可能的脆弱点的。 深入学习这些工具的源码,不仅可以提升对C/C++编程语言的理解,还可以掌握静态代码分析的...

    追求代码质量: 软件架构的代码质量

    同时,通过分析代码覆盖率报告和测试用例,可以确保对变更的充分验证,避免引入新的问题。 随着时间推移,架构可能会因为不恰当的引入、团队磨损或缺乏文档而导致熵的增加,即系统复杂性的无序增长。例如,当更多的...

    微软出品《代码大全》(第二版)

    12. **软件工程原则**:回顾了一些基础的软件工程原则,如DRY(Don't Repeat Yourself)、KISS(Keep It Simple, Stupid)和YAGNI(You Aren't Gonna Need It),这些原则有助于避免过度设计和代码冗余。 《代码...

    代码之美(中文完整版).pdf

    5.6 版本4:第二次优化:避免重复验证 5.7 版本5:第三次优化:复杂度 O(1) 5.8 版本 6:第四次优化:缓存(Caching) 5.9 从故事中学到的 第6章 集成测试框架:脆弱之美 6.1. 三个类搞定一个验收测试框架 6.2. 框架...

    Morris蠕虫源代码

    这个事件不仅在技术层面上展示了计算机安全的脆弱性,也在法律和公众意识层面推动了网络安全的重要性。 源代码是理解任何软件工作原理的基础,包括恶意软件。Morris蠕虫的源代码提供了一个深入研究早期网络攻击手段...

    css代码优化的12个技巧

    3. 避免使用链式选择符:链式选择符(也称为交集选择符)虽然可以缩小样式匹配范围,但它们使CSS更脆弱,应当尽量使用组合类选择符。 4. 坚持KISS原则:保持简单,不要让CSS规则过于复杂。简单的规则更易于阅读和...

    一个指示网络扫描的源代码

    3. **协议识别**:扫描过程中,源代码会根据目标返回的应答识别运行在开放端口上的服务协议,如HTTP、FTP、SMTP等,这有助于了解目标主机的功能和可能的脆弱性。 4. **服务版本检测**:进一步,源代码可能尝试获取...

    通过量子稳定器代码的组表示来构造避免量子错误的新代码

    由于量子计算系统异常脆弱,对于错误的敏感性极高,因此构建能够避免错误的量子代码具有巨大的实用价值。本文中提出的DFSs-based QEACs提供了一种新的技术手段,来达到这一目的。通过数值模拟,研究人员验证了这些...

    针对恶意代码的行为阻断方法研究

    这些技术往往依赖于恶意代码的特征库更新,而在新的恶意代码被发现并加入特征库之前,就会形成所谓的“脆弱性窗口”,在这段时间内,恶意代码可以轻易地绕过防护措施,对系统造成损害。 启发式经验规则则是一种更为...

    重构中错误代码

    硬编码的值使代码难以复用和测试,而过度依赖外部资源可能导致脆弱性。可以使用配置文件、常量类或依赖注入等方式来改善这种情况。 最后,**不恰当的异常处理**可能导致错误传播,影响系统的稳定性和健壮性。重构时...

    SQL注入漏洞演示源代码

    7. **修复方法**:源代码可能还包含修复这些漏洞的具体代码片段,展示如何将脆弱的查询转换为安全的查询。 8. **学习与实践**:此资源对于学习者来说是一个很好的实践平台,可以尝试注入攻击并学习如何修复。 通过...

    软件安全_安全代码原则和实践

    作者基于在计算机安全领域多年的实践经验,提供了丰富的建议,解释了为何当今的大量代码充满着脆弱性,并指导读者如何避免编写易受攻击的代码。 ### 安全架构与设计 安全架构章节讨论了什么是安全架构,以及构建...

    代码安全测试fortify规则库2020.01

    《代码安全测试Fortify规则库2020.01详解》 在IT行业中,代码安全测试是一项至关重要的任务,它...正确理解和运用这些规则,不仅能够提高代码质量,还能有效避免因安全漏洞带来的损失,是保障企业信息安全的关键环节。

    java 反编译 字节码 源代码 绿色软件 直接打开jar包

    同时,它也可以帮助我们发现潜在的安全漏洞,因为反编译后的代码可以暴露可能的脆弱点。 总的来说,“java-decompile-gui.exe”是一个实用的工具,它简化了查看和分析.jar文件中的字节码的过程。通过反编译,我们...

    基于等级保护的恶意代码防护体系建设方案.doc.rar

    2. 风险评估:在建设防护体系之前,通常需要进行风险评估,确定系统的安全风险和脆弱性,以便针对性地制定防护策略。 3. 恶意代码防护策略:这部分可能会讨论多种技术手段,如防火墙、入侵检测系统、反病毒软件、...

    金山卫士源代码(漏洞扫描。隐私保护)

    源代码中可能会涉及网络协议解析、文件系统遍历、系统调用监控等方面,用于识别潜在的攻击入口和脆弱点。这包括对操作系统API的调用、动态链接库(DLL)的检查以及对已知漏洞特征的匹配。 3. **隐私保护策略**:金山...

    安全修炼编程之道 附代码

    它深入讲解了如何避免常见的编程错误,如缓冲区溢出、SQL注入、跨站脚本攻击等,这些都是导致系统脆弱性的常见原因。通过分析这些漏洞的工作原理,读者可以更好地理解如何预防它们。 此外,书中还介绍了安全编码的...

Global site tag (gtag.js) - Google Analytics