发布于 2026-01-06 10 阅读
0

用TDD改善你的生活

用TDD改善你的生活

作为雇员或自由职业者,我们向公司和客户出售时间和工作成果。但我们这个职业与其他职业的不同之处在于,我们出售的是脑力劳动成果,有时甚至是高水平的脑力劳动成果。

因此,关注我们的心理健康和智力发展似乎是一项我们应该经常进行的合理活动。

开发界的许多人认为,甚至说,测试很难,而且很痛苦,更不用说测试驱动开发(TDD)了。

但我想要证明,如果你想作为一名开发者拥有更健康的生活,TDD 才是正确的方向。

但首先,让我来告诉你一些关于我们大脑如何运作的事情。

在座各位有人不会开门吗?真的吗?你们见过带使用说明书的门吗?我见过:那种上面有拉或推提示的门。

你有没有站在门前却不知道该怎么打开过?我有过。

事实上,市面上有很多这样的门。

关键在于门应该易于使用。但实际情况并非总是
如此。如何使用门应该是显而易见的,不是吗?

那么,开关呢?

我指的是大房间里那些开关面板,它们的位置和控制的灯的位置完全对不上。有时候,它们甚至安装在灯看不见的地方。你得试好几次才能找到打开你想开的灯的隐藏组合。

开关和它所控制的灯泡之间的关系应该很明显。

当我们谈到显而易见的事情时,我们指的是那些无需我们费脑思考就能获得的知识。这些知识就存在于现实世界中。我们只需要在做其他事情时运用它们。我们希望能够毫不费力地打开门、开关灯。

所以,当我们不得不思考一些显而易见的事情时,我们就浪费了一部分心理资源,占用了我们本可以用于其他用途的工作记忆空间。

当使用某个物体所需的所有线索都存在于物体本身时,知识就存在于该物体之中。因此,我们无需关心、推理或回忆如何操作该物体。当我们需要这样做(例如推理、记住操作说明等)时,我们需要将知识储存在头脑中,以便
达成目标。

因此,当我们执行一项任务时,世界上的知识越多,我们大脑中需要的知识就越少,从而腾出空间让我们更好地思考手头的任务。

我越少思考工具的使用,就越能专注于使用这些工具执行的任务本身。

但是,还有多少空间可用呢?

嗯……听起来有点令人失望:不太好。

我们的记忆容量几乎是无限的。你可以把它想象成一个容量巨大且智能的硬盘,能够保存记忆和数据长达数年。它并非被动存储,实际上,它会不断重建我们的记忆,以便存储和检索信息。这一点至关重要,因为当我们存储或检索信息时,我们需要使用工作记忆来保存正在使用的数据。这和计算机的工作原理非常相似,不是吗?

然而,我们的工作记忆与长期记忆截然不同。有些人称之为“短期记忆”,有些人称之为“工作记忆”……我认为你可以把它想象成一个处理器,它有一些寄存器,可以在工作时存储数量有限的信息单元,称为“信息块”。信息块的大小可以变化,但它们都是有意义的。

你能记住一个电话号码吗?我猜你会把数字分组,只记住两三个数字。

这是因为我们的处理器能够处理的数据块数量有限,大约是七个(上下浮动两个)。这个数字会因年龄和个体差异而有所不同,但这是一个非常好的近似值。因此,我们会尽可能地节省“寄存器”,将信息分组,并留出一些空闲空间。

如果我们把所有寄存器都填满会发生什么?嗯,任务精度和性能会下降,错误率会增加。总的来说,如果我们试图同时在工作记忆中保存太多信息,我们的表现会更差。

当然,这只是一个过于简化的说法。不过,我想你应该能明白其中的道理。如果我们把知识运用到实际生活中,而不是仅仅储存在脑子里,就能减轻知识负担,而且这样做也能让我们在任何任务中表现得更好。

你可以通过练习将一些知识从工作记忆中释放出来。这就是为什么当我们引入新技术、新语言特性或新工具等时,我们需要放慢速度,工作中也会出现更多错误。我们需要时间来让大脑中的某些环节自动化,同时将知识付诸实践。

在我们的工作中,我们需要管理一些无法自动化的任务,我们通常处理的都是全新的任务。

现在,是时候回到本文的主要主题了。让我们来聊聊开发者的生活。

让我们来分析一下,如果不编写测试程序会发生什么……

事实上,我们一直都在做测试,但我们倾向于手动测试。这就是我们所说的调试。我们采用试错法:这样行得通吗?不行……?再试一次。行得通……?那就继续。

这个过程可以用这张图来概括:我们一边编写代码,一边验证代码是否按预期运行,直到我们认为代码已经完成。之后,我们尝试验证代码整体是否有效,然后,我们才想起遗漏了一些细节……部署之后,我们又发现了一些新的问题,需要进行修复。

到最后,我们会发现自己头痛欲裂,并且感觉好像错过了什么。

这种情况的发生是因为我们试图同时处理脑海中所有的信息(记住,大脑容量有限),结果给自己造成了过大的压力。最好的策略是把目标和子任务写下来,并借助这些外部工具来帮助我们。

例如:一个简单的 API 端点可能需要很多东西:

  1. 控制器操作
  2. 通往此控制器操作的路径
  3. 用于执行操作的用例或命令对象
  4. 可能是一个(或多个)实体以及存储库
  5. 存储库 DIC 定义
  6. 或许是一项服务
  7. 服务DIC定义
  8. 响应对象

我们的记忆力会过度运转。这就解释了为什么我们会感到疲惫和压力,感觉自己可能忘记了什么,对自己正在做的事情感到不安,或者担心自己是否遗漏了什么重要的事情。

那么,让我们来看看如何执行相同的流程,这次是在最后进行测试。

嗯,这看起来很眼熟,但现在流程最后还有测试。就是那种我们自动化的测试。

最终结果确实更好,因为测试让我们对代码更有信心。但到最后,我们仍然会遇到同样的问题。

是的,我们一直在做同样多的工作,承受着同样的记忆负荷,而且还要编写一大堆测试题,而我们的大脑却在呐喊:“嘿,伙计,工作已经完成了!你到底在干什么?”

在这种情况下,或许我们的测试并非世界上最好的测试……

事实上,我们在开始测试阶段时就已经很疲惫了。
这就解释了为什么许多人认为测试很辛苦,甚至很痛苦。

所以,测试虽然能提高我们对代码的信心,但却需要付出大量额外的工作量。即使有了测试我们晚上睡得更香,我们的生活也并没有变得更好……
这是怎么回事?

要想真正改善你的生活,你应该尝试不同的方法。你应该尝试测试驱动开发(TDD)。

这就是TDD循环:一次只做一件事(并推迟决策):

  • 一个简单的测试,但它会失败(在编写测试之前不要编写代码)。
  • 编写代码使该简单测试通过(不要编写任何多余或少于必要的代码)
  • 审查代码以改进命名、架构、应用模式、减少重复等,但不要实现任何新内容,保持测试通过即可。

在这里,你可以从工作记忆模型的角度来理解这个过程。当我们编写第一个失败的测试时,我们的注意力会集中在这个测试上,因此我们不会去关注其他任何事情。编写测试也意味着我们将需要的知识应用到实际工作中。此时,我们的记忆几乎是空闲的。

接下来,我们专注于编写使测试通过所需的代码。我们需要的知识就在测试中,而测试恰好是我们任务的目标,所以它存在于现实世界中,而不是存在于我们的头脑中。

我们只需要思考如何让测试通过,所以,如果是第一个测试,我们只需要编写最显而易见的实现方式。即使这个实现方式很简单,比如直接返回测试期望的值。其他任何事情都不用担心。

然后,一旦测试通过,我们就可以查看代码,看看是否可以通过重构进行一些改进。我们不必添加新功能。我们必须在保证测试通过的同时,整理代码,删除不必要的重复代码等等。

我们会不断重复这个流程,直到功能完全实现。我们不需要编写额外的测试,也不用担心遗漏什么。我们不会头疼。我们只是动脑思考,避免了记忆过载。

这不是魔法,而是测试驱动开发(TDD)。当然,要做到这一点需要一些训练。TDD 是一种智力工具,而工具的使用需要自动化。
因此,你应该进行练习,比如练习“卡塔”(kata),既可以独自练习,也可以在同事的帮助下练习,或者加入实践社群……总之,选择适合你或你的团队的方式。练习,练习,再练习。一旦你能够循序渐进地进行,你会发现不仅事情会变得更容易,而且从长远来看,你会更快乐,压力也会更小。

最后一条建议:

尽可能多地储存你需要的知识:使用待办事项清单、便利贴、写下任务清单、绘制模式图、模型、概念图……

腾出精力,一次只专注于一件事。

TDD 不仅仅是测试。它意味着将你需要的知识融入代码(融入现实世界),从而解放你的思维。它意味着将决策推迟到你准备好的时候再做。

真的,试试TDD,你的开发生涯会因此而改善。

文章来源:https://dev.to/franiglesias/improve-your-life-with-tdd-a5d