Does TDD mean not thinking about class design?
I am making a role playing game for fun and attempting to use TDD while developing it. Many of the TDD examples I see focus on creating the test first, then creating objects that are needed to get the test to pass.
For example:
[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));
}
So based on this I'll create the character cla开发者_如何转开发ss and appropriate properties/methods. This seems fine and all but should my class design really come out of continually refining my tests? Is that better than mapping out the possible objects that my game will need ahead of time? For example, I would normally think of a base Character class, then subclasses such as Wizard, Fighter, Theif.
Or is a balanced approach the way to go? One where I map out the possible classes and hierarchy I'll need but writing tests first to verify they are actually needed?
Should my class design really come out of continually refining my tests?
Yes.
Does TDD mean not thinking about class design?
Absolutely not. It means thinking about class design in the course of writing your tests, and the rest of your code. Class design is at play throughout the Red-Green-Refactor TDD life cycle.
I think you're missing the point of TDD. TDD is not about writing tests - it's about designing your classes to be testable. This naturally leads to a better design and implementation.
It sounds like you're doing it backwards.
Your steps should be:
- Design your domain model
- Design your classes
- Write some tests
- Implement some class logic
- Refactor your classes to make them more testable where necessary
- Repeat Steps 3-5
I think it's generally assumed (even by the TDD purists) that a programmer designing an application by writing tests already knows something about design and architecture. Otherwise you can just paint yourself into programming chaos and anarchy by writing tests to the abandonment of any design principles.
Consequently, a developer writing an application "tests first" already has a fair idea of what his final class structure will look like, and that vision guides him when he is writing his tests.
TDD is about letting the tests drive your design, including your class design. This is valuable because the tests are meant to prove that the code "works". That means you'll wind up with a class design of a program that works, as opposed to a class design of a program which may or may not work.
I think the balanced approach is the one you need to take. First model the classes of your domain, because without them, how do you even know what to test?
Then, you'll probably create stubs or shells of these classes, with mostly empty implementations, just to let you write some test structures.
Once that's done, your test cases will likely illuminate the need for new methods / classes / properties that weren't in the original design, but are discovered as being necessary.
A balanced approach is the way to go.
However, the balance is Driven by the need to test.
You can map out the possible classes and hierarchy. But, you'll need to drive the design by (1) thinking about testability and (2) writing the tests before writing too much code.
For your tests to even compile, you need some class definitions. They don't have to work, but they have to compile.
In a few cases your class may be so simple, you actually write all (or almost all) of it first.
TDD leans toward thinking about and experimenting with class design concretely using running code rather than abstractly with pencil and paper.
Both approaches are useful. Even hardcore TDD zealots use pencil-and-paper (or perhaps a whiteboard) at times, and BDUF-ueber-alles types will bang out the occasional prototype. The question then is where you tend to fall: ponderer or more hands-on?
TDD is about design! So doing TDD you will be sure that your design is completely testable.
Also, the "balanced approach" is the way to go IMO. You already know a high level architecture and TDD will drive this architecture to be testable.
EDIT: Although, if you want just to practice TDD I would not do the "balanced approach". I would just do TDD with "baby steps" and maybe coding Dojos
精彩评论