如何使程序无错误(或者尽可能少的错误)

时间:2020-03-06 14:32:45  来源:igfitidea点击:

好吧,我知道这是一个愚蠢的问题,所以让我澄清一下。

我的老板认为,"到现在为止,凭借知识水平,我们应该再也不会在软件中出现错误了"。尽管这可能是正确的,但如果提供了正确的工具集和正确的方法,则永远不会允许我使用这些工具,也许是因为我不知道该怎么回答他(我是这里唯一的开发人员,所以我没有人在发生这种情况时求助于此)。

所以,这是我的问题:我们使用什么工具和方法来减少软件中可能的错误?

底线:没有任何错误的代码是不可能的。但是,这是可能的:

测验

  • 测试驱动的开发
  • 单元测试
  • 自动化测试
  • 功能测试
  • 变异测试
  • 由团队和绕过者进行测试

工具

  • 源代码控制
  • 优秀的编辑器/ IDE
  • 错误跟踪软件
  • 静态代码分析

实践,管理,环境

  • 代码覆盖率
  • 对等代码审查
  • 断言检查假设
  • 持续集成
  • 发展阶段
  • 工作时不会分心
  • 时间

解决方案

测试驱动开发是一个好的开始,但还远远不够。良好的实践,对代码的审阅和编程,高度的关注和良好的测试人员的协作可以有效地改善错误控制。

但是我认为"无错软件"与科幻小说有关。

单元测试!它不是一个好主意,但它节省了很多调试时间。

我们确实需要让老板意识到,编写几乎没有错误的任何复杂软件几乎是不可能的。

一旦我们接受了编写无bug的代码是一项不可能的任务,我们就可以开始关注真正重要的方面:使所有bug都易于检测到

单元测试是一种很好的方法,随着时间的流逝,我们会发现很多小技巧,这些小技巧可以避免使用这些技巧,尽管这实际上只是凭经验而已,并且知道我们可能会发生哪种错误。制作。

一个经常被引用(可能现在不相关)的示例是颠倒比较的顺序,例如:

"bar" == foo

而不是

foo == "bar"

因此,当我们打算执行比较时(foo ==" bar"),我们不会最终进行分配(foo =" bar")。如果我们颠倒顺序,那么错误情况(" bar" = foo`)是易于检测的语法错误,而不是很难找到的逻辑错误。但这仅在我们经常犯此类错误时才有用。

也许老板不熟悉人为错误。话虽这么说,使用单元测试,持续集成和静态代码分析等实践可以提高代码质量并减少某些类型的错误。

一些想法:

  • 练习编写单元测试。这挽救了我很多次(不是字面上)。
  • 使用源代码管理
  • 使用代码覆盖率工具-例如,在Java中,我使用Emma或者Cobertura
  • 使用持续集成构建工具,例如Cruise Control
  • 使用断言检查假设。 《实用程序员》(本书)对此进行了更详细的介绍。实际上,我强烈建议我们阅读。
  • 功能测试-例如,在Java中,我们可以研究jFeature

我想加强其他人关于编写无错误代码的说法-这是不可能的。但是,使用上述某些或者全部技术至少应有助于减少bug。

显然,甚至可能最重要的是,在部署/发布软件之前,我们应该让某人测试软件(即不仅仅是自动化测试)。

除非应用程序很小,否则我认为没有bug是不可能的。

我确实认为我们可以并且必须尝试通过严格的测试来限制软件中的错误数量。

我认为"到目前为止,凭知识水平,我们再也不应该在软件中出现错误了"。

但是我们可以在自己的项目中使用TDD(测试驱动开发人员),以最大程度地减少发行版中的错误。但这不是一个完整的解决方案。有些错误非常复杂,可能是由于更新了第三方组件或者其他原因引起的。

当我们有明确的要求进行测试以及防止回归时,JUnit(或者其他一些单元测试程序)将非常有用。如果测试是自动化的并且经常运行,则可以确保所做的更改不会破坏系统的其他部分。在设计棘手的类时,它也很有用,因为我们可以计划要测试的所有(很多)边缘情况,并一起测试它们。

关键点是

  • 自动化测试
  • 经常运行测试
  • 确保测试用例满足已知要求
  • 发现错误时创建测试用例;这些测试将失败,直到修复了错误

首先:无错误的软件是一个神话!

其次,工具本身依赖于很多东西,但是如果我们想让它们尽可能通用:

  • 优秀的编辑
  • 一个好的版本控制系统
  • 正确的开发阶段(功能设计,技术设计等)
  • 一支合适的测试团队
  • 一个不适当的测试团队(基本上是我们带来的送牛奶者,清洁女工和公共汽车司机……不知道他们在处理计算机和界面方面在做什么的人)
  • 一种表明我们不希望分心的方法
  • 当我们陷入困境时能够解决问题的时间

我同情你和你的老板。我认为,在当今时代,使软件"完美"昂贵的成本如此之高,以至于没人愿意为此付费。最终,客户接受了使软件负担得起的漏洞级别。

我将贡献一个简单的"方法"。这是零缺陷里程碑的想法。在软件项目中谈论代表项目时间轴重要点的里程碑是很常见的。在我见过的大多数情况下,人们说他们已经在完成为该里程碑中的功能键入代码时达到了里程碑。当然,实际上,这使我们不了解完成进度。

零缺陷里程碑不会尝试零缺陷。相反,这意味着我们必须先进行一些测试并确信自己知道所有错误是什么,才能声明已达到里程碑。我们可以选择在声明里程碑之前修复某些问题,也可以不声明,但是至少我们知道它们是什么。我们可以确定要进行多少测试,可以接受哪些错误,但是这些事情需要事先达成协议。

这种里程碑可以更好地衡量我们完成进度的程度,但是令人惊讶的是,我们很少看到以这种方式管理的项目。我推荐它。

软件中存在哪些缺陷?

越界错误?读取未初始化的变量?取消引用无效的指针?可以通过静态分析工具检测到这些。

对要求的理解不完整?在这里,测试驱动的开发和审查文化会有所帮助。

设计有问题吗?同样,评论是很大的帮助。

使用过时的代码?这就需要版本控制。

并且:保留缺陷日志,这样我们就知道自己造成了哪种缺陷。

我已经成功采用了"早期发布,经常发布"模式,在该模式下,一次选择较少的功能,并在将这些功能包括在发行版中之前对其进行了广泛的测试。不符合质量标准的功能不包括在迭代中。

显然,这并不能单独起作用,我们需要具有良好的开发实践,例如Phil,Manrico,Twan和其他人所提到的。

关于最佳实践,良好的开发流程+ TTD,但使用的一切都...
变异测试非常酷的工具来衡量单元测试的质量! http://nester.sourceforge.net/

祝你好运。

/伊夫根尼(Ievgenii)

无错误的软件是一个神话。为了进行比较,当老板说我们现在不应该在软件中出现错误时,这就像在告诉数学家他们现在应该已经算出了精确的十进制值,或者找到了所有的质数。无错误的软件是我们要实现的目标,而不是我们要实现的目标。

这并不是说我们不对软件中的错误负责任,或者熟练的开发人员不会减少错误的发生率。但是老板需要对自己的能力有现实的期望。没有完美的驱动程序,没有完美的管理者,也没有完美的程序员。

cosmo0,很抱歉,但我为我们感到可惜。

对我来说,老板认为我们必须编写无错误的代码与我们认为必须拥有无限的薪水是一样的。在"无错误"中添加"几乎"一词根本不会改变其含义。

有没有错误的代码。具有0功能的代码没有错误。但这是没有用的。

编写计算机程序与下棋非常相似。举世闻名的国际象棋冠军提格伦·彼得罗森(Tigran Petrosian)曾被一位不太礼貌的记者问到为何有时会犯大错。答案非常简单:"因为下棋并不容易。尝试自己下棋,就会看到。"

当然,我建议仅当老板是一个聪明的人并且会做对的时候才使用这个例子作为理由。否则,寻找另一份工作可能会更好。

它从一开始就是愚蠢的,不限于编程。只是几个反例。
我们大多数人都有自己的驾驶执照已有很长的年龄,因此永远不要再将它们卷入意外之中。那有多真实?

再举一个例子,在"正常"条件下螺钉决不会断裂,但它们仍然会断裂。可能超载,或者它们可能开始生锈,或者有人认为使用较差的质量是个好主意。并猜测一下我们没有看到的内容,我们必须很有可能说一堆螺丝钉是可以的,但是我们不能对它们进行详尽的测试。里面可能有薄弱的地方,这可能是因为其中包括空气,而我们不对其进行X射线检查则几乎看不到。因此,它一遍又一遍地反复进行,如果那种态度听起来有些合理,那么我们将生活在一个完全不同的世界中。

老板能否为我们提供无错误且完整的规范,这些规范从完成它们到完成软件的那一刻都不会改变?当我说完整时,我不仅指功能列表。所有功能之间的所有交互,对每种可能的用户输入的所有行为期望,环境的每种可能条件(例如,操作系统,存在的文件,正在运行的其他应用程序,对共享资源的访问,字体大小,配色方案,键盘)如何?布局),哪个进程的优先级高于其他进程,计时的毫秒级等。