Title Image

Don Xml's Grok This

The home of Don Demsak
Welcome to Don Xml's Grok This Sign in | Help
in Search

This Blog

Syndication

Site Sponsors

DonXml's All Things Techie

Reality Blogging – Test Driven Development with Domain Driven Design – Part 2

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:

  1. Create the blank solution
  2. Create the library
  3. Create the test library
  4. 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:
    1. ControlledVocabulary Vocab = new ControlledVocabulary;
    2. XmlDocument Doc = Vocab.ToXml();
    3. Assert(Doc.InnerXml == “the xml according the example in the spec”)
  5. Obviously this will not compile, so we would need to create a ControlledVocabulary class and add a ToXml function.
  6. The test should now compile, but it will still fail since the ToXml function does work.
  7. Fix the ToXml function by hard coding it to return an Xml Document that matches the one found in the example in the spec.
  8. Test again, now we are Green.
  9. Refractor to eliminate the hard coding of a specific document.
  10. Write another test to create a different example of the document.
  11. 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

Published Sunday, December 18, 2005 8:49 PM by donxml

Comments

Scott Bellware said:

Don, you’re a respected friend, but I wouldn’t want that to stop me form ripping on this post… :)

> …TDD purist would have like to have seen the following…

As long as we can assume that by “purist” you mean someone who is actually engaging in TDD practices in fact rather than merely in name.

> 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

If you were writing tests that tested nothing, then I’d go along with this assertion.

> Either TDD or DDD can be your master, not both. One will have to
> be subservient to the other

I’ve been doing both together for about a year now. I’ve never seen a case in my work where one is subservient to the other. I would assert the possibility that in skipping over some of the more subtle aspects of TDD in your own work that you might have missed some important learning opportunities.

> When you use TDD, it is the verbs that help you define your tests

Depends on what you’re testing. If you’re testing state then you might not have little behavioral or interaction testing to do and you’ll end up with tests that necessarily have little to do with verbs. To wit, noun/verb analysis can be proven time and again to produce bloated systems over the organic and evolutionary design inherent in TDD.

> 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

I seriously doubt it. It just means that you’ve got more state testing to do. No change to TDD process is necessary – you just follow the process to arrive at state-based tests. This is probably the easiest kind of stuff to do with TDD. The barrier to entry on this kind of stuff is at its lowest here. This is TDD for absolute beginners and is a perfectly natural place to demo TDD practice.

> 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

I find that the questions typically start at the tests – especially if the class factoring is emerging from testability-by-design. If you’re just doing wrote implementation against a model that you’ve already committed to before laying down the test harnesses that will drive design, then I can see how you might end up at this assertion.

> Meaning, have the domain drive the questions (and tests), not have
> the tests drive the domain.

Fair enough approach for plain old automated testing, but this is really quite reminiscent of MSDN’s ill-fated Guidelines for Test-Driven Development Document. I don’t see “TD” in this flavor of “TDD”.

> 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

Indeed. But the reason they give up is often due to laying down functional code before test code and arriving at code that isn’t testable by design and thus harder to write and maintain tests for. Rigorously following the TDD practice especially for the first several iterations is what institutes the awareness of the causes of and the knowledge to mitigate these risks. Doing a candy-coated version of TDD at the outset gives a team no better than a 50-50 shot at arriving at a sustainable testable-by-design practice – essentially reducing the chances of TDD success to a coin toss whose potentials are subject to random forces of chance and coding whim rather than by a predictable, methodological approach.

> 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

TDD and DDD together should have no impact on the realism of a domain model. TDD will just cause the software implementation to be even more sustainable.


December 18, 2005 11:06 PM

Toby Henderson said:

Dude, you're asking for more FLAMING !
December 19, 2005 6:59 AM

Don Demsak said:

Toby - Sometimes the flames are what I'm looking for. Actually, not flames, but feedback, but you get the point.

Scott, Where in the 3 step mantra of TDD is the designing of the domain? It is buried in step 3, refactor. You have become such a master at TDD and DDD that you might be doing some DDD implicitly (without even thinking about it) at the TDD step 1, which is not something ever mentioned in Beck's book (which I would assume is the bible of TDD). This will lead me into the next post.
December 19, 2005 7:38 AM

Scott Bellware said:

Nothing in TDD says that you can't do some agile modeling - either with a whiteboard or a UML-as-sketch too, or to capture the model with stories. When the model is transformed from some high-level design artifact into code, TDD takes over and fleshes out the low-level design concerns that can't be expressed or often even discovered with high-level design.

This is one of the most beneficial aspects of TDD. The process you describe would risk not harvesting key low-level design opportunities. And again, these are opportunities that you would not see in high-level design artifacts. You may not even know that you've missed them. You'd just plow into the job code-first and commit your mind to the representation that comes of doing code-first transformation of high-level design artifacts into low-level design artifacts. TDD brings a high-level-design to low-level-design transformation practice.

You may not ever know what you missed in not stopping to smell the code. You may end up right at the inherent optimal design, but there’s an inherent risk in not arriving there.

You’re depiction of TDD in these posts smells a lot like a Alpha-Programmeritis TDD anti-pattern. Maybe it’s not – I’ve got no idea whether it’s so or isn’t so. I’m just raising a flag to anyone reading this blog series. The depiction of TDD isn’t necessarily representative of TDD practice. It might indeed work for this particular project at this particular point in this project, but my work with TDD and DDD doesn’t cause me to skip over the TDD practices because I assume that I got high-level design right the first time.

TDD is there to challenge my assumptions about the model as I’m transforming it into code. I know that I’ve been wrong on at least half of the occasions where I’ve plowed high-level design into code without doing TDD. I don’t trust my high-level design assumptions to be correct for anything other than high-level design, and since high-level design artifacts aren’t executable, they need to be transformed into a low-level artifact that is executable. I trust TDD to vet my assumptions and to produce code that takes design issues into account that I couldn’t possibly have visibility into by inspecting high-level design artifacts.

I’m getting a bit freaked out reading your assertions about TDD and DDD because they don’t map to my own experiences and my Alpha-Programmer side is chomping at the bit. And certainly my TDD trainer and evangelist personalities are roiling in counting up the damage control costs for having to undo what I see as broad-based communication of possible TDD misconceptions and misrepresentations in these posts.

It’s quite possible that I’ve got it all wrong – but it’s equally possible that you do as well. I’m suggesting that you tread lightly on assumptions and sweeping assertions about your experience with TDD and DDD. It might be that TDD simply hasn’t settled itself deeply enough into your bones so that the practice maintains its integrity when mixing it with other design disciplines. There are certainly other disciplines that are often in conflict with TDD process – code generation comes to mind – but I don’t see either from my own experience of from the nature of DDD practice why TDD isn’t applicable and effective at the outset of the implementation.
December 19, 2005 1:48 PM

Jeffrey Palermo said:

Microsoft has replaced Guidelines for Test-Driven Development with a new article that I think hits the mark. :)

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnvs05/html/GuidelinesforTDD.asp
May 30, 2006 12:10 PM

Angel "Java" Lopez said:

Hola gente! Tengo en mi colección de enlaces, en mis apuntes para mis charlas, algunos enlaces sobre
December 9, 2006 2:20 AM
Anonymous comments are disabled

About donxml

I’m an independent consultant, specializing in .Net solutions architecture, based out of New Jersey who also doubles as an evangelist for XML, Domain Driven Design, enterprise architecture and .Net. I do not work for Microsoft, the W3C or any other big company that you may know of (at least not yet). I’ve been an indie for over ten years, and although I’ve been tempted a couple times to take a job with companies like Microsoft, I’ve haven’t found something better than my current situation. I work mostly with the large pharmaceuticals that are based here in New Jersey, and usually find myself on long term contracts. Definitely not the prototypical indie consultant, but it lets me dedicate time to my non-income generating activities like the developer community stuff, plus financing open source projects like XPathmania and MVP-XML. If you would like to talk to me about doing some contract work, just contact me via the contact page. My rates vary widely, depending on lots of different variables, but mostly distance from Jersey, and type of work. Plus, I’ve been known to donate some of my code for various projects.
Powered by Community Server, by Telligent Systems