学习调查错误[关闭]


11

我什至不知道如何定义这个困难。这让我想起了几位准员工在我找到工作之前对我进行的测试。他们会在房间里拿一个物体,然后允许我提出问题以帮助自己确定该物体是什么(很像20个问题)。我非常擅长此事(不,我从来没有因为谦卑而获得高分),所以我以为我会非常擅长解决错误...

但是这是我最近发现的东西。在那种情况下,我真的很擅长,因为很容易看到房间里的所有东西,因此我可以用一些组成部分的概念来解决我的问题。本质上,我“知道我不知道的事”。但是在编程时,我遇到了很多情况,而这个问题对我来说是完全未知的。我知道它已损坏,但是我不知道它可能如何损坏。我遵循了所有说明,我对这项技术相当了解...

老实说,我觉得我很难想象可能出错的事情,因此我可以对其进行测试,并希望找到解决方案。

我该如何发展这项技能?我需要做些什么来帮助我有限的想象力提出可能破坏我的项目的方式?是否有一些练习(也许令人困惑?)可以使我对此有所改善?我知道最大的治愈方法可能只是经验...但是,我希望能帮助加快这一过程。一次呆呆地盯着我的电脑屏幕看几个小时甚至都不是一件有趣的事...


3
想象一下您认为它可能如何工作,并从输出到输入反向工作以找到调查的路径
Steven A. Lowe 2014年

1
我将扔一个链接- 如何成为程序员 -列出的第一项技能是“学习调试”。

1
我想扔掉一些关于“开箱即用”思维的东西。关于错误,我经常认为要做的第一件事就是简单列出所有交互的系统,然后假设其中的任何部分都可能出错,直到被证明没有问题为止。然后您的工作就变得容易了:假设组件出现故障,并找到一种方法,即使一开始看起来似乎不合逻辑(例如“输出已损坏”,等等)。然后从最直接的交互开始,证明您的组件没有故障。事实上,这看起来像是想象,但通常只是从悲观的观点开始。
J特拉纳2014年

在每行代码下编写一个printfprintln或任何您要使用的代码,以确保100%一切正常,如您所愿。然后运行您的控制台应用程序,App > out.txt然后是查看大文件的困难部分。.有时我的日志文件超过了几百万行,这可能需要一些时间哈哈。当然正确的方法是使用调试器和断点,但是有时是不可能的。
SSpoke

1
阅读皮尔西格的禅宗和摩托车维修艺术 amazon.com/Zen-Art-Motorcycle-Maintenance-Inquiry/dp/0060589469
Jeffrey Kemp

Answers:


11

软件中的每个缺陷最终都归因于假设与现实之间的差异。阴险的错误仅仅是根深蒂固的假设与现实之间的差异。诊断错误的能力取决于您质疑自己的假设的能力,这确实需要意识到您不知道某些事情,您只是假设它们并且一直使用到现在。

显然,交易工具,日志文件,调试器等有助于发现此类假设并使世界模型与实际系统重新匹配。但是,直到您准备质疑关键的假设,例如“因为我们有全面的输入检查,这不会是糟糕的输入”,您才会花整个时间检查系统的错误部分,或者只是不知道其他地方首先。


3
我不愿意说这句话,但我想你已经打定主意了。我为在此期间所获得的系统的“知识”而感到非常自豪,并且我认为我对错误的想法持坚决的态度。正如我可能提到的那样,我从未在谦卑方面得分很高。遵循您的建议来挑战自己的假设,实际上使我在自己的代码中遇到的几个问题上取得了一些稳固的进步。所以,谢谢,我会牢记这一点。
杰伊·卡尔

2
@JayCarr:“在精神上抵制错误观念 ”-如果您尝试将错误视为学习的源泉而不是错误,该怎么办?只要您不止于此,做错就没有错。
JensG 2014年

14

我需要做些什么来帮助我有限的想象力提出可能破坏我的项目的方式?

在大多数情况下,我绝对不会说什么。您不应该尝试幻想可能导致程序中断的事情。你应该确定系统什么导致其破裂。

您应该使用以下信息进入调试过程:

  • 为产生错误而采取的步骤和输入的值;
  • 在给出这些步骤和输入后,程序该做什么?
  • 在给出这些步骤和输入后,程序做什么。

如果有错误消息,请获取有关它的所有信息。如果错误消息本身不清楚,并且您在实践中不知道它的含义(某些错误消息并不总是特别有用),请使用Google或StackOverflow或任何其他在线资源来查找有关此错误的信息。

如果前端未显示错误消息,请在重现该错误的时间段内检查应用程序写入的所有日志中是否有错误消息。该代码可能已经执行完毕,但是遇到了一个正在处理的异常,该异常会丢弃最终结果并在日志中产生一个条目。查找这些内容,执行上面的相同操作,并确切说明它们的含义。

如果有堆栈跟踪提供了代码抛出的异常(应该存在),请查看提到的代码行。这条线本身可能不是真正引起问题的那条线。如果您在一段Java代码中得到了NullPointerException,则stacktrace会告诉您您在哪里尝试使用了null值(如果您不希望这样做)。那并不能完全指出导致问题的那一行,但是它通常会告诉您什么变量没有您期望的值,因此您可以查看对该变量的任何引用/赋值以确定该值未设置或值设置不正确。

如果没有帮助,请启动调试器。如果您将其范围缩小到您知道导致问题的代码部分-但您不确切知道哪一行,那么请逐步解决。如果没有,则只需遍历整个过程。在这里,您需要确切地知道程序在给定输入下应该执行的操作,因为您需要查看每一行之后的每个值,并确切确定其与期望值的偏离位置。

仍然不知道问题出在哪里吗?向某人寻求帮助。同事,朋友,在线社区。向他们展示您刚才所做的所有工作。向他们显示错误消息,堆栈跟踪,解释程序的一般含义(如果他们还不知道),在此特定实例中应该做什么(例如返回值4),实际在做什么(例如返回值5)。如果您已将其缩小到调试器中的几行代码,请说“我知道问题是由代码中的这些行引起的,当它应为Y时将其值设置为X,但我看不到为什么会这样”。

花几个小时呆呆地盯着屏幕看绝对不是一件有趣的事,但是没有理由您应该这样做。如果您的代码有问题,那么您需要阅读或单步执行代码。


可能很快就判断了这个答案,当我阅读它时感到有些沮丧。合理的建议。我认为Killians的评论更能说明我的问题的核心。这是不是所选答案的唯一原因。
杰·卡尔

4

在某种程度上,这就像调查刑事案件或令人费解的难题。

首先,你是受害者。在调查了一段时间之后,您确定了一些嫌疑人,并且还提出了一个工作假设,即受害者可能是如何被谋杀的。您将继续进行调查,寻找更多有用的信息,使您离问题的真正根源越来越近。

有时您会走入死胡同(双关语)。这是其中的一部分,只要您设法使自己尽快回到正轨,就没有任何问题。关键是,始终考虑下一步需要什么信息,这些信息要么提供您的假设(并为您提供更多信息),要么证明它是错误的。然后找到一种有效获取信息的方法,做出结论并继续前进,直到最终能够定罪。

有时您会意识到,发现罪魁祸首的所有事实和迹象已经在半小时前摆在您面前。尽管很烦人,但这却是最有趣的部分,因为如果您对自己的行为和错误进行严格的审查,则您可能能够学习并变得更好。问自己一些问题,例如:

  • 我如何避免浪费时间?
  • 首先我忽略了什么,为什么?
  • 我要依靠哪些未经验证的和/或错误的假设?

这将训练您的能力。它还会发展您的直觉,因此随着时间的流逝,您将学会自动注意到所有那些容易被忽视的小事,从而使您更快地找到正确的答案。最后,所有这些都与刻意练习有关

最后但并非最不重要的是,永远记住福尔摩斯教给我们的是什么:当您消除了不可能的事情之后,无论多么不可能的事情,剩下的都是事实。


3

我需要做些什么来帮助我有限的想象力提出可能破坏我的项目的方式?

让历史为指南。如果您的项目得到了很好的管理,那么您应该拥有一个数据库,其中包含产品中曾经修复每个错误,以及对如何发现错误,如何重现错误,如何对其进行分析以及如何对其进行修复的分析。那不是只写数据库。阅读数据库,您很快就会发现错误分类法。

这样可以很好地概述产品中发生的各种错误。如果您对各种软件的问题有更普遍的兴趣,尤其是对影响安全性的缺陷有特别的兴趣,我建议您阅读CWE列表:http : //cwe.mitre.org/data/index.html


2

因此,我相信您不是在尝试重现和修复特定的缺陷,而是在考虑思考可以用于调查产品的新测试,以查看产品在这种情况下是否可以工作,例如:如果我在我们的产品中输入特殊字符,会发生什么情况注册页面的密码字段,或者如果我在将程序写入数据库时​​强行关闭该程序会发生什么情况。这些情况确实很难考虑。

在过去的10年中,软件开发(敏捷/ XP / TDD等)已达到仅满足显式要求的价值,然后宣布功能已完成,而不是找到破坏某件事的所有可能方法(可能存在例外,如果您在NASA工作或做白帽安全工作,但即便如此,还是有必要在用户故事的接受标准中明确指出此类情况)。

因此,如果您的功能明确列出了系统需要做什么,例如如何处理输入,其性能特征,用户工作流程操作等,作为接受标准,那么您将获得需要检查的测试的完整列表。应该进行测试以验证是否满足要求,而做到这一点的最佳方法是明确列出所有要求。看看敏捷测试象限

有人主张将这些测试作为要求的明确声明,这些要求必须在代码之前编写,即测试优先(或测试驱动开发)。

但是,我很欣赏您听起来好像并没有在考虑一个新项目,在该项目中您可以在开始之前设置自己的最佳开发实践,而在编写软件并被要求对其进行“测试”之后才进入。这确实更具挑战性,但应用相同的原理,只有在知道它应该做什么之后才能对其进行测试。如果开发团队没有一个完整的需求列表可以满足您的需求,那么提出问题是最好的方法。取决于您的团队,这可能需要做一些微妙的事情,因为在构建软件系统之前没有明确列出要求的人不希望被提醒他们错过了什么,但是对很好地执行此任务至关重要。

一旦找到需求-它必须是稳健的/必须是安全的,然后尝试更深入地研究并确定它必须多么安全,或者可接受多少失败,总会有一个限制,没有多少人拥有NSA证明安全级别是其应用程序的要求,还是需要为此付费。您挖掘的越多,就应该明确要防御或易于使用的安全攻击类型。然后,在安全性,设计,性能等方面,一些领域知识将非常有用。在这里,您可以向团队中或SE或google / books上的专家询问更多问题。


并不是我一直想回答的问题,但是出色的评论仍然如此。我赞成你,这是非常有用的评论。
杰伊·卡尔
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.