Saturday, February 28, 2004

TDD vs Architecture

Someone recently asked me on the OT mailing list about my experience with test-driven development (TDD). They were concerned that it seemed to advocate throwing away all the careful architectural design work we've been taught is a good thing, in favor of just attacking the problem piecemeal. Here was my response:

Disclaimer: I'm not an XP expert. I haven't read the XP literature. My only qualification to say anything about it is that I've been using it for a few months, and have noticed a difference in my satisfaction with the code I produce.

First of all, you have to ask yourself if you've been successful with your architecture-driven approach. If the answer is "yes", then why are you considering changing things? I find that XP's main feature seems to be "ruthless practicality", so if you've already got something that works, go with it.

Second, architecture is basically a set of pictures (and a lot of thinking) that you draw for guidance before you start coding. Nothing about that is incompatible with TDD. Get an idea of how you want to do something, then write the tests that assert that your design does it, then write the code that makes the tests pass.

One of the ways I've started to think about tests is as a way of expressing requirements. What I particularly like about that is that I'm expressing them in a highly precise, machine-readable, unambiguous language with which I am already familiar...C#.

Another thing to consider: designs done in the abstract are typically at a higher level than the API level. Or if they are at the API level, they rarely express pre- and post-conditions. Tests do both, so they really magnify your design documentation, bringing it to a lower level.

Now, it's true that traditional architecture and TDD tend to emphasize different things. Most people wind up doing architectures that attempt to abstract all the functionality you *might* need. TDD takes a more just-in-time approach, focusing on only writing the functionality you

*actually* need, *right now*. Of course, test-first can be done even for highly abstract requirements, and designs can be written to a set of practical requirements - so those facets are orthogonal. It's just that they tend not to be.

Both approaches have their place. I just find that I so rarely know exactly what my requirements before I start, that it's difficult to start with an abstract vision. A set of tests is also a set of use cases, and expressing them so formally (i.e. as C# code) allows me to work out details at the level I care about: the API design.


  1. I agree with what you are saying. I find that an architecture driven approach is mainly useful for conveying things at a high level to other team or organization members.

    TDD has been what I've tried to shoot for because it makes me feel safer. (Did I actually just type that? Bump my dork rating up by 20, please.) The problems I've run into in trying to implement it in my own work so far are two, namely:

    1 - Time constraints force me to push my testing code aside, instead relying on "sanity check" type tests, and putting more burden on our QA department.

    This feeds into

    2 - When a defect does happen, I write some test/debug code around it to make sure it can be more easily identified the next time it happens. Unfortunatly this is kind of a "closing the barn door after the horse got out" approach.

  2. Frankly, I think that ditching testing because of time constraints is shortsighted. You're basically just hoping that what you write will work. And since you do TDD, you know how incredibly rare it is that what you write works the way you expect it to the first time. And I'm not just talking about compiler errors or crashes at runtime, but all the times when your unit test fails and you're like, "But that should totally work!"

    That came out being a little bit more accusatory that I meant it to. In fact, I assume that when you say "time constraints" you mean "my boss is telling me to ignore testing and just do it". Can't help you much on that one. ;)

  3. "I assume that when you say "time constraints" you mean "my boss is telling me to ignore testing and just do it". Can't help you much on that one. ;) "

    Hahaha, yep, that would be correct. :)

  4. Although, honestly its more like my boss telling me "get something out the door that we can show marketing by 10am tomorrow even if its loaded with defects". (we're talking working overnighters here in the more extreme cases) Which is something we can do, but results in a lot of work for QA that would be totally shouldn't be needed. We the devs are pounding our heads against the desks seeing how inefficient it is to do things like that, however sometimes I fear the department leaders see it at some level as allowing them to request more resources, hence being bigger wheels, so efficiency arguments tend to fall on deaf ears. I guess I'm coming to realize that my dream of being a software developer would put me outside of the reach of office politics and into a realm of pure logic just ain't gonna happen in the real world. ;)

  5. Although it has other drawbacks, one of the things I like about being an independent consultant is that it tends to displace you from politics a little. Some of that is psychological "I don't work here", but some of it is real, too, since you tend not to get told about everything that's going on.

    But of course, the real world finds lots of other ways to intrude.