Monday, December 5, 2011

Mind The Aperture

Picture each software system as a gigantic puzzle — an admittedly over-simplified analogy.  Each piece, so the visualization goes, is an encapsulated component with boundaries and responsibilities.  Only when each puzzle piece is connected do we have a complete software system — the big picture coalesces on the landscape.

A problem with this analogy though — one that might reflect some of the challenges we face in grasping the true depth of problems our code aims to solve. You see, the big picture — the one resulting from an assembly of puzzle pieces — isn't a fundamental given.  We haven't anything concrete to serve as a reference picture.  How do we know when the system is ready?

Gaps In Foresight
The waterfall approach to software development doesn't work because of a fundamental misstep in presumed knowledge.  Knowledge before the construction phase starts.  Apertures inevitably rear their heads only after development has started.  If we are to assume that we won't hit these gaps in knowledge during the development of our product, we're ill-prepared to deal with them right from the get-go.

So what do these gaps represent?  Do they mean that there are serious problems with our understanding in what we've set out to build?  Do they mean that we've simply miscalculated the complexity involved?  Was our team naive in choosing the required technology platform on which our software runs?  Any one of these could be true, and the only way you'll find out is to try building it.  The trick is, if you can eliminate the painfully obvious gaps in knowledge before you start your endeavor, you can be sure that you're on the right path.

Wide gaps in foresight are preventable.  Perhaps even mid-size gaps can be identified and evaluated with no more than a little research.  It's the smaller ones to look out for.  These gaps in our assumed know-how will come back to bite us once we've put in any real development effort.  The trouble with small gaps in understanding what the software project is all about is that they tend to progress along side the project.  As the project grows in size, the components that we've designed — the interfaces that serve as the basis of our architecture — are lodged throughout the code.  And in the same way the newly-fashioned design parades through the system, establishing it's roots as the basis of which the rest of the code uses, the small gaps in our understanding take hold and forever change the future of the project.  That is, unless we can learn to differentiate between good gaps and bad gaps.

Leaving Gaps Alone
Who says all missing pieces are necessary, that all potential gaps of any software system must be filled?  I think this is another misconception that we all experience at one point or another during our lives of building software.  We have to somehow understand and implement all potential use cases of the system, including those that stakeholders have yet to consider.  These aren't exactly easy to come up with either.  We have to put ourselves in the shoes of users.  Of administrators.  Of support staff.  Anyone.

The trouble is, once we start thinking about where the requirements fall short, we start playing a guessing game.  We generally ask the whoever the gap concerns about what they want done about it — how should we implement this scenario? Chances are, they don't know.  If they'd thought about it, it'd be in the requirements now wouldn't it?  But at this point in the game, it's difficult to think responsibly about these gaps in our understanding of what the software does.  There is no system in production yet. So how does one quantify changes that should be introduced without any knowledge in how the system works in reality?

Asking a stakeholder about a missing gap in the system during development won't necessarily help you much because they need to think about it.  Or worse, no thought goes into how to fill holes in the system and it's just a workaround that plugs the gap.  In the best case, we will sit down with the stakeholder and actually think about what the gap represents, how it should be dealt with, and what are the significant architectural changes.

Keep in mind — this is still development.  We've now got a road block in place, slowing the continuous development effort.  While the issue details are being ironed out, there really isn't much that can be accomplished in terms of writing code. Pushing forward without a full understanding of what the system goals are, we could be writing the wrong thing.

Having said all that, I think it's better to leave gaps alone during the development phase.  Just as long as they're understood.  The implications of missing requirements from all perspectives of the project will enable use to move forward in pounding out lines of code.  Nothing makes stakeholders happier than a system delivered sooner rather than later — regardless of gaps in what the system does. The key is, as I mentioned, how the system deals with gaps in understanding.  If you allow for stakeholders to view a functional system, and can point out the gaps in a meaningful way, they're more apt to make the right decision and fill it with something useful.  Just be sure to produce a working system, one that knows about the gaps but will still work.  Point out the what the gap means for every aspect of the software.  It's much easier to make these arguments when you've got a running software system to back up your claims.