错误修正何时会变得过大,如果有的话?


128

假设您正在使用JavaScript创建视频播放器。该视频播放器使用递归功能反复循环播放用户的视频,因此,浏览器too much recursion RangeError有时会触发。

可能没有人会那么多地使用循环功能。您的应用程序将永远不会抛出此错误,即使用户将应用程序循环了一周也不会出现此错误,但是它仍然存在。解决该问题将需要您重新设计应用程序中循环的工作方式,这将花费大量时间。你是做什么?为什么?

  • 修正错误

  • 留下错误

您不应该只解决人们会偶然发现的错误吗?修正错误何时会变得矫kill过正?

编辑:

如果您担心递归方法不会导致实际的错误,请假设播放器每次播放视频时,变量都会增加1。在2 53循环之后,此变量将溢出,您的程序将无法处理它,并引发异常。


95
不要搞砸我的案例案例伴侣
Tiago Marinho

15
@PlasmaHH我正在使用这种假设的情况来解释我的问题。如果该bug存在或根本不重要
Tiago Marinho

13
@TiagoMarinho:我要提出的观点是:有时将这种情况定义为预期的行为是正确的做法。
PlasmaHH

23
为什么在地球上首先要使用递归来运行这样的循环?您可能不想修复该错误,但是您应该重新考虑您的设计过程:-)
jamesqf 2016年

28
这似乎更像是一个业务问题。您必须根据修复成本以及错误的影响/频率来确定优先级。
Casey Kuball

Answers:


164

你要务实。

如果错误不太可能在现实世界中触发,并且修复成本很高,我怀疑许多人会认为它是对修复资源的良好利用。在此基础上,我会说保留它,但要确保在几个月内为您或您的继任者记录了该黑客行为(请参阅最后一段)。

就是说,您应该将此问题用作“学习经验”,并且下次执行循环时,不要不必要地使用递归循环。

另外,为该错误报告做好准备。您会惊讶于最终用户如何突破界限并发现缺陷。如果确实成为最终用户的问题,那么您将不得不对其进行修复-那么,很高兴您记录了该黑客事件。


119
完全同意“您会为最终用户突破界限和发现缺陷感到多么惊讶”。

74
最终用户绝不受认为合理使用软件的限制。会有一些用户想要永远循环播放视频。这是您的软件提供的功能,因此他们将使用它。
gnasher729

36
YouTube上的@ gnasher729“ 10小时XXXX”视频是一个很好的标识,确实,有些人只是想永远循环播放。
克里斯·西里菲斯

23
另一个问题:如果您的软件很流行,那么有人会遇到只在极少数情况下确实会发生的错误,然后将其发布到互联网上,突然,每个人和他们的狗都说:“该软件是垃圾,如果我为一天”。或者竞争对手使用它来演示崩溃应用程序有多么容易。
gnasher729

4
强调最后一段。您是否知道MacOS Classic如果连续32,768次“鼠标按下”事件而没有“鼠标释放”事件,它将崩溃?
2016年

79

Windows 95中存在类似的错误,导致49.7天后计算机崩溃。它只是在发布后的几年才被发现,因为很少有Win95系统能够保持这么长的时间。因此,有一个观点:错误可能与其他更重要的错误无关。

您要做的是对整个程序进行风险评估,并对单个错误进行影响评估

  • 该软件是否在安全边界上?
  • 如果是这样,此错误会导致漏洞利用吗?
  • 该软件对目标用户是否“至关重要”?(请参阅Java EULA禁止您将其用于的事物列表
  • 该错误会导致数据丢失吗?经济损失?名誉损失?
  • 该错误发生的可能性有多大?(您已将此包含在您的方案中)

等等。这会影响错误分类,即确定要修复的错误的过程。几乎所有运输软件都包含很长的小错误列表,这些小错误尚未被认为足够重要可以修复。


2
我还记得某些英特尔CPU中的(硬件)错误,其中特定的浮点值全部出错。

5
我相信您指的是@WilliamKappler en.wikipedia.org/wiki/Pentium_FDIV_bug。长达一年才有人注意到它。
尤特纳格

10
@ gnasher729-并非如此,他们已经处于最底层,并且仍在挖掘:)大多数人不得不比49.7天IIRC更频繁地重新安装Win 95。
mcottle '16

4
@Luaan该评论原意是对M $的轻松挖掘,因此第一句话后露出笑脸。他们以'95落后于八球,因为它在95年问世很晚(可能是因为1996年发布的Win95看起来很糟糕),半熟(还记得USB BSOD吗?)并且倾向于变得不稳定并需要定期重新安装因此,我的第二句话-从来没有提到过在Windows 95上运行服务器,我不知道您从哪里(闪回?)。第二张CD改善了问题,但是'95的最初发行令人困惑。
mcottle '16

5
TBH我认为是“ Windows for Warships”惨败造成了更大的声誉损失(archive.wired.com/science/discoveries/news/1998/07/13987),并且使用的是NT。当时的Unix机器即使使用(很早)的Linux版本也可以管理多年的正常运行时间。所有家用计算机也都具有较高的正常运行时间能力,尽管很少使用这种方式。在过时十年后,我看到BBC micros嵌入教育展览中。
pjc50

33

其他答案已经非常好,我知道您的示例只是一个示例,但是我想指出该过程的很大一部分尚未讨论:

您需要确定您的假设,然后针对极端情况测试这些假设。

查看您的示例,我有两个假设:

  • 递归方法最终将导致错误。
  • 没有人会看到此错误,因为视频播放时间过长,无法达到堆栈限制。

其他人讨论了第一个假设,但看看第二个假设:如果我的视频只有一秒钟的一小部分怎么办?

当然,也许这不是一个很常见的用例。但是您真的确定没有人会上传非常短的视频吗?您假设视频是最短的播放时间,您甚至可能没有意识到自己在假设什么!这个假设会在您应用程序的其他地方引起其他错误吗?

不确定的假设是错误的巨大来源。

就像我说的那样,我知道您的示例只是一个示例,但是此过程要确定您的假设(通常比听起来难得多),然后考虑这些假设的例外情况,这是决定在哪里花费时间的重要因素。

因此,如果您发现自己在思考“我永远不必为此而编程,因为它永远不会发生”,那么您应该花一些时间来认真研究一下这个假设。您会经常想到比您最初想的更常见的极端情况。

话虽如此,这在某种意义上是徒劳的。您可能并不在乎您的JavaScript应用程序是否可以在TI-89计算器上完美运行,因此在此上面花费任何时间都是浪费的。

其他答案已经涵盖了这一点,但是想出“这很重要”和“这是浪费时间”之间的界线并不是一门精确的科学,它取决于许多因素,这些因素可能与一个因素完全不同。个人或公司。

但是该过程的很大一部分是首先确定您的假设,然后尝试识别这些假设的例外情况。


非常好的凯文。请注意我对上面针对分析问题的选定答案的评论What's the worst thing that could happen?
OMY

这里的另一个假设是,不断增长的堆栈只有在达到溢出大小时才会导致问题。实际上,堆栈可能是该漏洞不断泄漏的正常资源。在每个iterat ^ H ^ H ^ H ^ H ^ H ^ H递归上,整个浏览器可能会变得越来越慢。
Alfe

OP从来没有说过这个问题是由堆栈增长引起的。这很容易由计数器例程中的错误引起(dec-> div / 0?)。2.如果问题堆栈溢出问题,那么此问题是否不应该发布在StackOverflow中?<边敲击!> ;-D
OMY

@OMY该评论针对谁?
凯文·沃克曼

13

我建议您阅读以下文章:

可靠性及其威胁:分类学

其中,它描述了程序中可能发生的各种类型的错误。您所描述的称为休眠故障,在本文中,其描述如下:

故障产生错误时处于活动状态,否则处于休眠状态。活动故障是a)先前处于休眠状态且已由计算过程或环境条件激活的内部故障,或b)外部故障。故障激活是将输入(激活模式)应用到导致休眠故障变为活动状态的组件。大多数内部故障在其休眠状态和活动状态之间循环

对此进行了描述,所有这些都归结为成本效益比。成本将包含三个参数:

  • 问题多久会出现一次?
  • 后果是什么?
  • 有多少困扰您个人?

前两个至关重要。如果某个漏洞会在蓝色的月亮中出现一次并且/或者没有人在乎,或者有一个完美的实用解决方案,那么您可以安全地将其记录为已知问题,并进行一些更具挑战性的工作重要任务。但是,如果该错误将导致某些金钱交易失败或中断漫长的注册过程,从而使最终用户感到沮丧,则您必须对此采取行动。我强烈建议不要使用第三个参数。用Vito Corleone的话来说:

这不是个人的。是生意

如果您是专业人士,则应抛开情绪,采取最佳行动。但是,如果您正在编写的应用程序是您的业余爱好,那么您会在情感上参与其中,并且在决定是否修复错误方面,第三个参数与任何参数一样有效。


``这不是个人的。我想这是迈克尔的事,不是维托。(您会惊讶于最终用户如何
突破

实际上,如果您读过这本书,那就是Vito。甚至在电影中,汤姆·哈根(Tom Hagen)都说,首先在与桑尼(Sonny)争论是否应该去床垫时,迈克尔才首先说出一句名言:“这不是私人的,桑尼(Sonny)。这完全是生意。 ”。但是哈根从维托那里学到了这一点。
弗拉基米尔·斯托基奇(Fladimir Stokic)

11

直到有人将您的播放器放到运行24/7公司演示文稿的大厅屏幕上的那一天,该错误才会被发现。因此,这仍然是一个错误。

你做什么的答案确实是一项业务决策,而不是一项工程决策:

  • 如果该错误仅影响您1%的用户,并且您的播放器缺乏对另外20%所需的功能的支持,那么选择是显而易见的。记录错误,然后继续。
  • 如果该错误修复程序在您的待办事项列表上,通常最好在开始添加新功能之前对其进行修复。您将获得零缺陷软件开发过程的好处,而且由于它始终在您的清单中,因此您不会浪费太多时间。

5

特别是在大公司(或大项目)中,有一种非常实用的方法来确定要做什么。

如果修复的成本大于修复所带来的回报,则保留该错误。反之亦然,如果修复程序返回的费用超过其成本,则修复该错误。

在您的示例场景中,这取决于您期望失去多少用户以及如果开发新功能而不是纠正该昂贵的错误,您将获得多少用户。


6
修复错误的ROI很少容易评估-您通常必须依靠自己的判断。
Ant P

该修复程序将带来的回报主要是声誉,几乎无法量化。如果我是唯一一个甚至知道可能存在错误的人,然后在一两年内我换工作,而新公司正在考虑将视频播放器嵌入其产品中(可能卖出数百万个),我建议使用这个?
杰里·耶利米

@JerryJeremiah如果该错误阻止业务流程运行,这与声誉无关,那取决于业务流程的重要性。而且在每种情况下,无论您是否适用于纠正错误的每条策略,都必须根据您的经验和知识进行主观评估。即使您知道将要遇到错误的确切用户数量,您仍然必须做出人为选择(而且ROI策略也可以包括错误命中统计信息,以估算成本)。到今天为止,没有机械的方法可以知道先验的完美方法。
JoulinRouge

5

tl; dr这就是为什么RESOLVED/WONTFIX。只是不要过度使用它-如果您不小心,技术债务可能会堆积。这是您设计的基本问题,将来可能会引起其他问题吗?然后修复它。除此以外?保留它直到它成为优先级(如果有的话)。


5

您描述的情况实际上存在三个错误:

  1. 缺乏评估所有记录的错误的过程(您确实将错误记录在故障单/积压/已安装的任何系统中,对吗?),以确定是否应该修复该错误。这是一项管理决定。

  2. 您的团队缺乏技能,导致使用诸如此类的错误解决方案。迫切需要解决此问题以避免将来出现问题。(从错误中学习。)

  3. 很长一段时间后,视频可能会停止显示的问题。

在这三个错误中,仅(3)个可能不需要修复。


感谢您指出二阶问题。太多的人只治疗症状,而病因继续导致更多的症状。
jaxter '16

4

这里有很多答案,讨论评估修正错误而不是留下错误的成本。它们都包含很好的建议,但是我想补充一点,就是错误的成本经常被低估,甚至可能被大大低估了。原因是现有的虫子混淆了继续开发和维护的范围。在测试您的软件以查找错误的过程中,使您的测试人员可以跟踪几个“无法修复”的错误,这会使他们的工作变慢并且更容易出错。一些不太可能影响最终用户的“不会修复”的错误仍然会使继续开发变慢,并且结果将是错误的。


2

我多年的编码中学到的一件事是,错误会再次出现。最终用户将始终发现它并进行报告。是否修复该错误仅是优先级和截止日期的问题。

我们遇到了一些重大错误(我认为是主要错误),因此决定不修复一个版本,而成为最终版本的停顿者,因为最终用户一遍又一遍地发现了它。反之亦然-我们被迫修复了一个没人使用的功能中的错误,但是便于管理人员查看。


2

这里有三件事:

原则

这是硬币的一面。从某种程度上说,我觉得这很好的坚持固定的错误(或坏的实现,即使他们“工作”),即使没有人注意到它。

这样看:在您的示例中,真正的问题不一定是bug,而是程序员首先认为以这种方式实现循环是一个好主意。从一开始就显而易见,这不是一个好的解决方案。现在有两种可能性:

  • 程序员只是没有注意到。好吧……程序员应该对自己的代码如何运行产生直觉。并不是说递归是一个非常困难的概念。通过修复该错误(并费力地完成所有其他工作),他可能会学到一些东西并记住该东西,即使只是为了避免将来进行其他工作。如果原因是他没有足够的时间,则管理层可能会得知程序员确实需要更多时间来创建更高质量的代码。

  • 程序员确实注意到了,但认为这“没问题”。如果放任不管,那么就会发展一种放任的文化,最终会导致真正伤害的错误。在这种情况下,谁在乎。但是,如果那个程序员下次要开发银行应用程序,并确定某个星座永远不会发生,该怎么办?然后就可以了。艰难时期。

实用主义

这是另一面。的过程中,你可能会在这种特殊情况下,不修正错误。但是要当心-有实用主义,然后有实用主义。如果您找到一个快速而又扎实,有充分根据的问题解决方案,那就是良好的实用主义。即,您避免过度设计内容,但是您实际实现的内容仍需要深思熟虑。实用主义很差,就是您只是一起破解某些东西,而这种方式“确实如此”,并且会在第一个机会时破裂。

快速失败,很难失败

如有疑问,请快速失败并努力失败。

这意味着,除其他外,这意味着您的代码注意到了错误情况,而不是环境。

在此示例中,您要做的至少是通过将其替换为您自己的硬异常,从而避免发生硬运行时错误(“超出堆栈深度”或类似的错误)。例如,您可以设置一个全局计数器,然后任意决定在1000个视频后(或任何数量足够高而在正常使用中不会出现,而数量又足以在大多数浏览器中运行)的情况下纾困。然后给该异常(可以是一个通用异常,例如RuntimeExceptionJava中的异常,或者JavaScript或Ruby中的简单字符串)有意义的消息。您不必全力以赴来创建新类型的异常或使用特定编程语言进行的任何操作。

这样,你有

  • ...记录了代码中的问题。
  • ...使其成为确定性问题。您知道您的例外情况将会发生。您不必担心基础浏览器技术的变化(不仅考虑PC浏览器,还考​​虑智能手机,平板电脑或未来技术)。
  • ...使得在您最终需要修复它时很容易对其进行修复。您的消息指出了问题的根源,您将获得有意义的回溯。
  • ...仍然浪费时间进行“真正的”错误处理(请记住,您永远都不会期望错误发生)。

我的约定是在此类错误消息前加上“ Paranoia:”一词。对于我和其他所有人来说,这是一个明确的信号,我从没想到会出现该错误。我可以清楚地将它们与“真实”异常分开。如果我在GUI或日志文件中看到类似的内容,那我肯定知道我有一个认真的问题-毕竟我从来没有想到它们会发生。在一点上,我进入了紧缩模式(有一个很好的机会来快速而轻松地解决它,因为我确切地知道了问题的出处,使我免于进行大量的虚假调试)。


2
很抱歉,如果您对我多久接受一次答复有这种看法。在我的辩护中,我只是不知道问题有超过10,000个视图,并且在接受时有这么多答案。无论如何,我仍然没有改变最佳答案的想法。
Tiago Marinho

@TiagoMarinho,没问题,此评论并非主要针对您本人,我没想到您会重新考虑。;)那些投票表决删除我的答案的动机使我更加沮丧。此外,在这里,对于没有给出任何评论的几个答案都颇有争议。不知道这是否是在SE的特定区域中完成的方式。
AnoE

我完全同意关于怪异downvoting
蒂亚戈马里尼奥

我不知道至少在这种情况下,这种治疗方法是否比治愈方法更好。如果您要决定是否对已经发现的设计缺陷进行特殊处理,则有必要比较一下a)实施错误处理的整个生命周期成本,并通过修复错误来对错误进行处理。设计,或b)首先将设计固定下来。
jaxter '16

@jaxter,完全是。因此,我的想法是打开一个错误修正的思路(即使看起来过分杀伤),但是当您决定不修正该错误时,至少要实现快速失败的方法。显然,如果快速故障解决方案首先比“真正的”错误修复程序昂贵,那么请避免使用它并进行真正的错误修复程序。
AnoE

1

我工作场所的高级开发人员桌上的一个便利贴说

有帮助吗?

我认为这通常是思考过程的良好起点。总会有很多东西需要修复和改进-但是您实际上增加了多少价值?...无论是在可用性,可靠性,可维护性,可读性,性能...还是任何其他方面。


0

我想到三件事:

首先,在以负责任的方式做出将错误保留在代码中的决定之前,需要彻底调查已识别错误的影响。(在您的示例中,我立即想到了不断增长的堆栈代表的内存泄漏,这可能会使您的浏览器在每次递归时变得越来越慢。)这种彻底的调查通常比修复错误要花费更长的时间,因此我更喜欢修复大多数情况下的错误。

其次,错误的影响力比起初想象的要大。我们都非常熟悉工作代码,因为这是“正常”情况。另一方面,错误是“例外”。当然,我们所有人都已经看到了许多错误,但是我们看到了总体上可以工作的方式。因此,我们对工作代码的行为比对错误代码的行为有更多的经验。有成千上万的关于工作代码及其在何种情况下将如何工作的书籍。关于错误代码的行为几乎没有。

原因很简单:错误不是有序的,而是混乱。他们通常会留下一些命令的痕迹(或者反之亦然:他们不会完全破坏命令),但是它们的错误本质是破坏了程序员想要的命令。混沌本身倾向于不正确估计。仅仅因为一个程序不再符合我们的思维模式,就很难说出一个有错误的程序比正确的程序要做什么。

第三,您的示例包含以下方面:修复错误意味着必须重新设计程序。(如果剥夺了这方面的内容,答案很简单:修复错误,因为不需要重新设计,它不会花太长时间。否则:)在这种情况下,我对程序的设计方式失去了信任。重新设计将是恢复这种信任的一种方式。

综上所述,程序是人们使用的东西,缺少功能或其他地方的第二个非常麻烦的错误可能比修复错误具有优先权。当然,然后采取务实的方式并先做其他事情。但是永远不要忘记,对错误影响的初步快速评估可能是完全错误的。


2
下投时请发表评论。我们应该知道什么是批评,以改善答案。
Alfe

0

低概率/轻度后果=低优先级修复

  • 如果发生的可能性很低
  • 如果发生的后果是轻微的
  • 该错误不会构成威胁,因此不是优先解决方案。

但这不能成为懒惰的开发人员的拐杖...

  • “甚低发生率”甚至是什么意思?
  • “轻微后果”甚至意味着什么?

要声明发生的可能性非常低且后果是轻微的,开发团队必须了解代码,使用模式和安全性。

令大多数开发人员感到惊讶的是,他们本来难以克服的事情将永远不会发生,实际上会发生很多

我们的教育系统不能很好地教授概率和逻辑。包括大多数软件工程师在内的大多数人都具有破碎的逻辑和破碎的直觉。我知道解决此问题的唯一方法是面对现实世界中的问题,以及进行广泛的模拟。

用真实世界的数据面对您的直觉

制作多个日志以遵循使用模式非常重要。用对您认为不应该发生的事情的断言填充代码。您会惊讶于它们的作用。这样,您将能够通过硬数据面对直觉并对其进行完善。

我的一个温和问题和控制措施的例子

在我很久以前工作的一个电子商务站点中,另一个程序员犯了一个错误:在某种模糊的情况下,系统从客户那里扣除的借方费用比日志中记录的少1美分。我发现该错误的原因是,我制作了报告以识别日志和帐户余额之间的差异,从而使会计系统更具弹性。我从未修复过此错误,因为差异很小。每天计算差额,每月少于2.00美元。碰巧我们正在开发一个全新的系统,一年之内就可以取代现有的系统。将资源从可能有利可图的项目中转移来修复每月花费2.00美元并受到适当控制措施的东西是没有道理的。

结论

是的,有些错误无需立即修复,其重要性不足以延迟新功能的开发。但是,由于我们不能相信自己的直觉,因此系统必须控制此错误的发生率,以确保它很小。


-1

我认为这从一开始就是在问一个错误的问题。

问题不是“我应该修复此错误还是应该不修复此错误”。任何开发人员都有有限的时间。因此,问题是“在一小时,四个小时或一周内我能做的最有用的事情”。

如果修复该错误是最有用的事情,因为它可以使大多数人最大程度地改善该软件,则可以修复该错误。如果您可以通过添加人们所缺少的功能或修复更重要的错误来在其他地方进行更大的改进,则可以执行其他操作。并为任何使您未来的开发更有效率的事情提供额外的奖励积分。


不确定功利性指标在这里是否最有效。显然,视频播放器示例的设计目的是降低影响力,但即使这样也不是万无一失的。一个回答者已经在大厅用例中引用了24/7促销循环,另一个回答者可能是一个运行一周的销售/技术会议的售货亭。两者都会花费业务代表和/或金钱,所以这是不平凡的。
jaxter '16

这意味着修复该错误所带来的好处比最初预期的要多,因此应将其优先级提高。因此,如果对最有用的东西的看法尽可能与现实一致,那么您将在生活中获得更大的成功。
gnasher729 '16

-2

缺陷修复始终是一个矫枉过正

让我们先对错误部分进行分类。

这是一个诚实的错误,例如一次性错误或无法通过测试的可变阴影吗?在这种情况下,我当然希望除了“解决”该问题之外,您还编写了新的单元测试,并借此机会重构了附近的代码,其中所有后者都是有用的工作

但是,如果实际上是您所遇到的设计缺陷,则应重新评估设计,或者在最坏的情况下,请禁用此功能。

因此,请不要尝试仅对其进行修复

当然,您可能会做得更糟---您可以尝试“ hack-up-on-hack”方法。视频循环是一种黑客行为(架构不良,并且有已知的损坏)。您可以添加一个循环限制,以便在N次迭代(您测试过的次数低于浏览器限制)之后,循环终止。

后果显而易见,现在您必须同时支持损坏的代码和新的循环限制。

PS对此表示歉意。

PPS有关术语的注释:您无法“修复”错误。兽医也许可以,但是我们不要去那里;-)。问题已解决或“修复”,而错误已删除或解决。


您是否真的要说这总是“过度杀伤”?我认为您可能在某处混淆了定义。过度杀伤意味着“超出要求的工作量”,换句话说,它比任何人都应该做的更多。您断言错误修复始终是最重要的事情,而同时劝告人们这是不够的工作,我们必须在此之上做更多的工作,这没有任何意义。
doppelgreener

@doppelgreener我知道那会令人困惑。错误修复是一个可怕的实践,绝不应该这样做。另一方面,使设计软件体系结构适应不断变化的需求是应该遵循的良好做法。假设做对了,也可以纠正诚实的错误。
Dima Tisnek '16

2
我不知道您在谈论哪种错误修复,但是在我的日常工作中,“更改体系结构”是一种错误修复方法。您可能需要定义在“错误修复”术语下收集的内容。
doppelgreener

@doppelgreener-在某些形式的质量管理中,“修复”一词具有特殊含义,许多编程管理人员都采用了专门的用法。“ 修复 ”仅是临时解决方案或解决方案,而真正的问题“ 解决方案 ”则需要识别和消除“ 根本原因 ”。在软件中的错误可以像一个放错位置逗号,其中(修正逗号)修复一样简单IS的解决方案,但如果错误是那么更大的东西造成的修复(例如:循环限制器)将不会是相同的解决方案(重新设计/重写)。
OMY

2
@OMY谢谢您的解释。我觉得既然的“修复”这样一个定义没有被使用的问题,答案应该到这个词的意义作出回应使用。
doppelgreener
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.