Software Capex: The Cost of Flexibility

We tend to think of flexibility as a good thing.  When it comes to interpersonal relationships, the ability to compromise is considered a sign of maturity.  Shouldn't this be the case for software?  After all, software is just a human solution to a human problem.

Well, it turns out that it depends on what exactly we mean by "flexibility."
 
Flexibility as software extensibility is generally positive.  It's unlikely that we perfectly capture the problem space in an optimal fashion in the first go.  We should strive to make our future selves' lives easier.  Extensibility means, holding all else equal, building a version of the solution that is easier to expand upon in the future.  This kind of flexibility is good.  It means spending a little extra time now to save time in an ongoing fashion in the future.  We'll return to this idea later.
 
When by "flexibility" we mean producing a solution to an ambiguously defined problem, that's where we get into trouble.  While a compromise here may be born of good intentions, it can lead to unintended consequences.
 
We rarely, if ever have a perfect understanding of our problem domain.  However, to the degree we do understand it, we should strive to accurately model it.  If our business users have that knowledge but have not shared it clearly, we should challenge them to articulate it.  Some common examples of well intentioned compromises that may cause trouble include:
  • Including a feature that you don't need yet (but might need in the future)
    • maintaining the feature while changing the software adds incremental effort to each and every new feature or fix applied to the system
  • Given a list of options, including a catch-all option.
    • may allow the system to grow without specifically capturing known use cases
    • may tempt the user to override available cases with "other."
      • Imagine if you're in a hurry and can't find the "car" category so just dump your data in "other," overlooking the "automobile" category.
    • allows the system to continue to run with ambiguously defined categories or outright bugs.  Users can still get things done by dumping everything into "other."  To sort things out, we may need to establish human operations that manually mimic what the software was supposed to do (at a higher cost)
  • Tramp data (or Global Data)
    • you need something in particular but passing a superset object is more convenient...Careful now! You may be tempted to rationalize this as extensibility.
    • due to Hyrum's Law, once you've passed it you're going to struggle to un-pass it.  This leads to tight coupling, poorly structured code, and undue complexity.
    • it's a violation of the Law of Demeter

"When should we compromise?"
  1. If the flexibility justifies the cost, compromise.
  2. If the savings now is necessary to continue as a going concern, future be damned, compromise.  
Just bear in mind that savings is near term while maintenance cost is often in perpetuity.

PV of Compromise = Time Saved Now - [ Incremental Maintenance Cost / IRR ] 

We can produce the matching formula for our point on extensibility.

PV of Extensible Design = [ Future Time Saved / IRR ] - Incremental Time Invested Now

Let's go through a quick example to demonstrate.  We'll assume an Internal Rate of Return of 10%.  A given compromise saves us a month of time now (20 man-days).  It causes 5h/month of incremental manual support burden on engineering.  The value/cost would be (20d * 8h) - (5h * 12m) / 0.1 = 160 - 600 = -440 man-hours.  You can apply an appropriate burn rate/hour to transform this into dollars lost.
 
We can alleviate this somewhat by promising ourselves we'll return and fix the problem within 6 months.  This would change the value to 160 - (5h * 6m) = 130 man-hours saved (actually slightly more if we apply discounting each month, but I want to keep this simple).  The trick is living up to this promise as priorities change and new information comes available.

Claiming that the impact of design decisions lasts in perpetuity is perhaps an exaggeration.  However, it does provide us with a conservative estimate when we lack more detailed information about the future.  Moreover, it incentivizes longer term planning to improve the accuracy of the assessment.  This general approach gives us an objective framework for assessing alternative designs on a cost/benefit basis.
 
Software design decisions have a long lifetime in business.  When we consider how they impact maintenance cost, their importance to the bottom line becomes clear.  The engineer should take the herculean path, avoid rationalizing, and be courageous enough to challenge their business partners to articulate and share as much of the problem domain as they can.



 

Comments

Popular posts from this blog

Engineering Truisms

The Telescoping Constructor (Anti-Pattern)

A Strategic Approach to Precision Process Automation