不要被错误所蒙蔽
虽然今天是愚人节,但我并不想恶作剧。相反,我想借着这个节日的气氛,写写那些常常让我们觉得自己像个傻瓜的事情——代码错误!每个人都有自己调试代码的方法。不过,我认为开发新项目最难的部分之一就是建立自己的调试方法。以下是我在查找不熟悉的代码库中的错误根源时,会尝试遵循的操作步骤。
编译时还是运行时?
在深入探讨调试之前,有必要先讨论一下你可能会遇到的两种错误类型。由于调试的目标是找到错误的根源,请记住,在开发过程中有两个不同的节点可能会触发错误。
编译时间
编译时错误会被及早发现。它们通常是语法错误或文件未找到错误等等。如果是强类型语言,则可能是类型不匹配错误。
error There was a problem parsing "/Users/laurie/Personal/practice/src/pages/index.js"; any GraphQL fragments or queries in this file were not processed.
This may indicate a syntax error in the code, or it may be a file type that Gatsby does not know how to parse.
ERROR Failed to compile with 1 errors 12:39:25 PM
error in ./src/pages/index.js
Syntax Error: SyntaxError: /Users/laurie/Personal/practice/src/pages/index.js: Unterminated regular expression (14:30)
12 | {node.title}
13 | <ul>
> 14 | <li>{node.year</li>
| ^
15 | <li>
16 | {"Characters"}
17 | <ul>
这是一个我因为漏掉一个括号而触发的语法错误示例。
您可以等到尝试构建项目时再查看编译时错误。但是,使用带有语法高亮功能的集成开发环境 (IDE) 或其他文本编辑器通常会在您编写代码时就发现编译时错误。尝试运行代码检查工具 (linter),并在您的 IDE 中查找专注于您所用语言的插件。所有这些都可以帮助您在触发相关错误之前发现问题。
运行时
运行时错误是指代码在实际运行时遇到的问题所导致的错误。这通常是我们程序员会想到的错误类型。
Objects are not valid as a React child (found: object with keys {allMarvelYaml}). If you meant to render a collection of children, use an array instead.
in div (at pages/index.js:8)
in main (created by Context.Consumer)
in div (created by Context.Consumer)
in StaticQuery (created by Layout)
in Layout (at pages/index.js:7)
这是我在 React 中触发的一个错误示例。
本文的大部分内容将集中于找出运行时错误的根本原因。
错误消息和堆栈跟踪
运行时错误的第一个线索通常是错误信息和冗长的堆栈跟踪信息的组合。这段文本可能出现在浏览器控制台、终端、IDE、日志中,选择非常多!首要挑战是找到它。
提示:查找运行代码的命令来源。
完成上述步骤后,错误信息和堆栈跟踪的内容就成了有用的资源。请记住,有时这些机器响应中最有用的部分是隐藏的。不要只看那些易于理解的信息,往下翻几行,看看有没有什么有用的信息?
你要寻找任何你能识别的信息,或者能帮助你将其与自身代码对应起来的信息。包含变量名或行号会很有帮助。如果你没看到这些信息,而且你一开始也看不懂错误信息的意思,那也没关系。
Objects are not valid as a React child (found: object with keys {allMarvelYaml}). If you meant to render a collection of children, use an array instead.
in div (at pages/index.js:8)
in main (created by Context.Consumer)
in div (created by Context.Consumer)
in StaticQuery (created by Layout)
in Layout (at pages/index.js:7)
还记得我上面提到的错误信息吗?它指出错误来自 index.js 文件的第 8 行,这一点非常有用。在这个例子中,它指出我不能使用对象,而必须使用字符串或其他基本类型。
另一点需要注意的是,错误信息可能只是代码的后果。堆栈跟踪中提到的具体信息可能并不能真正指出问题的根本原因。这就是为什么触发错误如此难以修复的原因!
这个错误直接显示了源代码!不幸的是,这段源代码并非我们编写的,而是我们触发的底层框架代码的一部分。
是时候拿出谷歌机器了。
不幸的是,错误信息往往含糊不清,或者堆栈跟踪过于深,以至于我们无法确定是代码的哪一部分出了问题。这时,你就需要借鉴前人的经验了。
程序员日常工作中大约有 75% 的时间都在搜索错误。我开玩笑的,但感觉确实如此。熟练使用谷歌是一项实实在在的技能,它对你的效率有着巨大的影响。当你搜索特定错误的解决方法时,有几点需要注意。
-
复制错误信息时,请尽量简洁,并且只使用底层代码中提供的关键词。您的目标是尽可能多地收集答案,因此使用您代码中的变量名会导致与其他遇到此错误的人的答案不匹配。
-
明确技术细节。如果您知道是程序的哪一层触发了此错误(例如JavaScript 或 React),请将其添加到 Google 搜索关键词中。通常,相同的错误可能由不同的技术触发,这样可以排除一些搜索结果。
使用谷歌搜索时,你使用的具体关键词很重要!
请记住,即使你找到了遇到同样错误的人以及他们的解决方法(这种情况并非总是存在),你也未必能完全理解,这完全没问题。新手程序员(甚至是刚接触这项技术的程序员)可能很难理解这些回复帖中的答案。如果对问题的背景没有更深入的了解,就很难理解那些技术术语。但请相信,随着时间的推移,你会逐渐掌握这些术语,而且你仍然可以通过其他方法找到解决方案。
事实上,如果你想看看自己进步了多少,不妨回头看看一个月前你还看不懂的谷歌搜索结果。我敢打赌,现在你肯定能看懂了!
返回代码
以上调试步骤并非强制性的。有时,尤其是在学习阶段,从代码入手会很有帮助。无论你是否已经尝试过上述步骤,查看代码都是找出错误根源的最佳方法。
首先查看你最近添加的代码行。如果你采用迭代开发并经常测试的方式,这将更容易。因为在添加最后两三行代码之前,你的项目是可以正常运行的,所以更容易找出潜在的问题所在。
如果你不幸地编写了大量未经测试的代码,可以尝试暂时搁置你的更改,或者反向操作。目标是找到导致问题的代码片段,然后集中精力修复它。注释掉一些代码也是隔离问题代码的另一种方法,这样就不会删除你计划稍后添加回去的进度。
调试器是你的好朋友……断点也是。
尝试在代码运行时单步执行。变量是否被赋值为你预期的值?操作顺序是否符合预期?
有多种方法可以实现这一点。如果您运行的是 JavaScript,可以使用开发者工具在浏览器中设置断点。如果您在集成开发环境 (IDE) 中直接运行代码,则可以在 IDE 中设置断点。
根据项目的不同,打印出变量的结果或者代码执行到某个特定点可能更容易。
getResults(searchString: string): void {
this.githubSearchService.getUsers(searchString) // pull results
.subscribe(result => {
this.result = result;
console.log("I AM HERE!")
if (this.result) {
this.items = this.result.items;
}
});
}
控制台日志记录或打印语句都是调试代码的有效方法。
还是不行?
记住,你随时可以寻求帮助!提问时,提供尽可能多的信息非常重要,例如使用的技术、版本号、错误信息和堆栈跟踪等等。如果你能将代码部署到像 jsfiddle 这样的公共环境中运行,那就更好了!
调试是一项技能,解决错误可能非常耗时且令人沮丧。然而,一旦你找到了问题所在,它也是这份工作中最有成就感的部分之一!
文章来源:https://dev.to/laurieontech/don-t-get-fooled-by-errors-314c

