OK here's the respones to my highly non-scientific survey 

Your project is "In Trouble."  The Big Boss has just walked into your office and told you that he needs you to save the day.  Which of the following is more likely the culprit of this crisis that has your boss in a panic:

1) A developer failed to code a good algorithm in some module and now a very smart person must come along and replace that module with something much better.

2) The project has far too many layers of abstraction and all that nice readable code turns out to be worthless crap that never had any hope of meeting the goals much less being worth maintaining over time.

And the results are:

Of 27 responses at this writing

  • 8 didn't specify #1 or #2 at all or were balanced
  • 4 went clearly for #1
  • 15 went clearly for #2

Which if you like that means only 4 of 19 votes (21%) were for #1 with 8 abstaining. 

I suppose I shouldn't be too surprised because of how I asked the question but let me say what point I was trying to make and that is this:

Number 1 isn't a crisis, it's normal.  It happens all the time and it isn't or shouldn't be especially a big deal.  In fact if you try to hard to prevent all your #1s you are probably going to waste a whole lot of effort on "Premature Optimization."   Number 2 on the other had is really a crisis, like some other quality factors over-abstracting can render the code fundamentally unsuitable for the job at hand.  No amount of clarify of intent or maintainability can save it.  These are true crises where significant effort is totally wasted and will have to be re-done.  Arguably preventing those kinds of crises is why I have a job at all.

Sometimes people say that "usability" is the key factor driving the long term cost of code development.  I think I would agree with that statement but I may have a different definition of usability than you expect.  I don't mean elegant, simple, easy-to-read, convient etc.  Those things certainly help, but they aren't sufficient.  The literal meaning of the word is closer to what I want -- I have to be able to use it.  Goodness knows Win32 isn't the most elegant thing on the planet but it has a high degree of "fitness for purpose."  Which is to say it's good at what it does.  It couldn't possibly succeed if it was not and its arguably the most successful API set ever created.

So, while a hard-to-understand API does lose some points of "usability," an easy-to-understand API that does its job very poorly isn't worth the magnetic particles it exists on.  Usable first then re-usable was something I quoted a while ago but really I could say usable first or else nothing matters at all.

A bad module can be fixed.  A bad design has to be tossed.  Localized problems aren't the real enemy, they're just the regular bumps along the way.