Monday, August 16, 2010

Agile 2010 - Day 1 - Evolutionary Web Development with ASP.NET MVC (Part 1)

Presented by Brad Wilson, Senior Developer Microsoft ASP.NET MVC Team

Part 1 – TDD

The first session for me of the Agile 2010 Conference in Orlando was the “Evolutionary Web Development with ASP.NET MVC” given by Brad Wilson (@bradwilson). The first 90 minutes of the three-hour session was dedicated to Test Driven Development (TDD) basics. Brad and his sidekick Scott not only demonstrated the fundamentals of how testing drives design, but gave a good example of how paired programming works. For me, the jury is still out on the effectiveness of pairing, but then I’ve never been in a team that it was encouraged or embraced so that it could sway me.

Although TDD isn’t practiced at my current company, I do use TDD in my personal programming projects and it was a good reminder for me of the fundamentals. Repetition is what helps to keep our skills fresh

A few key points from the first half that resonated with me were:

1) When developing, think in terms of component development that facilitates isolation making it possible to test your units in isolation

2) Use your tests to drive public API’s – tests should also only exercise publicly visible behavior

3) Your tests should be small, simple, and fast – makes it easier to run them over and over again. If anything, I’d add that the tests should also be repeatable though that wasn’t discussed (maybe it was just that obvious).

4) The basic workflow in TDD is – Green –> Red –> Green. Although, I’ve often seen the workflow start with Red where my tests initially fail until I provide the requisite implementation to make them pass. In fact, re-reading James Newkirk’s book on TDD starts off with the Red->Green->Refactor workflow.

5) Refactor, refactor, refactor – if you aren’t regularly refactoring, your code probably (almost surely) has a lot of smells. The beauty of the unit tests is that it provides the safety net and gives confidence that while refactoring you aren’t breaking the contract that you promised to provide in your implementation.

6) Replace your dependencies with “test doubles” (mock objects) – Brad’s demo touched lightly on Moq (http://code.google.com/p/moq/), which I hadn’t used before. It looks like a good framework and I’ll have to experiment with it myself to see, but having used NMock, and others, it appears to address some of their shortcomings (like mocking classes not just interfaces).

7) TDD is more about design than it is about testing. The conscious act of creating tests that define the specifications for the public API is a radical departure for anyone that has never tried TDD. It can represent quite a leap in style and thought process, but one that can yield excellent results. Most people that aren’t practicing TDD say they believe that the process would slow them down. I believe (though I have no hard evidence to support my argument) that it’s quite the opposite. If nothing else, it certainly yields a cleaner design that makes maintainability higher reducing time over the long haul.

8) A side effect of #7 is that the unit tests aren’t the goal; they’re an artifact of the process. This can be a distraction for some – myself included. Until you realize that the unit tests are a means to an end, you may lose focus on what they are supposed to be doing for you: a.) driving your design and b.) providing a safety net for when you refactor (you want to refactor don’t you?).

9) Refactoring should focus on small, incremental changes. In my second session of the day (which I’ll cover in another post), Joshua Kerievsky (pretty sure it was him) spoke up about the importance of refactoring to patterns to improve overall design.

I came away with a few little catchy tidbits as well.

1) xUnit – uses the word “fact” to avoid the stigma that developers have against testing. I began experimenting with xUnit after the conference and find it equally usable to NUnit, but it also emphasizes some best practices that NUnit missed (as James Newkirk’s blog pointed out, xUnit was developed after some experience with “programmer testing”).

2) “Do the simplest thing that can make it work.”

3) TDD drives a very small incremental development style. Add test, watch it fail, add code, watch it pass.

4) In the real world you would write the acceptance tests first – BDD then TDD. The acceptance tests will fail for quite some time.

5) TDD tests are the documentation for other developers. BDD tests are the documentation for the business.

6) @bradwilson, “TDD is like the scientific method.” You form a hypothesis, write a test to represent it, and then see if your assumption is correct.

7) The basic test structure should be similar to this:

// Arrange
Set up the conditions for the test

// Act
DO whatever work is required

// Assert
Validate that the results are what you expected

See (http://c2.com/cgi/wiki?ArrangeActAssert)

That pretty much sums up the first part of that session. In closing, the important takeaways were using TDD and refactoring to drive your designs and improve code readability and overall health. Though this session talked about using mock objects as a means to loose coupling, a later session with Arlo Belshee discussed other design patterns that can also help to achieve loose coupling, but that don’t necessarily have the same overhead that mocks bring. I’ll cover more on that in a future post.