This is the second of a series on Test Driven Development with Domain Driven Design. It would be in your best interest to start at the beginning before reading this post.
I’ve received a lot of feedback on the first post, via comments, instant messages, emails, and other conversations, all of it very good feedback, and encouraging me to continue with this. A lot of what I’m trying to do is to explore using this blogging medium in ways that can not be done with traditional print media (books and magazines). One of the benefits blogging offers over the other methods is the ability for the author to be themselves, and not have to worry about doing things in a perfect or pure style. The downside if you are a recognized expert, you have a responsibility not to confuse the masses.
So in order to try to help clear up what Test Driven Develop is I’m going to dedicate most of this post on that subject, and explain why I deviate from it, in certain cases.
The Test Driven mantra is (from Kent Beck’s TDD by Example):
- Red – Write a little test that doesn’t work, and perhaps doesn’t even compile at first.
- Green – Make the test work quickly, committing whatever sins necessary in the process.
- Refactor – Eliminate all the duplication created in merely getting the test to work.
So, using this style, a TDD purist would have like to have seen the following, instead of what I did:
- Create the blank solution
- Create the library
- Create the test library
- Write the first test. In this case, since we are using the PRISM CV spec, which is a spec written around a document format. Because the spec is all about creating an XML document according to the spec, the first test would be just that create a controlled vocabulary instance, and get the XML version of that instance, The code would look something like this:
- ControlledVocabulary Vocab = new ControlledVocabulary;
- XmlDocument Doc = Vocab.ToXml();
- Assert(Doc.InnerXml == “the xml according the example in the spec”)
- Obviously this will not compile, so we would need to create a ControlledVocabulary class and add a ToXml function.
- The test should now compile, but it will still fail since the ToXml function does work.
- Fix the ToXml function by hard coding it to return an Xml Document that matches the one found in the example in the spec.
- Test again, now we are Green.
- Refractor to eliminate the hard coding of a specific document.
- Write another test to create a different example of the document.
- Refactor and continue writing tests.
Unfortunately, this style has nothing to do with Domain Driven Design. It will work, as long as you come up with the correct tests, but even then, there is no focus on the Domain, just the tests. There’s the rub; you can’t be a slave to two masters. Either TDD or DDD can be your master, not both. One will have to be subservient to the other. To make matters worse, specs on creating XML documents focus entirely on nouns, with no thought given to the verbs. When you use TDD, it is the verbs that help you define your tests. In a spec like SVG, XHTML, or even PRISM CV, the verbs are implied, thus making it difficult to come up with good tests. But that does not mean you should abandon TDD, it just needs to be modified to fit within the domain driven world. Once you get beyond creating an initial, small domain skeleton (like in the first post), I’ve found that I can slide into a more TDD like methodology, since at that point the domain starts to ask its own questions, which I can then write test for, and then the write code to answer them. But the focus has to always be on the domain, not the tests. Meaning, have the domain drive the questions (and tests), not have the tests drive the domain.
Anyone that has done TDD long enough will start to learn the art of coming up with the real tests, and not just the obvious ones. The problem is that overcoming the initial hurdle of only testing the obvious is hard to accomplish on your own. Most development teams don’t have the luxury of already having an experienced TDD developer to help mentor the rest of the team, so they get tend to get burned at the first hurdle, and then give up on TDD, which is a shame. So I tend to push folks down the Unit Test Driven path first, and then slowly have them migrate to the test first approach (TDD). Once they have mastered the art of testing, and get comfortable with refractoring, then you set the Domain Driven Design hook. TDD has a tendency to create muddled object models, because the focus is on the test. They start to notice how hard it is to actually use their object models, and are almost begging for a way to manage them. This is the point I call spaghetti object programming. You have all these object out there with no clear idea of their role within the big picture. Sometimes there are some attempts at using design patterns, but mostly they are never implemented correctly and only relate to the pattern in name and nothing else. But that is a story for another day.
I’ll continue on with developing the code in the next post, but for now it is time to let some of this all sink in, and hopefully get some more of that great feedback.
Technorati tags test driven development tdd domain driven design