孙子兵法——如何更快更有效地消灭虫子
想象一下,世界各地的开发人员花了多少时间来处理代码中出现的错误和问题。事实上,你在这方面的能力或许可以决定你作为一名专业开发人员的价值。
经验丰富的开发人员通常会帮助初级开发人员解决棘手的代码修复问题。所以,如果你是一名初级开发人员,并且感觉自己总是陷入困境,不得不向你的前辈寻求帮助,你可能会想——他们究竟是如何做到的?
答案是什么?
答案并不那么简单。你或许会认为,资深同事之所以能帮你解决所有问题,是因为他们经验更丰富或调试技巧更娴熟。但我认为这只是故事的一半。剩下的50%则完全是心理优势,原因如下:
你问了他们!你已经表明你相信他们的专业能力,这种积极的鼓励非常有力。这实际上可以让人变得更聪明——这种信任投票会让他们智力上得到真正的提升。
这不是他们的问题,所以他们不会害怕失败。没有了这种焦虑,他们更容易集中100%的脑力去寻找问题的真正解决方案。
即使他们没有什么可失去的,你的同事也知道,如果他们解决了问题,会给他们带来额外的心理奖励,因为你会对他们的卓越和高水平的专业技能感到敬畏。
你看,对他们来说没有大棒,只有一大把胡萝卜。
让我们思考一下提升自身技能的方法。我尝试在这里整理一些对我有用的想法和思路。我相信,阅读这份清单并运用其中的建议,能够提升你的技能,直到你成为那些你经常寻求帮助的专家。
请勿寻求帮助
这一点至关重要,对你的成长大有裨益。你应该在系统地完成了以下所有要点之后,仍然陷入困境——我的意思是那种无力自拔的困境——才寻求帮助。我经历过的最好的成长经历之一,就是在无人真正帮助我解决问题的时候。我别无选择,只能自己解决问题。
不要向仇恨屈服
情绪化对解决 bug 毫无帮助。你不应该有讨厌的 bug,这只会让 bug 更难解决。每个 bug 都是磨练技能的绝佳机会,所以最好试着去喜欢它们。
你相信魔法吗?
我相信,如果你真的在一个调试问题上苦苦挣扎了很长时间,那么这很可能至少有 50% 是出于心理原因,甚至可能更多。
你脑海里有个声音说:“不可能!一定是黑魔法!”你感觉世界疯了,这不可能是你的错。你觉得你唯一能做的就是逃避问题。
别听信这个声音!代码里的一切都是有原因的!没有什么黑魔法能破坏你的代码,兄弟,很抱歉告诉你,也没有什么魔杖能修复它!你只需要找到出错的那一行代码,然后修复它。很简单。
读取错误
请不要直接将错误复制粘贴到 Google 或 Stack Overflow 上。您应该抓住机会从每个错误中学习,提升自己的技能——当您遇到难以修复的错误时,这一点尤为重要。
最好仔细阅读错误信息,并尝试理解整个流程。通常,错误的原因就在你眼前——你只需要仔细观察即可。
阅读代码
别慌。通常情况下,代码已经告诉你哪里出了问题。最糟糕的情况会是什么?你浪费了一些时间检查代码,却找不到答案。
但实际上,这段时间不会被浪费,因为你会对项目有更多了解。在你完全熟悉之前,总会有工作要做。另外,练习代码阅读技巧总是有帮助的。
军队规则
这条简单的规则是一位防空军官在军事训练中告诉我的。当你维修一台复杂的机器时,如果出现故障,或者无法像以前一样正常运转,你应该把注意力集中在最近一次维修或检查的模块上。
这也完全适用于编程!所以你需要查看最近更新或修复的任何代码。
实现即时错误重播
当你意识到问题很棘手,需要进行大量测试时,应该暂停一段时间,以便改进测试流程。理想情况下,你的错误修复检查流程应该完全自动化。
如果你能找到一种更快地重现错误的方法,那么你就能更高效地测试多个解决方案。这将帮助你集中精力解决问题并快速找到解决方案。你甚至可以暂时简化现有的代码逻辑,从而加快每次测试的速度。
演绎推理
我在一个名为 SYPT 的学校物理竞赛中发现了这种方法。这种方法不仅用于科学研究,还能解决棘手的编程问题。以下是科学方法:
1) 检查流程并观察正在发生的事情。2
) 尝试构建一个理论解释来解释正在发生的事情。定义所有可能导致问题的因素。3
) 然后,你应该逐一验证这些理论,从看起来最合理的理论开始。确保你提出的问题是正确的。每次验证都应该抓住问题的本质。不要同时测试多个理论。这会干扰对问题的全面了解,并且无法得出正确的结论。
每个原因或理论都应该通过测试结果来证明或否定。同样的原则也适用于解决复杂的 bug 问题。
小黄鸭调试
这是一个著名的方法,源于一个程序员的故事。他总是随身带着一只橡皮鸭,强迫自己向鸭子解释编码问题。这能帮助他解决问题。
有时我发现自己会告诉别人一个 bug,即使我知道他们根本帮不了我!但这仍然很有用。我经常在谈话中发现正确的解决方案。当你试图和别人讨论问题时,你的大脑会组织它,并把它按正确的顺序解释清楚。有时,这可能正是你所需要的,帮助你解开接下来需要采取的逻辑步骤。
我知道这似乎与之前的建议“不要寻求帮助”相矛盾,但这是一个谬论。“橡皮鸭”方法会让你更加费力地自己解决问题。与人、动物、植物,甚至像那只著名的橡皮鸭一样的无生命物体讨论问题,绝对不是疯狂的表现。
代码二分法
这是最好的规则!即使你不完全理解一大段代码到底是怎么回事,它也能正常工作。我想你可能已经从标题中明白了,但无论如何,让我更详细地解释一下。假设一开始代码崩溃了,但原因不明。
你可以通过注释掉代码中的一段,然后重复检查来一分为二。如果错误消失了,那么你就知道错误出在你注释掉的那一部分代码上。如果没有,那么你可以对其他代码段重复此过程。
问题可能出在某一行,您需要重复测试,直到隔离出问题的代码片段。
当然,您必须检查整个代码才能完全理解它并做出决策来防止错误,但如果您在寻找错误本身时不必阅读所有可疑代码,那么速度会快得多。
PROD 上出现错误!
好的,首先,别慌!慌乱无助于快速解决问题。以下是您可以采取的应对生产环境错误的措施——在采取其他措施之前,先问自己这个问题:
我可以在本地重现该错误吗?
- 是吗?好,我们来调试一下,找出问题的原因。修复,部署,回家,亲吻你的妻子(拜托,亲吻你自己的妻子!)
- 不是吗?你知道,当本地没问题,但在生产环境中却失败时,人们往往会抓狂。我想说,在这种情况下,我们应该尝试看到负面和正面的影响。
这个挑战已经给了我们一些关于如何找到解决方案的线索。本地环境和生产环境之间有什么区别?可能我们有不同的配置或不同的 Web 服务器设置,或者其他一些可能与该问题相关的问题。这主要取决于逻辑。
稳扎稳打才能赢得比赛
即使你需要尽快修复问题,也不意味着你应该立即在生产环境中测试!我见过无数次因为热修复过程中的一些愚蠢的拼写错误而不得不进行两次甚至三次部署。检查本地测试并尽量保持代码质量。一次部署的逐步修复总比三次部署的三个热修复要好。
携带一些蓝色胶带!
想象一下,你正在处理一个特别棘手的 bug。公司现在因为这个问题而亏损。你已经找到了 bug 的原因,并意识到修复 bug 的工作量巨大,而且显然需要额外的单元测试等等。在这种情况下,我们该怎么办?
让我们努力提供一些可能的临时修复方案。即使不完美也没关系,但必须快速响应,以免公司在制定最终解决方案时遭受更多损失。
如果我们正在测试的某个新功能存在 Bug,我们可以先将其回滚,以保护主进程。这样,我们就可以先使用稳定版本的代码,同时花时间研究如何正确修复 Bug。
不稳定的测试
有时,即使本地界面上没有出现测试失败,你的 CI 也会无缘无故地显示测试失败。这类测试失败应该另写一篇文章,甚至一本书来专门讨论。
失败的原因肯定与测试运行的顺序有关。但即使你知道正确的顺序,也未必能解决问题,因为你可能同时运行着数千个测试,甚至无法确定究竟是哪个测试导致了失败。
一些测试工具(例如 Ruby RSpec)具有智能二分功能,可以帮助最大限度地减少计数中涉及的测试数量。然而,这可能是一个非常缓慢的过程,并且不一定能给出确定的结果。
因此,最好先阅读问题,并了解在测试之前哪些常见资源被触及并影响了测试结果。这样,你就能预测哪些测试是导致失败的原因。之后,你只需要按照正确的顺序运行目标测试,就能证明你的理论。
是的,我知道这听起来像是一个艰难的过程,但修复此类测试总是会导致其结构的改进。
奖励:如何编写没有错误的代码?
我不想吹嘘,但最近我的代码 bug 比以前少了很多。我学会了更加细心,用良好的架构编写正确的代码结构,从而迫使 bug 暴露出来。如果你对整个流程有非常深入细致的理解,很可能就不会遇到这么多或这么严重的 bug。
你的大脑可以像你的编程代码运行器一样运作。除此之外,如果时间充裕,我会尝试使用测试驱动开发 (TDD) 和端到端测试。虽然不可能 100% 避免 bug,但通过这种方式可以显著减少 bug 的数量。
最后的话
尝试享受修复 bug 的过程!一开始,它或许不如编写新代码那么令人满足,但它也有自己的优势。
例如,一些棘手的错误会让您成为一名真正的侦探,当您走在正确的道路上时,您将真正享受追逐的快感。
所以,bug越难解决,你获胜时的喜悦就越大!感谢阅读!祝你好运,战胜这些bug!
PS:非常感谢Pixel Point的朋友们提供的插图
文章来源:https://dev.to/lxkuz/the-art-of-war-how-to-beat-the-bugs-faster-and-harder-2e4g