Unit testing 红色,绿色,重构-为什么重构?

Unit testing 红色,绿色,重构-为什么重构?,unit-testing,testing,refactoring,tdd,Unit Testing,Testing,Refactoring,Tdd,我正在努力学习TDD和单元测试的概念,我看到了一句咒语:“红色,绿色,重构。”我很好奇为什么在测试通过后要重构代码 这对我来说毫无意义,因为如果测试通过了,那么你为什么要搞乱代码?我还看到TDD咒语,如“只编写足够的代码使测试通过” 我能想到的唯一原因是,如果要让测试通过绿色,你只需草率地编写任何旧代码。你只要拼凑出一个解决方案,就能通过考试。很明显,代码是一团糟的,所以你可以把它清理干净 编辑: 我在另一篇stackoverflow文章中发现了这个链接,我认为这证实了我提出的唯一原因,即“通过

我正在努力学习TDD和单元测试的概念,我看到了一句咒语:“红色,绿色,重构。”我很好奇为什么在测试通过后要重构代码

这对我来说毫无意义,因为如果测试通过了,那么你为什么要搞乱代码?我还看到TDD咒语,如“只编写足够的代码使测试通过”

我能想到的唯一原因是,如果要让测试通过绿色,你只需草率地编写任何旧代码。你只要拼凑出一个解决方案,就能通过考试。很明显,代码是一团糟的,所以你可以把它清理干净

编辑:


我在另一篇stackoverflow文章中发现了这个链接,我认为这证实了我提出的唯一原因,即“通过”测试的原始代码可以非常简单,甚至是硬编码的:

,因为你永远不应该重构非工作代码。如果您这样做了,那么您将不知道错误是最初出现在那里还是由于您的重构。如果它们在重构之前都通过了,然后又失败了,那么您就知道您所做的更改破坏了某些东西

他们并不想编写任何草率的旧代码来通过测试。最小和散漫是有区别的。禅宗花园是最小的,但不是草率的


但是,回想起来,您在这里和那里所做的最小更改可能会更好地组合到由它们调用的其他过程中。在两个测试分别工作之后,是重构的时候了。重构要比猜测一个将最小限度地覆盖所有测试用例的体系结构容易得多。

首先要使代码行为正确,然后再将其考虑在内。如果您以另一种方式进行操作,则在修复过程中可能会产生混乱/重复/代码气味

通常,将工作代码重新构造为分解良好的代码比预先尝试设计分解良好的代码更容易

重构工作代码的原因是为了维护。您希望删除重复,原因包括只需要在一个地方修复某些内容,并且知道当您在某个地方修复某些内容时,您不会错过其他地方类似代码中的相同错误。如果变量、方法和类的含义与最初的意图不同,则需要重命名它们


总的来说,编写工作代码是不平凡的,而编写功能完善的代码是不平凡的。如果你想同时做这两件事,你可能无法充分发挥你的潜力,所以先充分关注其中一件,然后再关注另一件是很有用的

通常,代码的第一个工作版本——即使不是一团糟——仍然可以改进。因此,您可以改进它,使它更干净、更可读、消除重复、找到更好的变量/方法名等等。这就是重构。既然有了测试,就可以安全地重构,因为测试将显示您是否无意中破坏了某些东西

请注意,通常您不是从头开始编写代码,而是修改/扩展现有代码以添加/更改功能。现有的代码可能无法无缝地适应新功能。因此,新功能的第一次实现可能看起来很尴尬或不方便,或者您可能会发现很难进一步扩展。因此,您可以改进设计,以最简单、最干净的方式合并所有现有功能,同时仍然通过所有测试

你的问题是老生常谈的“如果它有效,就不要修复它”。然而,正如Martin Fowler在重构中所解释的那样,代码可以以许多不同的方式被破坏。即使它通过了所有测试,也很难理解,因此很难扩展和维护。此外,如果它看起来很邋遢,未来的程序员将更加不注意保持它的整洁,因此它将更快地恶化,最终退化为一个完全无法维护的混乱。为了防止这种情况,我们进行重构以尽可能保持代码干净整洁。如果我们(或我们的前任)已经让它变得一团糟,那么重构是一项巨大的工作,对管理层和利益相关者没有明显的直接好处;因此,很难说服他们在实践中支持大规模重构。因此,在每次代码更改之后,我们都会进行小的甚至是琐碎的重构

我看到了咒语:“红色,绿色,重构。”

这不是一个“咒语”,而是一个惯例

我还看到TDD咒语,如“只编写足够的代码使测试通过”

这是一个指导方针

现在你的问题是:

我能想到的唯一原因是,如果要让测试通过绿色,你只需草率地编写任何旧代码。你只要拼凑出一个解决方案,就能通过考试。很明显,代码是一团糟的,所以你可以把它清理干净

你快到了。关键在于TDD的“设计”部分。您不仅在编码,还在设计解决方案。这意味着确切的API可能不会一成不变,您的测试可能不会反映最终的设计(因为它还没有完成)。在编写“仅足以通过测试”的代码时,您会遇到一些问题,这些问题可能会改变您的想法并指导设计。只有在你有了一些工作代码之后,你才能改进它

此外,重构步骤涉及到整个代码,而不仅仅是为了通过上一次测试而编写的代码。随着编码的发展,代码的各个部分之间的交互越来越复杂,重构代码的最佳时机就是它一开始工作

正是因为这个非常早期的重构步骤,您不应该担心第一次迭代的质量。这只是一个概念证明,有助于设计。

你不应该接受“只编写足够的代码使测试通过”的咒语。 记住,你的应用程序还没有准备好,只是因为你所有的测试都通过了。显然,您希望在测试通过后重构代码,以确保代码可读性和良好的架构。测试就在那里