您还未登录! 登录 | 注册 | 帮助  

您的位置: 首页 > 软件开发专栏 > 开发技术 > 正文

编程须谨记:大象不咬人,蚊子却致命

发表于:2021-03-23 作者:读芯术 来源:51cto

本文转载自公众号“读芯术”(ID:AI_Discovery)。

1996年6月24日,欧洲航天局的阿丽亚娜5号无人火箭在发射仅37秒后爆炸。三亿七千万的投资和十几年的努力在一瞬间付诸东流。

原因为何?源自一个简单的软件漏洞。它试图将可代表数十亿个潜在值的64位浮点型变量存储至只能代表65535个潜在值的16位整数中。也就是说,为了让火箭进入太空,需要分配更多的储存空间。

这告诉我们,小的失误会造成严重的后果,潜在危险最大,为此付出的代价最高。

大象不咬人,它们只想与你成为朋友

程序出错时,几乎每一个明显的错误都会在代码中显现。这些错误会引发显而易见的编译器错误或运行错误,而编译器错误或运行错误会在用户界面或编译器中体现出来。开发人员很清楚,这些问题需要立即解决,所以这些错误几乎不会引发担忧。

最有可能的情况是,发现错误后,开发人员立刻进行修复,绝不会提交一份板上钉钉的半成品或编写了不符合预期目标的代码。

大象不咬人,因为可以以直观的方式将它们轻易驯服。从长远角度来看,它们不会惹任何麻烦,也不会造成任何伤害(除非命令它们那么做)。它们容易识别,通常会说,“看看我!关注我,我会向你表达爱意,你不会后悔的。”

蚊子会成群结队地叮咬你,让你患上莱姆病,甚至杀死你

与大象相对的是蚊子——代码中看似无关紧要且并不明显的部分,作为隐藏数据藏匿于看似有效的代码的backburner中。他们随时准备发动攻击,让代码毁于一旦。由此导致的错误包括:逻辑错误、设计问题、杂乱的代码以及有缺陷的非优化算法。

阿丽亚娜5号火箭发射的问题在于,研究人员复制了此前成功发射的阿丽亚娜4号火箭的工作代码。研究人员显然认为这些代码同样适用于阿丽亚娜5号,但这些代码并不能满足阿丽亚娜5号火箭的环境需求,无法应对新环境的要求。

图源:unsplash

最小的错误却造成了最大的问题

  • 逻辑错误会引发产品处理问题和产品信息显示问题,减损预期功能,影响用户体验。即便开发人员没有在应用程序的运行方式上发现任何相关的或可立即识别的问题,也会导致用户流失。
  • 设计不当会导致类似阿丽亚娜5号火箭爆炸等问题。这种设计下的代码可以在低计算量的环境中工作,但不能在高计算量的环境中工作。忽略相关事宜会导致系统故障,因为系统不是为处理大规模操作而设计。

此类问题通常在编写良好的测试代码中出现,这些测试代码旨在给系统施加尽可能多的压力,但如果不编写测试代码处理这些情况,可能会发生令人震惊的黑天鹅事件,从而造成严重的后果。

  • 杂乱的代码会增加代码中的错误和问题识别难度。除此之外,随着代码的扩展和修改越发困难,开发成本也会急剧增加。这会使代码更容易出现常见错误。杂乱的代码出现时,应即刻提高警惕,进行代码重构。
  • 在计算量大的情况下,非优化算法会影响性能。尤其对于适用于不适应重构代码以更好地执行算法的程序员来说,这个细节很容易被忽视。

当遇到加载时间长、超时或限制时(特别是使用云后端时),通常会注意到这个细节。有些代码单独运行时效果会很好,但在编程时需意识到,单独运行顺利并不意味着它能够与大型数据集和其他组件协同工作。

如果不顾这些小问题,其结果将会令人大吃一惊。好消息是,有很多方法可以降低并最小化这些错误的影响。

使用驱虫剂!

不注意小的问题,最终会面临最大的问题。在某种程度上,阿丽亚娜5号事件的程序员值得同情。但是此类事件说明,在大量的压力测试和测试驱动开发的支持下,仔细编写代码尤为重要。

编程不只是写出能运行的代码,它还需要仔细周到的考虑:代码不是胡乱编写,许多新老程序员只是把代码片段拼凑在一起,就像试图把圆柱体塞进方孔一样。虽然圆柱也能塞进去,但并不合理,而且无论如何也不稳固。

图源:unsplash

因此,在编写代码时最好把这些问题放在心中:

  • 代码是否过于复杂?应如何将其简化?
  • 是否为代码编写了严格的测试类,这些测试类具有强大的断言和测试功能,以应对多种不同的数据饱和和高计算量情境?是否了解代码的局限性?
  • 函数是否太小?可以将大型函数的方法应用于小型函数吗?
  • 变量,类和函数是否拥有清晰明确的名称?仅通过阅读名称能否明确了解代码的功能?
  • 是否复制了过多的方法,而这些方法可在多种不同的过程中重用并具有通用功能?重复方法是绝对必要的吗?它们值得应用于不同的功能情境吗?
  • 如何处理错误?是否使用try-catch块抛出错误,并对变量运行null检查?错误被发现时,是否有特定的过程来确保功能平稳?
  • 代码是否易于扩展和延伸?如果进行了修改,需要担心任何相依性吗?
  • 代码是否有能力优化来处理大量数据?代码在运行压力过大时是否会引发错误或超时?

当然,还可以问自己更多的问题,这些问题足够汇编成一个详尽的清单上述问题可能是最重要的,但却未得到足够的重视。通过限制潜在的未知错误,使不确定的事情成为已知,来降低代码中任何错误的风险,而非观察后才成为已知。

这些大错误不应成为长期关注点,因为大错误很容易更正和解决。日常的微小错误和不一致性才是真正需要关注的问题。