You’re probably quite familiar with the hi-larious tire swing cartoon that made the rounds some years back which satirically suggested “how software projects really work”. You haven’t? Ok: Click here and then come back.
To borrow from an old Simpsons episode, “it’s funny ‘cause it is true”. It speaks to all the follies that beset traditional software projects and how traditional practices spectacularly fail to generate real value for customers. It’s funny, but as I’ve written here in the past, the joke is really on all of us because the failures these practices engender costs billions.
The Code/Fix Software Anti-Pattern
This brought to mind a real-world example of what happens when we engage in code/fix software development. In this anti-pattern, design activities aren’t structured or governed – they just happen. New features are added to an existing code base that doesn’t have automated tests to reveal when things break as a result of the imposed changes. It seems easy to do at first: Just get into the code and fix it, dammit!
This creates bugs – sometimes serious bugs – that don’t appear until we’re well down the road. To use the cartoon above by example, we have the tire swing in our head, but the reality is something like this:

Here in Ontario, we’ll be hosting the G20 and G8 summits – which means that a lot of ad-hoc “beautification” projects are being hastily assembled at taxpayers’ expense ($1B and counting). Behold what has happened in the cottage country city of Parry Sound – I believe this to be the perfect illustration of the Code/Fix anti-pattern metaphor:

This is the result of adding features without a usability plan for the product – it seemed like a good idea at the time… And more to the point, some “developers” and their “project manager” actually thought this was a reasonable solution, despite the primary purpose and function the hydrant serves (ie. provide water to a fire engine to help firemen put out fires).
While software doesn’t have to respect the laws of physics that will make fixing this a chore in the real world, we get the same inertia as a result of code/fix software development. This occurs when we eschew reviewing our design through refactoring, which necessitates having a suite of unit tests and a continuous integration server. It’s painful to fix because we have no idea how long it will take because we don’t know what’s going to break as a result.
In the real world example, it’s painful enough: The hydrant is barely useable now, and will be useless after the first snowfall. But you know what will happen: They’ll put a flag on a stick next to it and it’ll be someone’s job to dig it out. And it will be so until there’s money in some budget to fix it – as it gets deferred, technical debt will be incurred. Heaven forbid if it ever needs to be used, as it will likely lead to property damage. But not to worry, another quick fix like adding a welded on elbow joint should do the trick for now! A rather perfect metaphor for the code/fix cycle.
Fixing the Problems Before They Begin: Hard Work
The solution to this dilemma is simple: Don’t let it happen. The execution is the hard part because it involves learning a new skillset and setting up what we think will be a Rube-Goldberg for building software. Not true: Start small and work outward.
Read up on unit testing – write a few. Get books to guide you like Pragmatic Unit Testing in C# with NUnit, xUnit Test Patterns:Refactoring Test Code and Test Driven Development by Example. Learn about continuous integration using your favourite version control system with Continuous Integration: Improving Software Quality and Reducing Risk.
If something seems like its an impediment to adopting the practices, figure it out: If you can stand up a CI server with tests faster and more reliably with Subversion – use it. The objective is to have the machines do the tedium to keep your designs solid and testable.
Ultimately, it’s an investment that pays bigger dividends than you might think.