Our CodeBetter-mate Sam Gentile gave a truly great talk this evening at our ADNUG meeting. He covered a remarkable variety of topics related to Extreme Programming practices and tooling for .Net. I had to leave early to take a sick child off my wife's hands, but even so I jotted down about a dozen things I wanted to blog about.
Sam stated that most of his unit test cycles last no more than ten minutes from starting to write the unit test to the unit test passing. If your unit tests are regularly taking longer than 10 minutes, you probably need to rethink your approach and look for a different way. Long unit testing cycles and/or needing the debugger quite a bit are an indication that your code may not be cohesive or loosely coupled. Being able to get in a rhythm where you write fine grained unit tests in tight cycles is a good sign that your code/design is on the right track. I've started work on "Jeremy's Third Law of TDD: Test small before testing big" that'll expound on this topic, but for now my emphatic advice is to strive for fine grained unit tests. Both to make writing working tests easier and to enforce good coupling and cohesion.
Sam talked a bit about his struggle to reconcile the idea of being an architect with XP and creating an architecture with Continuous Design. While I think that book is still being written, I emphatically agree with Sam that architects should code. I certainly feel that my ability to positively impact a project is much greater when I'm coding. Code is important. Even if you don't accept the XP "Code is Design" idea, we could still agree that the quality of a "design" is definitely reflected by the ease of the coding. Good code, i.e. maintainable code that is cost effective over time, takes skill. Bad code results in support costs and opportunity costs because of the difficulty in extending the code. I think it's nearly insane to say that anybody is "too important to code" as one of my managers used to berate me when I was an architect. Invariably, much of the worst overengineered code I've had to deal with originated from an architect who never had to dogfood his design (the rest came from me in my Architect Hubris stage).
The simplest thing that could possibly work isn't a license to hack. Someone asked a question about whether XP was more focused on business value maybe to the exclusion of technical quality (sorry if I misinterpreted the question). The focus on delivering business value is probably the correct end, but good code/design/software backed with good build and test automation is a great means to the business value end. I buy into the whole "doing a good job is its own reward" thing a little bit because I think the "Software Craftsman" ideal is attractive. It's certainly more romantic than being a CMM compliant, plug compatible software engineer anyway.
There was some talk about an overdependence on Intellisense being a barrier to TDD adoption with some reference to Rocky Lhotka's TDD comments last week. I certainly don't like coding without Intellisense, but it's not a compelling reason to forgo TDD. If you'll let me get away with the term, the "Reverse Intellisense" ability of ReSharper and other refactoring tools to automatically create method stubs for missing methods offsets the lack of Intellisense for new code that's being specified in a unit test. Add in RhinoMocks to mock a brand new interface with strong typing and you have quite a bit of ability to model the interaction between classes in a unit test, then use ReSharper to generate the missing methods that are defined in the unit test. It may not sound like a big deal or even useful, but I've found it really makes TDD easier. I like to think of this sort of TDD design doing a UML sequence diagram in code. Behavior Driven Development is taking this idea much, much further (but it looks like it almost requires a dynamic language like Ruby or Python).
Refactoring is a grossly abused term. Refactoring is improving the structure of existing code while maintaining the same functionality, hopefully in a disciplined manner backed up by automated tests. You use refactoring to remove little code smells as you go and bigger refactorings to remove duplication and enable new changes. Telling management that you're just doing some refactoring to cover the fact that you're really doing an architectural rewrite is just plain lying. Shame on all of us who've ever played a shell game with "refactoring." One more thing, the phrase, "do it quick now and you can just refactor it later" makes my blood boil.
When the topic of Pair Programming came up, someone asked if pairing can reduce the amount of time it takes to bring new team members up to speed on a project. Pairing doesn't negate Brook's Law by any means, but my experience in this regard has been very positive, More so when either the existing or new team members are experienced with pair programming. Pairing is actually a bit of a skill that some of us (me) have to work on more than others.
All in all, it was a great session. Thanks for coming Sam and playing through pain.