Monday, January 14, 2008

Making the permanent move

I'm getting pretty tired of cross-posting, so I'm making the permanent move over to Los Techies.  After all, if I get a free t-shirt:

Then the least I can do is stop dipping my toe in the pool and just jump in.  Cross-posting is for chumps anyway.

You don't need to update your feeds, except the feed now links to Los Techies.  This will be my last post on the blogspot site (sniff, sniff), and while you treated me well blogspot, your name doesn't rhyme with a tasty, tasty beer.

Thursday, January 10, 2008

Converting tests to specs is a bad idea

When I first started experimenting with BDD, all the talk about the shift in language led me to believe that to "do BDD" all I needed to do was to change my "Asserts" to some "Shoulds".  At the root, it looked like all I was really doing was changing the order of my "expected" and "actual".

In my admittedly short experiences so far, I've found that BDD is much more than naming conventions, language, and some macros.  For me, unit testing was about verifying implementations while specifications were about specifying behavior.  Although I'm not supposed to test implementations with unit testing, conventions led me down this path.  It's easy to fall into the trap of testing implementations, given constraints we put on ourselves when writing unit tests.

Starting with tests

Typically, my unit tests looked something like this:

[TestFixture]
public class AccountServiceTests
{
    [Test]
    public void Transfer_WithValidAccounts_TransfersMoneyBetweenAccounts()
    {
        Account source = new Account();
        source.Balance = 100;

        Account destination = new Account();
        destination.Balance = 200;

        AccountService service = new AccountService();

        service.Transfer(source, destination, 50);
        
        Assert.AreEqual(50, source.Balance);
        Assert.AreEqual(250, destination.Balance);
    }
}

When I wrote the implementation test-first, I first got a requirement or specification from the business.  It sounded something like "We want to be able to transfer money between two accounts".

Before I started writing my tests, I had to figure a few things out.  Our naming conventions forced us into a path that made us choose where the behavior was supposed to reside, as we named our test fixtures "<ClassUnderTest>Tests".  In the example above, we're testing the "AccountService" class.  Additionally, our individual tests were named "<MethodName>_<StateUnderTest>_<ExpectedBehavior>".  We took these naming conventions because it organized the class behavior quite nicely according to members.

Converting to BDD syntax

I wanted to try BDD, so the quickest way I saw to do it was to change the names of our tests and switch around our assertions:

[TestFixture]
public class AccountServiceTests
{
    [Test]
    public void Transfer_WithValidAccounts_ShouldTransfersMoneyBetweenAccounts()
    {
        Account source = new Account();
        source.Balance = 100;

        Account destination = new Account();
        destination.Balance = 200;

        AccountService service = new AccountService();

        service.Transfer(source, destination, 50);

        source.Balance.ShouldEqual(50);
        destination.Balance.ShouldEqual(250);
    }
}

Now that I see the word "Should" everywhere, that means I'm doing BDD, right?

Just leave it alone

BDD is much more than naming conventions and the word "should", it's more about starting with a context, then defining behavior outside of any hint of an implementation.  When creating my Transfer test initially, before I could start writing ANY code, because of our naming conventions I had to decide two things:

  • What class does the behavior belong
  • What method name should be assigned to the behavior

But when writing true BDD-style specs, I don't care about the underlying class or method names.  All I care about is the context and specifications, and that's it!  If I was writing the Transfer behavior BDD-first, I might end up with this:

[TestFixture]
public class When_transfering_money_between_two_accounts_with_appropriate_funds
{
    [Test]
    public void Should_reflect_balances_appropriately()
    {
        Account source = new Account();
        source.Balance = 100;

        Account destination = new Account();
        destination.Balance = 200;

        source.TransferTo(destination, 50);

        source.Balance.ShouldEqual(50);
        destination.Balance.ShouldEqual(250);
    }
}

The key difference here is nowhere in the fixture nor the test method name will you find any mention of types, member names, or anything that hints at an implementation.  I'm driven purely by behavior, which led me to a completely different design than my test-first design.  In the future, if I decide to change the underlying implementation, I don't need to do anything with my BDD specs.  When I've decoupled my implementation of behavior completely from the specification of behavior, I can make much more dramatic design changes, as I won't be bound by my tests.

I've also found I don't modify specifications nearly as much as I used to modify tests.  If behavior is changed, I delete the original spec and add a new one.

So don't trick yourself into thinking that you need to modify your tests to become BDD-like.  Just leave those tests alone, they're doing exactly what they're designed to do.  A single context is likely split across many, many test fixtures, so it's just not an exercise worth undertaking.  Start your BDD specs fresh, unencumbered from existing test code, and the transition will be much, much easier.

Stop the Flash insanity

More and more it seems high-profile websites are using Flash as a mechanism to deliver essential content.  In extreme cases, such as mycokerewards, the entire site is built on Flash.  Ads in websites, which you used to be able to ignore, now use Flash to replace the entire screen contents, screaming at you to "GO SEE CLOVERFIELD!!!".

My dev machine is a fairly hefty beast, but it still has a hard time processing Flash-only sites:

I'm not even doing anything in the Flash-only site except that I'm looking at it.  It's doing some ridiculous, pointless animation of bubbles floating around, and that requires 40% of my dual-core machine's resources.  When I look at this site on a single-core machine, I pretty much can't use FireFox any more, as it's completely consumed with those floating bubbles.

Sites that used to be relatively easy to get around are now just annoying, like ESPN.com, which are starting to rely heavily on Flash to deliver actual content.  Please don't start playing some highlights video if I'm just going to your homepage, I really don't like Stuart Scott screaming "BOOYAH" to me through my speakers.

If anything, Flash should be use to complement content, but not be the actual content.  To deal with normal annoyances, I go back and forth between these two FireFox add-ons:

  • Adblock Plus (blocks ad content, but not other Flash content)
  • Flashblock (blocks ALL Flash content, letting you opt-in to anything you want to see)

Flash for delivering ad content is perfectly fine, as long as it's non-intrusive and non-resource intensive.  Flash for delivering site content is just plain heinous, and I hope Santa delivers coal in those perpetrators' stockings next year.

Wednesday, January 9, 2008

More on Scrummerfall

A couple of comments have led me to think that I didn't explain what it is.  Let's review waterfall phases:

  • Requirements specifications
  • Design
  • Implementation
  • Integration
  • Testing
  • Deployment

Each of these has a gated exit, such that to exit one phase, you need to meet certain criteria.  For example, to leave "Design" phase, you have to have your detailed design with estimates signed off by developers, analysts, and the customer.  You cannot enter Implementation until you have finished design.

Scrummerfall still uses a phase-based methodology, but uses iterations for the "Design" and "Implementation" phases.  Testing is done as unit tests during development, but QA is not involved until the actual Testing phase later.

Scrummerfall is easier to introduce in companies heavily invested in waterfall, as it's only one group (developers) that are actually changing how they work.

Scrummerfall also makes two assumptions that become more invalid and costly the larger the projects are:

  • Requirements don't change after Design
  • Integration, Testing, and Deployment are best done at the end

Now just because Agile doesn't have gated phases for these activities doesn't mean they don't happen.  Design and requirements gathering still happen, as do release planning, testing, deployment, etc.  The difference is that all of these activities happen each iteration.

This is very tough in fixed-bid projects, which assume that requirements, cost, and deadline don't change.  There are alternatives to fixed-bid projects, which I won't cover here, that provide the best of both fixed-bid and time-and-materials projects.

With Agile, you don't do a "Testing" iteration and a "Design" iteration.  That's lipstick on a pig, you're still doing waterfall. 

So how do you avoid Scrummerfall if you're trying to introduce Agile into your organization?  The trick is to sell the right ideas to all of the folks involved.  If it's only developers leading Agile adoption, chances are you won't get too far past TDD, continuous integration, pair programming, and the rest of the engineering-specific XP practices.

Get buy-in from an analyst, a PM, a tester, your customer, and your developers.  You won't have to convert all of the analysts and PMs, just the ones working on your project.  Remember, each person needs to see tangible business value from the changes you are proposing.  I tend to target management for Scrum and developers on XP, because although it's easy to get everyone to agree on values and principles, the concrete practices vary widely between the different roles.

Tuesday, January 8, 2008

For the record

This is not Scrum:

  • Planning
    • Release planning
    • Backlog creation
    • Architecture and high-level design
  • Development sprints
    • Design
    • Code
    • Test
  • Conclusion
    • System integration
    • System test
    • Release

This is Scrummerfall, where we still do a phase-based waterfall model, but do iterations during the "development" phase.  I hear the word "hybrid" thrown around a lot in the above model.

This isn't the cool kind of hybrid, like a Prius or a Liger (pretty much my favorite animal).  It's more of the Frankenstein hybrid, where it looks good on paper, but in the end you need the village mob with pitchforks and torches to drive it away.  Afterwards, the villagers have a bad taste in their mouth regarding science, so they banish it instead of booting out the mad scientist.

One of the key benefits of agility is the ability to respond to change through feedback.  If the backlog is set in stone before my "development sprints" start, how do I change the backlog once business requirements and priorities change, which they inevitably will?  There is no mechanism to respond to change in Scrummerfall, dooming your project to quick failure, but now you get to blame Scrum.

Another disaster waiting to happen is waiting until the end to do system integration.  I think everyone learned that "it works on my computer" doesn't fly very far once you start collecting a paycheck.  Customers demand the software works on their machine, not yours.  So why wait until the very end to do the riskiest aspect of development, when cost of failure is at its highest?  It pretty much guarantees failure and some exciting blamestorming meetings.

I think these models come about from those who think Agile and Scrum are just another process, a cog to switch out.  Agile isn't a process, it's a culture, a mindset, a belief system, a set of values, principles, and practices.  Treating it like just another process gives rise to tweaking and leads to hideous hybrid Frankenstein monsters, roaming the countryside and spreading failure.

Monday, January 7, 2008

SVN and proxy servers

So I wanted to check out Jeffrey's sample code he demonstrates in the latest dnrTV episode.  I get a fun message back from SVN, which is completely meaningless to me:

It turns out that although SVN works through port 80, the proxy server I'm behind filters HTTP headers, one of which is PROPFIND.  Google tells me that I can configure SVN to use a proxy server, which is what I need to do with several applications (including Live Writer).  Although I have to hard-code my password into the configuration file, it fixes the problem:

I have to change the configuration file every few months when my password expires, but otherwise I'm good.

NBehave source moved to Google Code

Well, we're fed up with it.  CodePlex is a great home for everything...except source control.  We've decided to keep all things project related (wiki, releases, discussions, etc.) on CodePlex, but move our source to Google Code.

We got the inspiration from the MvcContrib project, which is doing the same thing.  Too many people love their SVN, it turns out.  With Google Code, we can use SVN as our SCC provider instead of TFS.  Pulling down source, submitting patches, and other source-related tasks should get much easier.

Our Google Code project can be found here:

http://nbehave.googlecode.com

And the source can be browsed here:

http://nbehave.googlecode.com/svn/trunk/

Our public CCNET instance has been updated, which can be found here:

http://ccnet.nbehave.org/

It's been a bit of a journey integration NSpec and finding a new home for the source code, and moving to SVN should make all of our lives a little easier.