Sunday, December 06, 2009

A Year Of London Developer Events

Today marks a year since I moved to London from Chicago. So far, my favourite thing about being here is the trains run like clockwork the vibrant software developer community.

Here is a list of events I've attended, all of which I highly recommend:

Tuesday, October 27, 2009

Misadventures in DDD With Not-So-Ubiquitous Language

Lots of people have been talking about DDD (Domain-Driven Design) lately, and my friend Tom just discussed it over on his blog in the article Refactoring Toward Deeper Insight. So, I thought I'd share one way not to do DDD.

Once upon a time, shortly after the big blue book was published, I saw it in the store and thought it looked interesting. I bought it and read through the first section about knowledge crunching and ubiquitous language. And it all made so much sense—where I worked, the business analysts and software developers already worked together to crunch knowledge into a domain model they both understood (or so I thought). The trouble was, even though when they talked together, they used that language, when the developers actually wrote the code, they used their own. Why? Well, I didn't know—mostly just because we usually thought our names for things were better, I supposed. Trying to keep the language the same just wasn't something we'd thought about much.

So, I decided that on the project I was working on, we'd start doing DDD by using the names from the business language for the classes in our code. I didn't discuss it with the business people, since I didn't think it involved them much—they didn't need to change their language, we developers just needed to use it.

Everything went fine for most of the project. Then, a couple days before release, the business decided that they wanted to rename one of our core domain concepts—and that was okay, right, because it was just changing a few labels on a few screens?

And that's when I learned that if you want to do DDD, it helps to get buy-in from the business.

So, happy DDD-ing everybody—because I do think lots of the ideas are great and worth exploring—just make sure you let the business know what you're up to and you'll avoid my rookie mistake.

Monday, October 26, 2009

Estimating is Like Measuring the Coast of Great Britain

Earlier today, Liz Keogh tweeted this, which I couldn't agree with more, as long as she's saying what I think she's saying:

Thinking about fractal estimation—estimates grow as scale shrinks—and wondering what dimension current projects have.
A while back, every time I started doing technical estimates for a release, I began to think more and more of the illustrations along the side of this Wikipedia article: How Long Is the Coast of Britain? Statistical Self-Similarity and Fractional Dimension.

The situation was, that as a developer in a waterfall process, when I was trying to estimate how long it would take to code something, even with the requirements supposedly "fixed," unless I examined the code I was proposing to change in so much detail that I was basically writing it—and that's not estimating anymore—I'd always miss things that would make coding take longer than I'd estimated. In essence, there were always craggy little details that upon actually writing the code, became significant or added up with others to become significant.

Now, I know that if your architecture and code are clean, this should happen less. But I still think it's generally true that until you actually write the code, you really don't know how long it will take, and the amount of time will usually be longer than you think when analyzing it at higher levels.

Then, I thought of this problem again when I attended a talk on Scope Budgeting. There, the general issue is that in Agile, if you write a user story, estimate it, put it in your backlog, and only elaborate it when you pull it back out to implement it, you may find that the size of the story grows at elaboration-time.

According to Liz's fractal estimation rule, that makes complete sense and should be expected. I agree. Whenever I have worked with user proxies to move from general functional requirements to specifics, the estimate has always increased. The amount of work needed to address all the details we discover always grows beyond the original estimate. If we made commitments based on that estimate, the only way to keep them is to prioritize and remove some of the details.

I can think of a few ways to address this problem, if we want to consider it to be a problem:

  1. Just be aware of it and deal with it as needed, which is a lot better than not being aware of it at all.
  2. Start measuring it, so you can factor it into your future estimates. This might be taken care of by comparing estimates to actuals and factoring that into future estimates. You'll need to decide whether the time it takes to do this is worth the return, though.
  3. Move toward techniques like Kanban that de-emphasize estimation. Whether or not this works for you will depend on your current situation, but it's always worth questioning whether you're estimating because you truly need to or just because that's what you're used to.

Sunday, September 06, 2009

Pair Programming for Flow

A while ago, I attended the workshop Debugging Pair Programming by Matt Wynne .

Matt gave the same workshop at Agile 2009. That website has a good write-up of how it worked.

After the first part, where we discussed how to convince different developer personas why they should cooperate with pair programming, we moved on to the second part, where we paired up and interviewed each other about good experiences pair programming or collaborating in other ways.

I was paired with Tom ten Thij , who said something really interesting about pair programming.

He said that pairing can make it easier to get into flow.

This was completely the opposite of what I'd heard before about pair programming. Before, I'd heard it can be difficult to achieve flow while pairing—that you might even have to give up on flow, but that the increased code quality is probably worth the trade-off.

But Tom's point was that while pairing, you're less likely to procrastinate getting into your coding task. In other words, having a partner helps force the "activation energy" that flow activities can require.

So, as long as your pair works well together, and you keep everyone engaged by doing something like ping-pong programming, you might be able to achieve flow after all.

Saturday, August 08, 2009

Misadventures In BDD With NBehave

From my previous post, you might have picked up that I like the idea of BDD's given-when-then construct for describing scenarios.

For a while, I've been wanting to use this syntax in unit/integration tests to make them clearer. But I've been hoping to do that without switching languages or unit-testing frameworks. Toward that end, I tried out NBehave.

Here's some test code that demonstrates my worst fears about why NBehave might not be right for me:

public void Execute()
{
    var story = new Story("Search Contacts by Relationship Strength")
        .AsA("User")
        .IWant("To search on the Strength field")
        .SoThat("I can find Contacts who have a given Strength");

    Scenario scenario = story
        .WithScenario("Find Contacts with Strength of 50");

    scenario.Given("The database contains a Contact with a Strength of 50")
        .And("a search results view", GivenResultsInfo)
        .And("a query for Contacts with Strength of 50",
            GivenQueryForContactsWithStrengthOf50)
        .When("The search is run", WhenRunSearch)
        .Then("The results contain Contacts with Strength of 50",
            ThenShouldContainResultsWithStrengthOf50);
}

private void GivenResultsInfo()
{
    var resultsView = new ReadOnlyResultsView(
        ExtendableEntity.Person, SortType.Ascending, 
        new[] { Column }, Column);
    ResultsInfo = new ResultsInfo(resultsView);
}
private void GivenQueryForContactsWithStrengthOf50()
{
    var condition = 
        new DecimalCondition(Column, ComparisonOperation.EqualTo);
    condition.DataField.Value = 5;

    _query = TypeHelper.GetAdvancedQuery(_entityType);
    _listManager.AddListToAdvancedQuery(_query);
    _query.MainConditionGroup.AddCondition(condition);
}
private void WhenRunSearch()
{
    ISearchService service = TypeHelper.GetSearchService(_entityType);
    ISearchResults results = service.GetResults(_query, ResultsInfo);
    _resultsData = results.Results;
}
private void ThenShouldContainResultsWithStrengthOf50()
{
    Assert.Greater(_resultsData.Rows.Count, 0);

    foreach (DataRow row in _resultsData.Rows)
        Assert.AreEqual(5, (decimal)row[Column.Name]);
}

But for me, creating reports of the text descriptions wasn't the main point. The main point was just to better organize the test. When I started writing the code, I thought maybe I'd just skip the text, but then I thought, "Oh well, I might as well do it."

And that was fine, but when the requirements changed, I had trouble keeping the text synchronized with the code.

After I wrote the initial code, the team decided that instead of having strength on a scale from 0-60, we'd have it on a scale from 0.0-6.0. And when I changed the code, I was in a hurry, since that change hadn't been part of the original estimate, and consequently threatened our timeline.

So I ended up with text that said 50 and code that said 5.

Monday, August 03, 2009

Open Space Coding Day: TDD As If You Meant It and Cucumber With IronRuby

Saturday I was at the Open Space Coding Day that was part of the Alt.Net UK Conference 2009.

In the morning, I was in the session on TDD As If You Meant It. Gojko Adzic already did a pretty good write up, so I'll point you there to learn more about it: TDD as if you meant it – revisited.

In the afternoon, I was in the session about using Cucumber and RSpec with IronRuby. Mostly, I was interested in this because I keep hearing really good things about Cucumber, but as a non-ruby person, I have never quite discovered what those good things actually look like.

I was also a bit psyched, because I was pretty sure I'd heard that IronRuby was going 1.0 on my birthday. But alas, it seems that article subtly changed since I last looked at it, from saying "IronRuby is 1.0!" to now saying "IronRuby is almost at 1.0!" A slight let-down, but that's okay. We still had a good session, and I'm the first person to understand that software doesn't always magically appear on a certain date just because we want it to.

To install IronRuby, Cucumber, and RSpec, I mostly used these instructions:

The process for me went something like this:
  1. Install Ruby.

  2. Install IronRuby. (The day I was doing this, 0.6 was being billed as the current release. It looks like things have moved on.)

  3. From IronRuby and .NET, do:
    1. Installing required gems
    2. Creating a Cucumber wrapper script for IronRuby
    3. Running the examples

  4. Now the examples ran, but there was some weird escape-character output. I didn't find the answer to how to fix this, but another person in the session, Lorenzo Stoakes , did. Here's how that looked on Twitter.

    For convenience, though, I guess I'll compile that into the single sentence: In your file that corresponds to C:/Ruby/lib/ruby/gems/1.8/gems/cucumber-0.3.92/lib/cucumber/formatter/ansicolor.rb, replace Term::AnsiColor.coloring = false if... with Term::AnsiColor.coloring = false.

At that point, the examples seemed to sort-of run okay for me. I think Lorenzo and Garry Shutler got past some warnings that were getting output, but I didn't. I'm also pretty sure Garry also got RSpec to work.

What was the whole point? Well, since I didn't get past the examples, I'll sum it up with one of them.

Say you're developing a calculator. Your business person can specify the addition behaviour in text, like this:

Feature: Addition
  In order to avoid silly mistakes
  As a math idiot 
  I want to be told the sum of two numbers

  Scenario Outline: Add two numbers
    Given I have entered  into the calculator
    And I have entered  into the calculator
    When I press add
    Then the result should be  on the screen

  Examples:
    | input_1 | input_2 | output |
    | 20      | 30      | 50     |
    | 2       | 5       | 7      |
    | 0       | 40      | 40     |

And you can make that executable by adding some code in a related code file like this, where you're testing a .NET assembly Calculator.dll that contains a Calculator class in the namespace Demo, and the Calculator class has push and Add methods:

require 'spec/expectations'
$:.unshift(File.dirname(__FILE__) + '/../../lib') # This line is not needed in your own project
require 'Calculator' # Calculator.dll

Before do
  @calc = Demo::Calculator.new # A .NET class in Calculator.dll
end

Given "I have entered $n into the calculator" do |n|
  @calc.push n.to_i
end

When /I press add/ do
  @result = @calc.Add
end

Then /the result should be (.*) on the screen/ do |result|
  @result.should == result.to_i
end

That does look pretty sweet.

Tuesday, July 28, 2009

Scope Budgeting

A while back, I attended the talk Scope Is Not A Dirty Word given by business analyst Angela Ashworth and delivery manager Mark Coster from ThoughtWorks.

The centre of the discussion was "scope budgeting," which basically boils down to having the developer work with the user to manage scope within an iteration.

In many flavours of agile, the user writes a story, the developer estimates it, and then it goes into the backlog. It's only when the story gets pulled from the backlog and put into an iteration that the user and developer fully flesh out the implementation details. But at that point, they may find they have scope creep—that the implementation will take longer than the original estimate.

At this point, the developer has two options:

  1. Implement the story, even though it will take longer than originally estimated, pushing out the other stories, potentially dropping some off the end of the release.
  2. Talk to the user more. Let him know that the estimate has changed and why. See if together they can come up with a way to reduce the scope of the story to get it back down to the estimate.

Option 2 is scope budgeting.

I have to admit that I was actually very disappointed to hear this from ThoughtWorks.

I have never been part of an agile project, I've only read about it. My agile daydreams included how nice it would be to have the user prioritise stories from the beginning, understanding that not everything would necessarily make it into a release, thus avoiding one of the activities I've come to think of as churn—the developer and user constantly having to re-prioritise and re-think functionality as scope creep happens in order to try to fit everything in or to figure out what is best to leave out.

I suppose I can understand why scope budgeting is a good idea. And I can understand that having all the stories in an unchanging ordered list from the beginning of the project isn't really very agile at all.

But it's still tough to see my daydreams shattered.

The up side is that it highlights that both the developer and the user are in the same boat, working together toward the same goal. In waterfall, each is under pressure to "be perfect." The user should write down every single implementation detail at the beginning of the project and the developer should estimate every one of them down to the minute. Later, when they discover that a requirement was missed, the developer blames the user for blowing the project. When they discover that an estimate wasn't quite right, the user blames the developer for blowing the project.

At least with agile and scope budgeting, the focus changes from blaming to recognising that neither the user nor the developer can make a perfect plan at the beginning of the project—that they need to work together throughout to figure out how to create the most value.

Monday, July 27, 2009

My Favorite Technical Books

It's been half a year since I moved from Chicago to London, and there is still an awful lot of stuff that isn't unpacked and is sitting in boxes, including many, many books.

But last weekend, the DH and I added yet another bookcase to the flat, and it's time to take care of the box sitting at my feet, labeled "Amy's favorite computer books."

But wait, I hear you say, if those are your favorite computer books, how can they possibly still be packed away in a box? Don't you need them at your desk every day?

Not so much anymore. A few years ago, I bought a subscription to Safari Books Online, which I can't say enough good things about. Yes, it can be expensive, but if you can scrape together the cash and you love technical books, it's great. Almost all of the books in my box are on there, so I don't need them at my desk.

The other aspect of having these books at my desk was that they were available for my teammates to easily grab and use. But now that I'm in London and those teammates are in Chicago, that doesn't happen anymore.

So, my favorite books have been sitting in their box until now. Now, I have a bookcase with glass doors available, so they won't get dusty. Here they come out of the box:

Head First Design Patterns by Freeman & Freeman I can't say enough good things about this book. It was the book that made the light go on for me for understanding what design patterns are and why they are useful. I own two copies—one was for work and one for home—plus the poster.

Working Effectively with Legacy Code by Michael Feathers For when you have to deal with ugly code, old code, code written by someone else long gone from your company, scary code, code without unit tests, or code you wrote last year and now hate.

Refactoring to Patterns by Joshua Kerievsky A bridge between patterns and refactoring.

Software Estimation: Demystifying the Black Art by Steve McConnell Sometimes I curse that I read this, because it made my BDUF estimates more accurate. Don't worry, there's lots of other good stuff in there, though.

Patterns of Enterprise Application Architecture by Martin Fowler This was the most-borrowed book in my library before I moved.

Pro C# 2008 and the .NET 3.5 Platform by Andrew Troelsen When I can't remember how something .NET 3.5 works, and I have trouble finding it online, this is where I end up.

VB & VBA In a Nutshell by Paul Lomax Because unfortunately, sometimes VBA still happens.

There are two more that I need to mention, even though they aren't in the box. The first, I have on CD, and the second I used to borrow from a work-mate until I got Safari books:

Design Patterns: Elements of Reusable Object-Oriented Software by Gamma, Helm, Johnson and Vlissides

Refactoring: Improving the Design of Existing Code by Martin Fowler

But wait? Where is The Mythical Man-Month by Fred Brooks? Good question. Darn thing is too skinny. It's always getting itself lost.

Sunday, July 26, 2009

Programmer.Grrl: The Prequel

As I mentioned before, back in high school, I was pre-med. The interesting thing is, when I was about 15, I actually did take a programming class and really enjoyed it. It was BASIC on Apple IIe computers. I remember one of the projects being to code a dice game. What could be more fun that that? Not just playing a computer game—but creating one?

It didn't feel like school, it felt like play. And because it felt like play, and because I didn't know that programming was a real profession, when it came time to sign up for the next semester of classes, I decided I didn't have space in my schedule for Programming II. I needed to take more biology or chemistry or some such thing.

The problem was, where and when I grew up, in a small town out in the country and before the Internet, I didn't have any concept that what I'd done in the programming class was at all useful. I didn't make any connection between it and the software my family bought for our own PC clone—things like WordPerfect and Lotus 1-2-3.

I don't know that it's true, but I hope so, that the Internet has opened childrens' horizons, so that when they think about what they want to be when they grow up, they understand there is more available than the professions they see in their everyday lives. Because when I think about that programming class I took when I was 15, I always wonder what a better programmer I might be if I'd kept with it from way back then.

It also makes me think more about how people end up as programmers in general. One of the original joys of programming when I was 15 was that I was making something. Most of my life, especially my school life, didn't produce anything remotely tangible or useful. It was about completing assignments or studying for tests, where once the assignment was done or the test taken, it was over, and the graded paper or test wasn't useful in any way.

But programming was different. You could tinker around and write some code and have something useful when you were done. Making something—something that other people might even really like—it's a rush. I'm sure there are other programmers out there who got interested in programming because of that. And for us, that's one of the frustrations with Big Design Up Front or with other processes where it's difficult to link end-user value back to our own work. Even if the process works for the organization, it can be tough for the individual.

Monday, July 20, 2009

Companies are Addicted to Profit Like Smokers are Addicted to Nicotine?

What I believe and what I'm discussing are two very different things. I absolutely can't agree more with pretty much everything Jim says in Define success....

My worry is that if an organization views its projects as successful, the argument that the success isn't sustainable may not be compelling. If so far, using its current methods, the organization has been making money, and as far as its managers can see, will continue to do so in the near future, how do you convince those managers that it needs to change?

It's even more difficult than convincing a smoker that smoking will kill him eventually, and that he should stop—at least in a logical sense. An organization isn't an individual, whose best interests are intrinsically aligned with the longevity of his body. An organization is a collection of individuals, who can leave at nearly any time. If the organization's methods aren't sustainable—if it won't make it through the next 50 years—how many employees really care, as long as they are currently able to cash their paychecks?

It reminds me of Alan Greenspan's testimony about the economic meltdown: "Those of us who have looked to the self-interest of lending institutions to protect shareholder's equity—myself especially—are in a state of shocked disbelief."

Yes, it's a shocker. It turns out that not everyone in an organization cares about its longevity, as long as they get their cash and escape before it implodes.

But let's assume better of employees of software companies, especially since most I've encountered really do seem to care a lot more than that.

It's still hard to convince people to change when the current model is "succeeding."

In organizations where meeting yearly financial targets takes higher priority than continuous improvement, the continuous-improvement conversation can end up working like this variation of being too busy sawing to sharpen the blade:

Lumberjack: Say boss, this blade is getting dull. It's getting slower for me to cut down the trees. I don't think we're going to make our quota.

Supervisor: You have a point. How long do you think it will take for you to sharpen the blade?

Lumberjack: I'm not sure. Since I've been working here, we've never sharpened the blades, so it's difficult to estimate how long it would take, because I'm out of practice. Plus, the blades are pretty dull, so it probably would take longer than usual anyway.

Supervisor: Hmmm. I'm not sure we'll be able to make our quota if we don't know how long it will take. We can't risk that. At our current rate of cutting, we can still make the quota if we hire in a few contractor lumberjacks. We'll do that.

It's not necessarily that the members of the organization don't want to improve—they may just think they don't have time given their current constraints.

And as far as the greater organization is concerned, they still made their quota. As far as it's concerned, everything is hunky-dory.

So, I'm back to the question. If the organization thinks the project was a success, but some people do not—some people think that success will be unsustainable in the long run—how do those people convince the rest of the organization that change is needed now?