Say you need money. Lots and lots of money.
You could rob a bank. Assuming you were skilled/lucky enough, you could have the money in hand right away, and for a minimal investment of time and effort. This is efficient.
On the other hand, you could study, practice, work, and connect for years to build a career, and a reputation. You would accrue the money more slowly, and with a great deal more upfront muscle and patience. But the likelihood of you being hunted like an animal, your bounty being reclaimed by lawmen, and your life being ruined is orders of magnitude lower. This is effective.
The choice between efficiency and effectiveness in our day to day work rarely presents itself with this level of clarity. Pressure to deliver more, faster, and cheaper blurs the line even further.
But delivering something today that crumbles tomorrow has no value. It is unprofessional, and it erases the trust you may have heretofore built with your audience.
So, what does this have to do with software?
Signing off on an exhaustive, up-front specification document is efficient.
Adding the next most important feature, one at a time, is effective.
Writing legacy code is efficient.
Writing test-driven code is effective.
One big go-live at the end of the project is efficient.
Shipping working software early and often is effective.
Each of the bold choices above is sure to trigger resistance in traditional management. These options sound like extra time and money, like unnecessary detours from the straight line between points A and B that they may have imagined the work of software to be. And that is understandable, if all that has ever been emphasized in their work is a lock-step bottom line that would make Fredrick Taylor blush.
It’s not about right or wrong, smart or stupid, good or bad. It’s about balancing short term and long term. It’s about whether we care about delivering value, responding to change, and building trust, or if we’re just here to punch the clock today, make the sale today, and not ruffle any feathers today.