paint-brush
如何成为专业调试器经过@pragativerma
1,514 讀數
1,514 讀數

如何成为专业调试器

经过 Pragati Verma8m2022/09/18
Read on Terminal Reader
Read this story w/o Javascript

太長; 讀書

调试不是在职业生涯的任何阶段教给任何人的东西,这导致人们认为调试非常困难。尽管对于开发人员来说是一项必要的技能,但作为新手很难理解从哪里开始。这是一门艺术,可以通过随着时间的推移创建和审查越来越多的代码来获得,但直觉可以通过一些我们今天将在本文中讨论的建议来培养。在描述重现问题的步骤时,请遵循以下一些简单提示: 尽量具体,因为您提到的概率越多,打开的调查途径就越多。

Company Mentioned

Mention Thumbnail
featured image - 如何成为专业调试器
Pragati Verma HackerNoon profile picture
0-item
1-item


作为一名开发人员意味着你有一半以上的时间必须是一名调试员,有时是为了你自己的代码,有时是为了帮助你的同行进行代码审查或结对编程。尽管对于开发人员来说是一项必要的技能,但调试并不是在职业生涯的任何阶段都教给任何人的东西,这导致人们认为调试非常困难。


调试看起来很困难,不是因为它的机制,而是因为作为新手很难理解从哪里开始。毫无疑问,这是一门艺术,可以通过随着时间的推移创建和审查越来越多的代码来获得,但是直觉可以通过一些我们今天将在本文中讨论的建议来培养。


让我们开始吧。


重现问题

调试任何问题时最糟糕的情况是无法可靠地重现错误。这可能是由于竞争条件、外部系统或环境问题等多种因素导致已部署系统或开发人员阶段框上的不同行为模式而发生的。


这归结于测试人员和开发人员,您在重现错误的方式上越具体越好。此外,一旦你发现了问题和演示它的方法,请确保将有关重现它以及理解和解决它的所有细节都放在错误跟踪系统上。这不仅可以帮助您验证实施后的修复,还可以帮助其他开发人员了解错误的原因和解决方案。


在描述重现问题的步骤时,请遵循以下一些简单提示:

  • 尽量具体一点,因为你提到的概率越多,调查的途径就越多。
  • 如果需要输入,请始终包含一些示例或示例值。此外,请提及为用户输入指定的约束或规则,因为这可能是问题的可能原因,值得检查。
  • 始终指定环境详细信息 - 操作系统、浏览器类型和浏览器版本。对于不同浏览器可以描述不同行为的 Web 应用程序来说尤其如此。
  • 务必包含相关的崩溃报告、日志、带注释的屏幕截图等,以正确解释您期望应用程序的行为方式与其实际行为方式之间的差异,以免给调试器造成误解。


将问题转换为自动化测试

这一步并不总是可行的。有时这是可能的,但不切实际或真正必要,但是,在某些情况下可能值得实施。在这种情况下,自动化测试可以是您的开发用例已经用于测试的任何东西,例如单元测试或集成测试。在可能的情况下,单元测试是一个很好的选择,因为它们被设计为经常执行,所以你会知道问题是否很快就会出现。


您可能会发现自己编写了许多单元测试,这些测试在试图确定问题的根源时会通过。您可能偶尔也会发现自己编写的单元测试在当前情况之外毫无意义,但即便如此,拥有一个可以帮助您指出问题根源的测试也没有什么坏处。仅仅因为它不是当前的问题并不意味着它以后不会找到问题 - 它还可以作为代码应该如何表现的更多文档。工作单元测试通常是确定系统内哪个层产生问题的绝佳方法。


以与您的生产代码相同的活力重构您的单元测试。如果您有一个巨大的单元测试实际上正在测试一段重要的代码,请尝试将其拆分为更小的测试。如果幸运的话,您会发现基于原始问题的巨大失败单元测试可能会分解为多个通过测试和一个较小的失败测试。


即使您很早就发现了一个问题并且可以在一行中解决它,也要尽可能构建一个单元测试来验证它。纠正代码时出错就像最初开发代码一样简单,并且测试优先的原则仍然适用。


不要期望事情会像他们应该的那样工作

如果您正在调试任何问题以使自己清楚地知道某处没有按预期工作,那么您必须有点偏执,否则不会有任何问题。您需要对问题所在的位置保持开放的态度,并根据您对所涉及系统的了解进行导航。


这里的主要目标是阻止您声称“问题不存在”。不信就证明。如果它看起来是,无论它看起来多么不可能,都要深入挖掘它。


清楚代码的用途

如果您不清楚任何一段代码的用途,无论它是否是问题的原因,请花一些时间来理解它。您总是可以围绕它进行一些测试,并尝试记录它的作用。如果您不确定行为是否正确,请寻求帮助。一旦清楚,试着记录你所知道的一切,无论是使用测试、XML 文档还是一些外部文档。


一次解决一个问题

如果一段代码异常糟糕,您最终可能会在调试原始代码时发现其他问题。在这种情况下,决定首先要解决哪个问题,然后只关注该问题是至关重要的。


在一个完美的世界中,您将解决一个问题,将您的代码验证到版本控制中,然后修复下一个问题,依此类推。这使得确定代码中的哪些更改会导致以后的哪些行为更改变得简单,当一个问题的修复结果证明会破坏其他问题时,这一点至关重要。


让你的代码帮你调试

日志在调试中非常有用。他们可以从调试器可能没有帮助的地方为您提供信息。然而,日志记录,就像调试一样,也是一门细心的艺术。如果您没有正确执行此操作,它可能无法以最佳方式为您提供帮助。因此,无论何时在代码中引发异常,都应注意不仅要记录异常消息,还要记录堆栈跟踪。


基本上不应该在没有记录的情况下默默地吞下异常。它们有时是验证用户输入或配置设置的最简单方法。在这些情况下,日志记录可以成为您真正的朋友。


同样,使您的代码能够抵抗错误的输入。越早检测到错误输入,就越容易发现问题。如果仅在通过多种方法处理了一个值后才获得期望,则可能很难追查问题的根源。合同可能有助于在此处定义约束,否则,如果您怀疑将来出现问题,您应该保持警惕并添加验证。


了解您的调试器

就像绝地武士没有他的光剑就无法成为伟大的人一样,如果不了解调试器的能力,您也无法成为伟大的开发人员。现代调试器有很多特性,这些特性大多没有被充分利用,因为开发人员没有意识到它们。例如,条件断点或用户定义的数据结构表示可以在持续一整天的调试会话或仅持续 10 分钟的调试会话之间产生差异。


您不需要背诵所有内容,但对调试器的能力有一个不错的了解,并且对涉及基本功能(如单步执行、单步执行、设置断点和恢复执行)所涉及的快捷键有很好的了解很重要.


让人民参与

调试很困难,因为它可能会让人士气低落,并且使用文档记录不佳的迷宫代码会很快导致身体疲惫。考虑一下:如果你被困住了,休息一下,出去散散步,喝杯咖啡,吃一块巧克力——任何对你有帮助的东西。


如果您需要包含其他人,请不要感到尴尬 - 如果代码的行为看起来不合理,或者您只是不知道在哪里查看,请询问。密切关注对方在做什么,既可以向他们学习,也可以在他们似乎正进入您之前观察到的死胡同时警告他们。让他们知道您观察到了什么,以及您的想法,讨论可能会带来提示。


测试到最后

当你认为你已经解决了问题时,尽你所能去测试它(在合理的范围内)。显然,单元测试应该是您的第一个呼叫端口 - 您引入的用于隔离问题的单元测试现在应该通过,但所有其他测试也应该通过。


一个高层次的问题经常是由许多低层次的问题引起的——很容易发现第一个低层次的问题,纠正它,然后假设高层次的问题会消失。有时会发生相反的情况:高级行为由于更重要的低级问题而恶化。在这种情况下,您将需要继续修复然后进行测试,直到您看到一切正常。


审计潜在错误

问题经常发生在群体中。例如,如果您发现有人在一个实例中忘记对用户输入进行足够的转义/编码,那么在另一个实例中可能会出现相同的问题。一次对可能的问题进行快速审核要比将每个问题作为一个单独的问题提出来要便宜得多,可能涉及其他工程师进行您刚刚完成的相同调查。


以类似的方式考虑补丁的后果。它会在其他地方引起短期内可能无法解决的问题吗?会对打补丁或升级有影响吗?在您的产品生命周期的这个阶段,这是一次重大维修吗?找出问题所在通常总是值得的,但有时让代码被破坏更安全——可能使用“创可贴”修复来解决症状而不是原因——并将完全治愈留给下一个版本。这并不意味着您应该保留错误报告。


如果您有修复建议,请尝试创建一个补丁文件并将其添加到错误报告中(当然,要明确哪些文件的哪些版本需要补丁)。至少,在错误报告中提供你的研究的详细解释,以避免以后浪费时间。 “解决下一个版本”(或任何您的等价物)的错误状态应该表明这一点,而不是“我们不太可能真正解决这个问题,但我们会一次推迟一个版本。”


结论

这些建议不能在一两天内使您成为专业调试器,但如果遵循耐心和良好实践,它肯定会帮助您朝着正确的方向开始。高质量的代码不是偶然发生的——它需要耐心和精确。


这就是本文的全部内容。让我知道您对上述调试技巧的看法,并随时在下面的评论中添加您成为专业调试器的方法、提示和技巧。


继续阅读!