Tuesday, February 19, 2013

Developing Error Opportunities

I'm never able to catch myself making a coding mistake before it happens.  The funny part, for me anyway, is after the fact when I discover what the issue really was — it was a trivial error.  And the pattern I followed leading up to the error was avoidable.  How could I not have seen this coming, I sometimes question.  Is the answer that only in hindsight are these types of things obvious in an activity as complex as writing software?  That may be the answer.  But even still, I think it is both interesting and worthwhile to think about this type of software development pattern.  What makes us predictably and repeatedly successful, and what makes us unpredictably and repeatedly error-prone?

You might argue that this simply human nature, we have to fail before we succeed, we learn from our mistakes, and the same mistake is never repeated twice.  I would certainly agree that learning how to program well is no different, at the biological level, from learning anything else.  Conceptually, I think it's a little different because not only do we need to take incomplete problem descriptions and form our own abstractions in a language that the machine understands, we have a given set of tools already at our disposal. Generic tools somebody else has coded and made available for our use.  And since they're generic, they might apply to at least part of the specific problem we've set out to solve.  But this rarely goes smoothly.  We want to avoid reinventing the wheel, and yet, existing tools, that fit nicely with their designer's abstract mode of thought, may not match ours.

And this is no means the cause of the repeated anti-patterns — patterns that work against us instead of for us — we just tend to follow patterns too closely.  Consider using someone else's component versus writing our own.  We're smart, we don't want to create more work for ourselves.  Reusing an existing component is advantageous.  And since we already know how the component works, because we've seen it in action elsewhere, it's reliable.  And predictable.  But not necessarily in this new context in which we're using it.  This is where our productive pattern breaks down — simply due to the fact that we're over-utilizing our pattern strength.  Relying on patterns that have worked in the past isn't a bad thing, but we tend to overlook some nuances when everything comes pre-assembled.

Its tough to think about an approach to reduce the opportunity for error during the software development life cycle without introducing too much big-upfront-design.  Trying to close every single gap by planning out every single contingency for a relatively small piece of code is not very efficient, and not very agile.  I think the best we can do is try to acknowledge our human fallibility and document the interesting ways it impedes our code-writing velocity.