TDD是否意味着不考虑类设计?

10

我正在开发一个角色扮演游戏,为了好玩,尝试在开发过程中使用TDD。我看到的许多TDD示例都侧重于先创建测试,然后创建所需的对象以使测试通过。

例如:

[Test]
public void Character_WhenHealthIsBelowZero_IsDead()
{
   // create default character with 10 health
   Character character = new Character();
   character.SubtractHealth(20);
   Assert.That(character.IsAlive, Is.EqualTo(false));
}
所以基于这个,我将创建角色类和相应的属性/方法。这看起来很好,但我的类设计是否真的应该源自不断完善我的测试呢?这比事先映射游戏所需的可能对象更好吗?例如,我通常会考虑一个基本的Character类,然后是像Wizard、Fighter、Thief这样的子类。
还是采用平衡的方法才是正确的途径?首先编写测试以验证它们实际上是否需要,然后再映射出可能需要的类和层次结构?

不幸的是,你提供的代码示例是许多敏捷程序员编写代码的方式(引用“单一使用原则”),这并不是正确的方法。并非所有人都这样做,但太多人了。 - BlueRaja - Danny Pflughoeft
8个回答

6
我认为你误解了TDD的重点。TDD不是关于编写测试,而是关于设计可测试的类。这自然会导致更好的设计和实现。
听起来你是倒过来做的。
你应该按照以下步骤进行:
1.设计你的领域模型 2.设计你的类 3.编写一些测试 4.实现一些类逻辑 5.如果需要,重构你的类以使它们更易于测试 6.重复步骤3-5

1
根据您的经验水平,“设计”类可能需要也可能不需要。我几乎从来没有单独进行设计步骤。 - John Saunders
@Joh Saunders - 很可能你仍在设计它们,只是采用了“即时”设计的方式。我认为将 JIT 设计与缺乏设计区分开来非常重要。TDD 强烈暗示(故意轻描淡写)至少从关注点分离/封装的角度来看,良好的类设计。你的类设计不是使用 UML 或其他工具记录,而是记录在测试语法中。你说得很对,“取决于你的经验”... 对于新手来说,某种形式的显式设计步骤可能是个好主意。 - Jim L
@Jim:我回应那些以旧式方式思考“类设计”的人,需要单独的设计步骤,有文物、UML等。当然,TDD也有设计,但没有单独的设计步骤。这可能会导致项目经理不高兴,因为没有一个单独的时间桶来计费“设计”小时数。 - John Saunders
@John - 过时了吗?也许是,但几乎所有的业务分析师都会告诉你,这仍然需要很大一部分时间。我在一家小型、技术先进的公司工作,我们仍然使用类图来设计我们框架的部分。 - womp
所有那些BA们都还没有告诉我需要进行类设计。也许他们太害怕告诉我了? - John Saunders

6

我的课程设计真的应该不断地通过修改测试来完善吗?

是的。

TDD是不是意味着不考虑类的设计?

绝对不是。它意味着在编写测试和其余代码的过程中思考类的设计。类的设计贯穿于红-绿-重构的TDD生命周期中。


5
我认为(即使是TDD纯粹主义者也这样认为),通过编写测试来设计应用程序的程序员已经对设计和架构有了一定的了解。否则,您只能通过写测试来放任任何设计原则而使自己陷入编程混乱和无政府状态。
因此,一个“先测试”的开发人员已经对他的最终类结构有了一个相当好的想法,而这个愿景会在他编写测试时指导他。

虽然我同意开发人员应该理解设计原则,但我认为测试可以帮助指导你的设计。例如,松耦合应该自然而然地出现。 - TrueWill

1
TDD(测试驱动开发)是让测试来引导你的设计,包括类的设计。这是有价值的,因为测试旨在证明代码“有效”。这意味着你将得到一个能够工作的程序的类设计,而不是一个可能工作也可能不工作的程序的类设计。

1

我认为平衡的方法是你需要采取的。首先,对你的领域进行类建模,因为没有它们,你甚至不知道要测试什么

然后,你可能会创建这些类的存根或框架,其中大部分实现为空,只是让你编写一些测试结构。

完成这些步骤后,你的测试用例很可能会揭示出原始设计中不存在但却被发现必要的新方法/类/属性。


0

平衡的方法是正确的道路。

然而,平衡是由测试需求推动的。

你可以勾画出可能的类和层次结构。但是,在编写太多代码之前,你需要通过(1)考虑可测试性和(2)编写测试来驱动设计。

为了使你的测试甚至能够编译,你需要一些类定义。它们不必工作,但必须编译。

在少数情况下,你的类可能非常简单,你实际上需要先编写所有(或几乎所有)的类。


0

TDD是关于设计的!因此,通过进行TDD,您可以确保您的设计完全可测试。

此外,“平衡方法”是我认为应该采用的方式。您已经知道了高级别的架构,而TDD将推动这种架构变得可测试。

编辑: 虽然,如果您只想练习TDD,我不会采用“平衡方法”。我会采用“baby steps”和编码Dojos来进行TDD。


0

TDD倾向于使用运行代码具体地思考和实验类设计,而不是用铅笔和纸张抽象地思考。

两种方法都有用。即使是最狂热的TDD信徒有时也会使用铅笔和纸张(或者白板),以及BDUF-ueber-alles类型也会偶尔打出原型。问题在于你倾向于哪一种:沉思者还是更加实践?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接