速来报名!AICon北京站鸿蒙专场~ 了解详情
写点什么

神奇的调试艺术

  • 2020-03-30
  • 本文字数:4004 字

    阅读完需:约 13 分钟

神奇的调试艺术

真正精通调试技巧的人是非常少的,这是我在多年企业系统管理的工作经验中所了解。如果说调试很简单并且有很多的人都在做,而且每个人都能够找到错误。然而现实情况是,大多数商店都有一个被称为“灭虫者”的“亲密接触者”,被请来寻找其他无法追踪的错误。我曾担任过产品经理和咨询经理,在任职期间,我们工作内容很大一部分都应付查找这些让人讨厌的 Bug 🐜 并对其进行修复。


我相信故障的排除是可以被传授,学习和掌握的技能。不幸的是,太多的人专注于工具和开发语言功能,而不是一个除去语言,平台或工具后,如何都会起作用的思维框架。有兴趣了解动态解决代码的秘密吗?请继续阅读!


我从事 Bug 修复已有几十年了。我发表的第一篇专题文章其中之一就是一篇名为“ The Exterminator’s Code”的故障排除文章,该文章在 1999 年的《 News / 400》杂志上刊登。我发现有效的 Bug 搜寻涉及多种技能。仅仅了解技术还不够。高效是有方法的。一些过程步骤是能够被学习,而且随着您在职业生涯中遇到更多系统,经验会不断增加。


总是令我惊讶的是,善于发现缺陷的人与那些不善发现缺陷的人之间的差距。您可能认为这将是一个连续的技能,但是我发现人们有些得到,有些没有得到。那些得到这些技术的人做事非常速度,且始终如一。那这些秘密是什么?

测试你的眼睛 👀

帮我个忙,做个小测验。阅读下面的文字,快速计算段落中“F”的数量。


Finished files are the result of years of scientific study combined with the experience of years.


我一会儿再回答这个问题。如果我把它放在那太容易了。记下您的想法,然后再进行一些更深入讨论。这是另一套方法,请相信我,这一切都可以解决。您准备好参加另一场比赛了吗?


我希望您观看一段很短的视频。该视频有一些说明。只要让它播放一次即可。不要试图暂停或快进。这是链接或者您可以按下面的视频播放。继续观看,然后写下分数(您会明白的)。


到目前为止,我希望您开始明白我的想法,这是掌握调试技术的第一步。以我的经验,大多数开发人员调试代码的方式不对。当他们按下 F5 键并开始单步执行程序时,他们并没有注意到发生了什么事情。


什么?我在开玩笑吗?他们设置了断点。有监视窗口。他们尽职尽责地敲击 F10 和 F11 以进入和退出子程序。我什么意思?这是正问题所在:


他们正在等待程序执行他们期望的结果。而且并不难不,尤其是当您是编写程序的人时!因此当您逐步执行该代码块时,“是的,是的,我只是在这里初始化一些变量”然后快速按 F10 键,那您就错过了它,因为一个字符串文字拼写错误或引用了错误的常量。


“ F”测验的答案是 6。大多数人算出是 3,是因为他们在脑海中念出单词并聆听“ F”音,而不仅仅是看字母。这就是人们在凭着他感觉在调试时程序,而不是观察程序的真正运行。

认真:训练你的眼睛👁👁

你看到大猩猩了吗?大多数人不会第一次。因为他们是按照指示行事的。他们正在数通行证,这正是演习的目的。但是你能相信当你看到它并且知道你在寻找什么时它是多么明显吗?你怎么会错过这样的事情?


希望到现在为止,我们已经确定你的大脑有一个很好的过滤器,并将尝试给你你想要的。所以,当你带着期望逐步完成代码时,你猜怎么着?你会看到调试器做了你期望的事情,而忽略了可能导致错误的真正发生的事情。

但要怎么做呢?¯*(ツ)*/¯

有几件事你可以做,以帮助磨练你的调试技能,我鼓励你尝试所有这些。


请其他人调试您的代码,并提供调试他们的代码。了解如何查看代码并了解它在做什么的最好方法是逐步浏览您不熟悉的代码。一开始它可能看起来很乏味,但它是一种纪律和技能,可以帮助您学习如何以正确的方式遍历代码,而不做任何假设。


尽量不要把代码当作块。换言之,当你有一个初始化变量的例程时,不要把它当作“初始化块”来单步执行,而要考虑每个语句。不要把这些语句看作句子,而是回到编程的根上,在等号的左边看到一组符号,在等号的右边看到一组符号。你会惊奇地发现这能帮助你快速适应错误或重复的作业。在 MVVM 中很常见,例如,对于开发人员来说,剪切粘贴并最终生成如下代码:


private string _lastName; private string _firstName; 
public string FirstName { get { return _firstName; } set { _firstName = value; RaisePropertyChanged(()=>FirstName); }}
public string LastName { get { return _firstName; } set { _lastName = value; RaisePropertyChanged(()=>LastName); }}
复制代码


你发现 BUG 了吗?如果没有,花点时间你会找到的。但当你编写的代码是这样的时候,这个就显得要困难得多了,因为你希望它“正常工作”。

回归基本 🔎

有了这些精美工具可以告诉我们如何重构代码和扫描类,有时我们忘记了必要进行故障排除的基本工具。


我正在参与一个客户的一起对内存泄漏问题进行故障排除,发现自己开始于庞大的依赖关系,句柄和实例图。我可以看到某些对象被创建了太多次,但是看一下代码,它看起来就正确了。其他东西从哪里来?


所以,我回到了根本。我在构造函数中放入了一条调试语句,然后再次运行它。突然,我意识到有些实例正在如实地报告自己,而另一些则没有。这到底是怎么回事? …该类是从基类派生的。因此,我在基类中放置了另一个调试语句。果然,它也被实例化了。快速转储调用堆栈并解决了问题……不是通过图表和重构工具,而是良好的老侦探工作。

不要相信文档🔐

我从早年学到的一个教训是不要相信文档。我正在写一本关于正在开发的新框架的书。该文档稀疏,多变,并且经常出错错误。在一个特定的部分中,我正在写某些应用程序应该如何工作。该文档非常具体地说明了如何将工作划分为多个线程。我的导师说:“不要相信它”,并鼓励我去调试。在逐步检查代码并观察实际发生的情况并不是预期的发生结果,我了解到架构是非常不同的。我能够帮助修复文档,并帮助开发人员避免不必要的代码开销。


我经常做一些小型项目来学习语言和平台。例如,考虑以下 JavaScript:


const doSomething = (payload, fn) => { fn(payload); };
doSomething('This should echo', console.log);
let text = 'Some text'; doSomething(text, text => text += ' appended to.');console.log(`The text after the call: ${text}`);
let textPayload = { text }; doSomething(textPayload, payload => payload.text += ' appended to.');console.log(`The text after the payload call: ${textPayload.text}`);
复制代码


您可以预测控制台的输出内容吗?您可以通过运行jsFiddle来验证您的答案。


这是一段简单的代码,但是帮助我超越了概念化的范围,和对象在 JavaScript 中理解差异,从而亲身体验了它们的实际作用。

熟能生巧️‍♂️️‍♀️

我经常调试正常的代码。我经常发现潜在未立即显示的问题,我可能会注意到初始化代码被多次调用(这可能会导致大规模的性能问题),或者某个事件被超出范围的实例注册而没有注销。这可能导致内存泄漏!


有时,甚至“简单的代码”也可能会超出自己的假设而泄露秘密。我从事了 Angular.js 编写的一些最大的项目(是的,需要 $scope 或 controller as)。一些使用数据绑定的非常简单的页面在“后台”进行大量的工作。通过调试这些页面,我发现效率低下,例如运行多个“摘要循环”,这些随着时间的推移会影响性能。


一个很棒的练习是下载一个开源项目,最好是一个实用程序或工具。花些时间查看源代码,以确定您认为代码的将如何运行。然后,启动调试器并逐步执行每个语句。千方百计!您可能会对发现和学习到的东西感到惊讶。您执行的次数越多,您就越有准备。你会:


  1. 了解如何通过预览源代码来分析代码

  2. 发现开发人员用来解决各种问题的模式

  3. 潜在地发现作者尚未意识到的问题


此练习可能只发现了一个改进的地方,并作为开源贡献提交给项目。

最好的调试工具就是您的想法 🧠

最后,我将会给您提供许多年前导师给我的同样建议,这是我多年前开始排除第一个企业问题时所给的。他告诉我,目标应该是永远不必启动调试器。每个调试会话都应该从逻辑上演练代码开始。您应该分析一下您期望的结果,然后实际地进行遍历… 如果我在这里通过了,这里我就理解,然后再去那里,这样就可以循环 …帮助您理解代码。在我浏览源代码的十个错误中,有九个是错误的,而不必使用 F5。


当我按 F5 键时,现在我对代码应该执行的操作有一个预期。当它做一些不同的事情时,通常更容易找出计划哪里出了问题以及执行代码如何脱离脚本。在许多不允许您完全运行调试器的生产环境中,此技能尤其重要。自那时以来,我一直受教并遵循这样的理念:源代码、位置良好的跟踪语句和深入思考的组合是修复最丑陋的错误所需要的全部。


启动调试器并在您 认为 可能存在缺陷的位置设置断点是很容易的事。在紧要关头,这可能是最好的方法,如果您成功了,给你冒泡提示您!如果没有,请不要陷入相信您的假设的陷阱。相反,请退后一步,开始分析 实际发生的情况,而不是 您认为应该发生的情况


我的步骤通常如下所示:


  1. 尝试修复我认为的问题(如果我可以编写一个因缺陷而失败并在修复时通过的单元测试,则可加分)

  2. 如果不是,请退后一步并分析代码以确定其实际作用

  3. 打开调试器,但是不要在我认为可能是问题的地方设置断点,而是从头开始逐步进行操作,并注意发生了什么,而不是我认为应该发生的事情

  4. 添加调试语句以帮助留下痕迹

  5. 单独提取代码,以查看是否可以找到缺陷而没有完整解决方案的复杂性和开销


我已经做了足够长的时间,以至于我 80%的时间都在第一步中找到了解决方案,最终在 20%的时间中为最后几步花费了额外的时间。

这是一门你可以学到的艺术

调试是一门需要耐心,专注和经验才能学习的艺术。我希望前面的练习可以帮助您理解那些有时会阻止您修复代码的筛选器,并且这些技巧将帮助您下次遇到问题时有所不同。请记住,没有不可修复的缺陷,而且没有比您的耳朵更强大的调试器。


您最喜欢的调试技巧是什么?请使用以下评论分享。


原文链接https://dev.to/dotnet/the-secret-art-of-debugging-1lfi


2020-03-30 19:14686

评论

发布
暂无评论
发现更多内容

直播教学!20 分钟开发可视化「智能门铃」丨RTE 开发实战课 • 第一期

声网

最佳实践 直播 RTC 声网

OPPO、京东云 loT 项目数据架构改造,数据处理痛点这样破解

TDengine

tdengine 数据架构 时序数据库 用户案例 loT

Mac教程:如何开启任何来源选项

理理

Mac 苹果电脑 任何来源

真的有那么丝滑吗?面试阿里(Java岗)从投简历到面试再到入职

做梦都在改BUG

Java java面试 Java八股文 Java面试题 Java面试八股文

VPN客户端Shimo mac版使用教程:如何创建新的 VPN 帐户?

Rose

vpn mac系统 Shimo下载 Shimo教程

Last Week in Milvus

Zilliz

Milvus Zilliz 向量数据库

SpringBoot项目就连创建目录都让人抓狂

做梦都在改BUG

Java Spring Boot 框架

使用抓包工具Wireshark分析IoT设备网络行为——设备管理运维类

阿里云AIoT

网络协议 物联网 网络性能优化

订阅标识符与订阅选项--MQTT 5.0新特性

EMQ映云科技

物联网 IoT mqtt 订阅 企业号 3 月 PK 榜

React数字滚动组件 numbers-scroll

观纵科技

JavaScript 前端监控 React

金三突击面试,收获6个Offer,原来面试还能这么简单!

做梦都在改BUG

Java java面试 Java八股文 Java面试题 Java面试八股文

亿级用户中心的设计与实践

做梦都在改BUG

Java 服务架构 亿级流量 用户中心

CleanMyMac4.20专业的mac清理软件

茶色酒

CleanMyMac4.20

企业不想走弯路,不如试试低代码开发

引迈信息

低代码 低代码开发 JNPF

设备使用HTTPS协议接入IoT物联网平台——设备接入类

阿里云AIoT

真香!阿里最新出品Java面试核心讲(终极版),Github已星标50K

程序员小毕

Java 程序员 面试 后端 架构师

可插拔组件设计机制—SPI

京东科技开发者

spi Java】 JavaSPI 企业号 3 月 PK 榜

Acrobat Pro DC 2023发布,有哪些新的改进?

Rose

adobe pdf编辑器 Acrobat Pro DC 2023

ElasticSearch必知必会-Reindex重建索引

京东科技开发者

elasticsearch 索引 ES 集群 企业号 3 月 PK 榜

喜讯|百度入选“移动互联网APP产品安全漏洞治理”优秀案例

百度安全

使用Assembly打包和部署Spring Boot工程

做梦都在改BUG

Java spring Spring Boot assembly 框架

交易系统之数据库弱依赖解决方案

京东科技开发者

数据库 高并发 灾备 db 企业号 3 月 PK 榜

AntDB数据库助力中国移动华南中心计费项目

亚信AntDB数据库

AntDB 国产数据库 aisware antdb AntDB数据库 企业号 3 月 PK 榜

业务架构那点事(2)如何通过高层访谈获取企业战略信息?

涛哥 数字产品和业务架构

业务架构 访谈

通过Flutter实现一个能在多端运行的扫雷游戏

编程的平行世界

flutter 前端 游戏 移动端 扫雷

K8S部署应用详解

tiandizhiguai

3D摄影棚布光工具Set A Light 3D Studio

Rose

Mac软件 Set A Light 3D Studio 3D摄影棚布光工具

面面俱到!四面阿里拿offer后,才发现师哥给的面试笔记有多强大

做梦都在改BUG

Java java面试 Java八股文 Java面试题 Java面试八股文

如何在 macOS 中互换 Control 和 Command 键

理理

mac教程 Control键 Command 键

解决 Parallels Desktop 虚拟机不能连网的问题

理理

Parallels Desktop 虚拟机 PD虚拟机不能联网 PD常见问题

从稀疏表征出发、召回方向的前沿探索

百度Geek说

召回 预训练模型 稀疏矩阵 企业号 3 月 PK 榜

神奇的调试艺术_文化 & 方法_Azure 中文精选_InfoQ精选文章