What I’ve Learned over the Last Five Years

While (procrastinating) cleaning off old files on my computer I found this small essay I wrote last spring that was never published.  This is an introduction to this talk online.

You want your codebase to last right? It’s one thing to dash off some throwaway code to solve an immediate problem, but quite another to craft a codebase that can evolve over time to handle new requirements. A long lived codebase must change as the requirements change, the underlying platform evolves, and the expectations of the users increase.

I’ve learned quite a bit about this issue of long lived codebases as the principal developer of an open source tool named StructureMap for Dependency Injection and Inversion of Control with .Net. The original release of StructureMap happened all the way back in 2004, but development has continued ever since. At this point, there is very little code remaining from the initial release, and the current functionality set bears little resemblance to the rudimentary features of the 2004 timeframe.

The biggest source of StructureMap changes has been to reduce the user’s friction in configuring the tool. Our expectations for framework usability have changed dramatically over the past five years. In 2004 we were enamored with using Xml configuration as a way to create dynamicism and extensibility in our software systems. StructureMap circa 2004 could only work when it was fed copious amounts of repetitive, error prone Xml configuration. Today, the “Xml Hell” style of framework configuration is unacceptable to most users. Instead, I’ve had to streamline the Xml configuration and introduce new a programmatic Domain Specific Language for configuration that is easier to use. Going even farther, many open source tools in .Net are adopting “Convention over Configuration” approaches to further reduce the mechanical effort of configuration.

My long lived system has had to change over time, and it’s very likely that yours will too. It turns out that the design decisions we make, the way that we write our code, and the manner in which we express and organize our unit tests will have a substantial impact on the efficiency of changing a codebase and the effective lifespan of that codebase to keep up with those changing needs.

At one point last year my continuing work on StructureMap was being hindered by the internal structure. I finally realized that the key abstractions inside StructureMap no longer matched the newer requirements. My progress on StructureMap improved dramatically after I first restructured the design to more appropriate abstractions.

In many cases, I have not been able to complete changes until I refactored to clean up code duplication or decrease harmful coupling by more closely following the “Law of Demeter.” The point being that “design in the small” is significantly important to the continuing health of a codebase.

Lastly, I’ve seen observed that Test Driven Development is a fantastic tool we can use to support the future evolution of our systems – except when it’s applied badly. One of my biggest challenges in evolving StructureMap over the years has been brittle unit tests that were too tightly coupled to the original implementation and automated tests that were very hard to understand and troubleshoot when a code change broke those tests years after the original writing of the test. My negative experiences with unit tests in StructureMap have led me to finally appreciate the benefits of Behavior Driven Development (BDD). I believe that adopting the BDD style of expressing specifications and organizing tests around features and behaviors has improved my development experience.

About Jeremy Miller

Jeremy is the Chief Software Architect at Dovetail Software, the coolest ISV in Austin. Jeremy began his IT career writing "Shadow IT" applications to automate his engineering documentation, then wandered into software development because it looked like more fun. Jeremy is the author of the open source StructureMap tool for Dependency Injection with .Net, StoryTeller for supercharged acceptance testing in .Net, and one of the principal developers behind FubuMVC. Jeremy's thoughts on all things software can be found at The Shade Tree Developer at http://codebetter.com/jeremymiller.
This entry was posted in Uncategorized. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • http://r r

    d

  • Eyston

    @Jeremy

    I don’t know why, but it was really bothering me. I think I’ve seen a few videos where both Martin Fowler and Kent Beck talk about how they define themselves as ‘classicist’ testers and it was like ‘who am I to disagree?’.

    Still going through the NDC videos. Currently on your ‘Software Design and Testability’ video. Looks like there is a ton of TDD videos from NDC. It would have been interesting to see what the day long Scott Bellware session was like (no vids…). I need to budget in a conference a year :)

  • http://codebetter.com/members/jmiller/default.aspx Jeremy D. Miller

    @Eyston,

    I hate the distinction between “classicist” vs. “mockist” testing. The decision to use state-based testing vs interaction based testing is a case by case decision, even within the same feature.

    I actually don’t think the actual tooling is all that important, and NUnit/MbUnit is just fine.

    @Jeff,

    I don’t actually think that BDD is really that different. Good resources on TDD are still helpful. I still think the hardest part is the design aspect anyway.

  • Eyston

    I started using MSpec and specification style testing (I dunno if its bdd or not) and found that how I was testing was changing. I then read Martin Fowler’s stub vs. mocks paper and it seemed I was writing much more mocking tests versus classical tests. Is this a feature of BDD / Specification style testing? Or can you write classical type tests and still do BDD / Spec?

    Since that project I started to use Gallio as a test runner (my boss is cheap and won’t buy Test Driven .NET and I got tired of using MSPec console runner to hunt through >100 tests to see which broke) so am using NUnit and MbUnit but want to keep the MSpec style of sut / context / tests.

  • http://http://agileconsulting.blogspot.com Jeff Anderson

    Jeremy,

    Your experiences with test driven development mirror my own, I still think it’s a fantastic approach that is essential to evolving code.

    But behavior driven development certainly works a lot better…

    what would be your most recommended resource that you would use to help newbies to bdd get up to speed?