Subverting TDD as a design tool

So TypeMock can now mock DateTime.Now.  Replacing the functionality of DateTime.Now, which is an external dependency, was one of the first issues that taught me the value of TDD.  With TypeMock replacing DateTime.Now, I get all the benefits of unit testing, but none of the benefits of TDD.  Yes, my code is now “testable” in the sense that I can now write a unit test against my code, but I’m using Jedi mind-tricks to do so.

TDD combines example-driven, client-first development with the icing of providing a safety net of providing executable specifications to lock down existing behavior.  For me, the real benefit of TDD is the former, much more than the latter.  TDD tells me exactly where my design is bad, as tests that are hard to write belie a design that is hard to work with.

When I first hit the “DateTime.Now” problem, TDD led me down a path that forced me to invert dependencies.  Instead of an opaque dependency on DateTime.Now, I had an explicit relationship between that class and its dependency through an IClock interface:

public PunchClock(ISystemClock clock)

From the standard external system dependencies such as clock, files, configuration and so on, I’ve used the dependency inversion principle everywhere inside my codebase.  Why?  TDD and DIP tell me if my class is doing too much.  If my class is doing too much, it will be hard to understand, change and maintain.  In my experience, TDD is by far the most efficient tool at showing me deficiencies in my design.  It shows me not only problems in design of individual members and even type and member names, but problems of my overall architecture.

If I have a legacy system I need to change, there’s a whole book on techniques for doing so in a safe, responsible manner.  Changing legacy code is like camping – you always leave your campsite cleaner than when you found it.  But I still can’t understand why I would need a tool that subverts all of the indicators in a unit test of bad design.

Related Articles:

Post Footer automatically generated by Add Post Footer Plugin for wordpress.

About Jimmy Bogard

I'm a technical architect with Headspring in Austin, TX. I focus on DDD, distributed systems, and any other acronym-centric design/architecture/methodology. I created AutoMapper and am a co-author of the ASP.NET MVC in Action books.
This entry was posted in TDD. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • http://www.lostechies.com/members/colinjack/default.aspx colinjack

    DateTime.Now is one of the things I always find it boring to mock (IClock or whatever). To me TypeMock is definitely easy to misuse but to me it is the whole running with scissors thing.

  • http://www.beingnew.net justindavies

    When I read your post I had the same reaction – why on earth would you want to plaster over a symptom of bad design as opposed to rooting out the infection?
    But on second thoughts I can imagine some legacy systems being so monolithic that it is just too scary to poke in the guts and pull out those hard-wired dependencies – isolating DateTime.Now woujld allow tests to fake the current time without changing the innards.
    But it could so easily be an excuse to *never even try* and improve the code. Scary.

  • Paco

    I don’t think it’s good to inject everywhere. Par example in entities.
    I use something like this (I don’t know where I got it from):

    public static class Clock
    {
    public static Func Current = () => return DateTime.Now;
    public static DateTime Now { get { return Current(); }
    }

    And then I replace the func in current before each test.

  • http://jonathan-oliver.blogspot.com/ Jonathan

    How do you feel about injecting a time service into a domain entity? The dependency on the current time is a tricky matter because you don’t want to inject dependencies into your domain entities, but you don’t want them to depend on DateTime.Now.

  • http://www.lostechies.com/members/bogardj/default.aspx bogardj

    @Paco, Jonathan

    I go with the Func-y version for entities and such, I personally got it from Ayende.

  • Paco

    Why not everywhere

  • http://scottbellware.com Scott Bellware

    Jimmy,

    Kind of a point of order: It’s not code that is or isn’t “testable”; it’s design that is or isn’t testable.

    Even with TypeMock, the *design* isn’t testable. The reason is that the design can’t be made testable in and of itself without bringing in outside tools (design elements) to make it so. Testability is about whetehr something can be isolated without the need to introduce new factors, such as runtime profiling (TypeMock).

    TypeMock doesn’t make anything “testable” unless we opportunistically re-define what what colloquially and commonly mean by “testable”, which is what TypeMock as an entity continues to strive to do. I don’t think they do this nefariously. I honestly don’t think that the TypeMock folks have a reasonable understanding of what is meant by “testable”.

  • http://www.lostechies.com/members/bogardj/default.aspx bogardj

    @Scott

    Ah yes, design. That makes a lot more sense.

    @Paco

    Sometimes I want to make the dependency explicit and obvious.

    @Justin

    The Feathers book is chock full of safe dependency-breaking techniques. We use them quite a lot, even in new codebases.

  • http://neilmosafi.blogspot.com Neil Mosafi

    Couldn’t agree more, be explicit about what you depend on.

    Also imagine one day the requirement comes up to run a historical calculation, or to freeze the clock at the start of a message loop so all operations within that loop get the same time, and you will thank yourself for having abstracted that dependency.

  • miz

    forgive a dullard’s question: what exactly is being subverted in this specific case?

  • Jeremy Gray

    @Paco & Jimmy – This is purely anecdotal, of course, but I went down the static/Func combo route once and immediately regretted it. It allows for hidden dependencies to be taken over time and, far worse, was a great source of messy test code (you need to make sure to restore the real func after the test so it has to be gettable, your setup needs to back it up, push the replacement in, run the test, put the original back) that is prone to human error and results in indirect test failures that are dependent on order of test execution and can be difficult to diagnose. Easy to correct once located, yes, but at the cost of the aforementioned messy test code all over the place and for each dependency. :)

    ctor injection FTW! :D

  • http://www.lostechies.com/members/bogardj/default.aspx bogardj

    @Jeremy

    I’ve gone back and forth myself. It’s pretty straightforward to do double-dispatch with an IClock into an entity…but in some domains where time was _everywhere_, the Func made the most sense. I never worried about putting the replacement back in, however. That was never an issue for me.

  • Jeremy Gray

    @Jimmy – I hear ya. I go back and forth on this a bit myself, and suspect that there is a happy medium where certain things are just used so widely (and/or by types you’d rather not use ctor injection on) that statics/funcs may give the best result while using injected interfaces and their implementations for everything else.

  • http://sm-art.biz ulu

    How do you decide which dependency should be explicit? Which part of the framework is a “dependency”? We all depend on System.String after all..

    Knowing your dependencies is important, I agree, but what do you gain in this particular case?

    Sometimes you use DateTime.Now in just one method of your class. do you still use a constructor injection? That is, when you go the ISystemClock way.

    As for the Func way, isn’t it the same design as with DateTime.Now, only testable?