犯错对于你作为一个开发者的成长是很重要的。我喜欢说,软件开发是一连串的错误和纠正(或者问题和解决方案,如果你愿意这样看的话)。对我来说,我知道如果我没有犯过所有的错误,我就不会成为现在这样出色的开发者。
开发人员会犯错;这是必然的,因为我们是人。犯错误是开发过程中的一个自然部分。真正的问题不在于我们犯错--那是不可避免的。问题在于,有时我们的错误会传到我们的客户那里,在最好的情况下,这些错误是令人尴尬的,而在最坏的情况下,它们会使企业损失时间和金钱。
作为开发者,我们需要的是工具和技术,以帮助我们在错误发生之前抓住它们。幸运的是,我们可以从别人的错误中学习,而且我们可以获得广泛的技术和实践,我们可以在进入生产时部署,以预先减轻错误的风险。
在这篇文章中,我们将介绍各种可以帮助的技术。使用这些技术的组合给了我们犯错误的余地,而这反过来又给了我们作为开发者学习和成长的空间。它还能帮助我们及早发现错误,并将破坏性的变化在生产中的风险降到最低。
个人开发者技术
我把这些技术分成两部分。首先,我们将介绍你可以自己练习的内容,然后我们将讨论你可以和你的团队一起练习的内容。正如你所看到的,有很多事情你可以自己做,以改善你的开发实践。
迭代编码与小提交
这是每一个开发者都可以做的事情。当你以小的增量迭代地写你的代码时,你可以独立地测试和提交每一个代码变化,在你当前的整体计划的方向上迈出小步。小的变化比大的变化更容易测试和验证其正确性;当出错时,它们也更容易退缩。
当事情变得糟糕时,你可以安全地重置你的工作副本。虽然你会失去你当前的修改,但它们不会太多,因为你只做了小的提交。
这个技巧非常重要,它实际上是我的开发哲学中最基本的规则:当你以小而简单的增量编码时,你就能保持代码的正常运行*。*
在一天结束的时候,许多小的、经过良好测试的代码提交,加起来就会有大量新的、可以工作的代码。

手动测试代码
手动测试你的代码是开发中必要但被低估的部分。玩弄你的代码!了解它的真正作用,而不仅仅是你认为它的作用。这是在代码离开你的开发计算机之前发现错误的最好方法。
你可以在你的REPL中测试你的代码,从命令行,或使用你的前端;你可以使用VS Code REST Client 测试你的REST API,如果你需要,甚至可以创建你自己的测试平台。有很多方法可以测试 - 但要确保你真的在测试你的代码。
对于新的开发者和有经验的开发者来说,手动测试是一个很好的起点,他们都在构建新产品。由于自动化测试涉及大量成本,一般来说,在投资自动化测试之前,最好确保你的产品是可行的。此外,你需要先做好手工测试,然后才能做好自动化测试--你怎么能把你不知道怎么做的事情自动化呢?
即使你已经毕业于自动化测试,你仍然需要不时地返回到手工测试。更不用说你的团队中的某个人无论如何都要做手工测试--如果探索性测试不做,你就不可能找到开发人员无法想象的错误。
设置你的测试环境
如果你在你的开发计算机上还没有一个快速有效的测试设置,请考虑这是你在开发环境中首先需要解决的问题。
你会希望有一个脚本或框架,你可以启动并让你的应用程序在短短的时间内运行并准备好测试--越快越好。Docker中的compose 命令在这方面是很好的,甚至更好的是,Compose现在已经内置于Docker中了。
你还需要为你计划运行的任何测试方便地访问现实的数据。你需要数据库夹具,或测试数据集,用于你的应用程序的不同设置。这些测试数据集不需要很复杂--一组JSON文件就可以完成工作。然后你需要一个脚本来快速加载数据到你的测试数据库。
同样非常重要的是,你要有一个类似于面向客户的生产环境的测试环境。你的公司应该为你提供这个--如果他们不提供,当软件错误出现在实际生产环境中时,他们就不能抱怨。
你也可以确保你的开发环境被配置成与测试和生产环境相匹配,或尽可能地匹配。为此使用Docker--这是一个很好的方法,可以确保在开发中运行的东西在生产中也能运行,而且对你的队友也是如此。
代码自我审查
自我审查是每个开发者都应该做的事情,即使你也在做同行审查。
在提交之前审查自己的代码,可能是在别人之前发现代码错误的最简单的方法。自我审查应该是快速的--假设你的提交量很小,那么在你工作的时候审查每一个提交量应该不会花很长时间。
使用你的版本控制软件的diff 功能来检查你所做的修改。确保你理解你的代码修改,以及你做这个提交的原因或理由。如果你不明白,先不要提交。花点时间想一想。
试着向坐在你旁边的一个想象中的朋友解释你的代码。有些人喜欢向一只橡皮鸭子解释他们的代码修改。

在让别人检查之前,先检查自己的工作。你可能会惊讶地发现,通过持续的自我审查,你可以先发制人地捕捉到很多错误。
练习防御性编码
为了应对墨菲定律,我们应该经常练习防御性编码。认为我们的代码会一直工作是天真的,我们应该为最坏的情况做准备。我们的代码会抛出意想不到的异常(通常是在生产中,当我们没有预料到的时候),我们的API会被错误地使用,我们的函数的输入会是垃圾的。最终,任何可能出错的东西都会出错。
所以,我们应该假设事情会出错,并确保我们的代码能优雅地处理它。
我们怎样才能弄清这一点呢?通过...
防御性测试
你应该主动攻击自己的代码,以确定它是如何反应的。随机地在代码中添加异常,看看会发生什么。故意以错误的方式使用你的API。向你的函数传递垃圾输入。随机地烧毁服务器--也就是混乱工程--以确保你的分布式系统是可以容错的。
当你知道你自己的代码是如何失败的,你就能更好地处理这种失败。
自动测试
我们已经介绍了每次改变代码时,测试我们的代码是多么必要。而在每次生产发布之前,我们必须测试来自整个开发团队的集成代码。
一旦你学会了如何手动测试你的代码,如果你能把它放在自动状态,为什么还要花几个小时费力地手动测试呢?如今,没有多少代码是不能进行自动测试的。我们可以使用嘲讽来隔离我们的代码进行单元测试,或者我们可以通过集成测试或端到端(E2E)测试来获得真正的收益。
自动化测试意味着我们可以在任何时候重新运行我们的测试过程,而不需要投入我们自己的时间。
必须承认,自动化测试是一项大的投资。我们需要在进入之前确定这是一项值得的投资,但对于中长期项目来说,自动化测试很可能会为你节省大量的时间和金钱--更不用说,它还可能会捕捉到一些令人尴尬的错误,否则就会进入生产。
测试驱动的开发
测试驱动开发(TDD)采用自动化测试,并将其置于开发过程的前端和中心:我们的开发是由测试过程主导的。
TDD实现了一个惊人的结果,你可能必须自己看到才能真正相信。当你第一次尝试TDD,并意识到你的代码在第一次运行后就完美无缺地工作时,你会感到震惊。代码第一次就能正确运行是很罕见的--总是有问题的--但是有了TDD,你的代码第一次就能完美运行是非常正常的,当然,这取决于你的测试的彻底性和可靠性!
也许TDD最重要的一点是,它让你从一开始就考虑到测试,这有助于你完善你的能力,以创建适合自动化测试的代码。
TDD改变了你作为一个开发者。后TDD的开发者会写出质量更高的、设计更合理的、测试更好的代码。即使后TDD开发人员没有进行TDD,他们的代码也会减少错误,这纯粹是由于他们更加关注自己所写的东西。
投资于你的技能和开发环境
作为个人开发者,你能做的最后一件事就是不断地、持续地投入时间来提高你的技能和升级你的工具集。总是在学习和改进。总是在寻找能够带来改变的工具和技术。
我们有幸成为开发者,在这个时代,我们可以接触到一个庞大的、不断增长的工具生态系统。我们可以选择编程语言、框架以及软件和测试工具。你需要了解那里有什么,以及它如何帮助你交付更可靠的代码--所以要确保你在该领域的最新和最伟大的东西上。
开发者团队技术
现在,让我们提升到团队的水平在下面的章节中,我们将回顾你可以和你的团队一起练习的一系列技术。
同行代码审查
让一组新的眼睛看你的代码是比审查你自己的代码更重要的一步。下次你准备推送代码时,叫你的队友过来看看你的代码变化。逐一审查diff 。解释你改了什么,为什么要改。如果你在远程工作,提交一个拉动请求,并在接受之前让它接受虚拟审查。
这样做是因为你的审查者有不同的视角,他们有可能发现你的代码中的错误和缺陷,而你没有--或无法--想象。
同行代码评审也是促进团队内部交流和分享学习经验的好方法。它还能提高你的团队接受批评的能力--尽管要注意确保你提供的是善意的批评。毒性和非建设性的批评是不受欢迎的,也不应该被欢迎。
请注意,这并不是要把你的代码中的问题归咎于你。这是为了让团队一起工作,以改善产品,并发现那些可能在生产中出现的问题。
分支策略
一个简单而稳健的分支策略很容易实施,可以帮助隔离有问题的代码。你也可以用分支来缓冲客户的问题。
它不需要很复杂。我喜欢使用以下分支:main,test, 和prod 。创建这些暂存点意味着你的代码在施加到你的客户身上之前必须经过多个检查点。
开发人员将代码推送到main ,意味着他们的代码经常被整合。这有助于避免合并冲突,并确保开发团队一起工作,以整合他们的代码并修复任何发生的问题。
这是持续集成的基础,是持续交付之前的一个重要实践,也是持续交付的基础。当main 出现故障时,团队有责任找出问题所在并加以修复。
假设main 分支在功能准备就绪时是健康的,main 被合并到test 。现在可以在合并到prod ,并将改动强加给客户之前,在test 上做大量的测试。
对缺陷进行优先排序
你是否在一个已经充满了bug和问题的代码库上工作?你的重点应该是减少你已经有的缺陷。一个有问题的代码库或糟糕的开发环境本身就会造成问题,但它也会降低开发人员的积极性--这反过来会增加进入生产的问题数量。
在添加新功能之前,首先要关注修复现有的最糟糕的缺陷。
当然,这里有一个平衡的问题--我们必须不断增加新的功能以保持业务的发展--但这是一个权衡。有了正确的团队结构,我们可以在实施新功能的同时,不断改进代码库,使其更可靠,对失败有更强的适应力。
确保你对你的产品的健康有一个长期的愿景。这可能需要长时间的坚持和持续的努力才能有效处理。
结对编程
当你有一个棘手的问题被证明难以解决时,你会怎么做?你会请别人坐在你旁边,帮助你解决这个问题。结对编程将这一点发挥到了极致:成对的开发人员一起工作,并肩解决问题。
这里的好处很简单:两双眼睛比一个人发现更多问题。结对编程帮助开发人员更快、更可靠地发现问题,但它也可以大大改善和扩大你的经验。作为一个开发者,没有比与更有经验的人结对工作更快提高水平的方法了。
一旦你进入了结对编程的节奏,无错误的代码就会变得非常流畅。这就像一场乒乓球比赛,选手们合作,尽可能长时间地把球留在空中。
敏捷开发的 "停止线"
敏捷开发可以追溯到丰田公司的Taiichi Ohn所提出的精益生产的根源。在他的系统中,如果工厂里的任何工人发现任何问题,他们都可以叫停生产。然后,这些问题被修复,生产重新开始。他们不容忍任何制造方面的错误。
作为开发者,我们也应该这样做。不要容忍你的持续集成或持续交付系统的问题。如果这些自动化系统出现故障,开发团队必须停止在其他项目上的工作,专注于修复它们。这些是问题的早期预警系统,也是代码进入生产的检查点。它们是我们在错误到达客户面前的最后一道防线。团队应该把保持这些系统的工作放在最优先的位置。
但是--当问题真的被推广到生产中时,会发生什么?我们应该尝试在生产中修复它们吗?这是个硬性的否定!
尽可能快地收集证据并记录再现案例。然后,为你的客户着想,将破坏性的变化回滚到以前的工作版本,以尽快恢复功能。一旦压力消失,你就可以在测试环境或开发计算机中重现并修复这个问题,在那里它不会打扰到客户。
结论
程序员会犯错,错误会发生。这是开发中的一个事实,但这并不意味着我们的客户应该受到影响。我们有很多方法可以在开发管道的早期发现--然后修复--问题。
既然我们可以合理地预期问题的发生,我们就应该一直在寻找解决方案。
请使用这篇博文中概述的技术来减少错误一直到生产的风险。你的开发需求会有所不同,但你有责任阻止你的错误一直发生在你的用户身上。
The postKeeping mistakes away from productionappeared first onLogRocket Blog.