Engineering organizations are too focused on efficiency. Not software efficiency, but work-effort efficiency. We need to drop efficiency as a goal of its own and realize that it is only one factor of many in delivering what actually matters: total organizational throughput.
Efficiency can be defined as a measure of the work cycles we spend that are necessary to produce a result. Throughput, on the other hand, can be thought of as the total results produced in a fixed period of time. Far too much time is spent optimizing efficiency at the expense of throughput.
This scenario plays itself out variously throughout the software world:
Laura and Steve, two complete strangers working for different companies, are both working on web applications that need to implement a feed of notifications. This happens every day across the engineering world, but if Laura and Steve were coworkers, they and their manager would start having a conversation around efficiency: It’s inefficient for them to each independently implement notification feeds for their apps — since we could make and abstract a single notifications feature they could share — so obviously they should coordinate and avoid duplicating effort, right?
Laura and Steve have a series of meetings to discuss their applications and figure out the common functionality they’re implementing, and to spec out the common notifications system that will serve both of their products. Midway through the week, they’ve got agreement on what they’re building, and on Thursday and Friday, they’ve knocked out the initial version of the notifications system they’ll both use.
Two weeks later, Laura is far enough along in her feature that she’s ready to plug in the notifications system and realizes her requirements are a little more complicated than she initially expected and the data model for a notification will need to include another concept. She schedules a meeting to make sure that her change doesn’t affect Steve’s product. They work together for another day to add the new concept and Steve spends an hour reworking his integration to deal with the data model change.
Six months later, Steve is shocked to learn that Tom’s team — on an unrelated project — has implemented their own notifications system. Steve goes to his and Tom’s manager to try to figure out how they can prevent such inefficiency in the future and they agree that the engineering teams will write up implementation specs and get them reviewed by each of the teams to prevent this duplication of effort in the future.
You can see how this continues to progress down this path until nothing can get done without a gauntlet of approvals and meetings. We’ve all worked in jobs where entire weeks go by with nothing productive being accomplished as we talk, review and debate changes we want to make. We’ve all hated those jobs.
You can also blow this up to the size of a multinational software giant and imagine just how much coordination and agreement cost must be spent preventing inefficiency. Yes, Laura, Steve and Tom work in an inefficiency-free workplace where nobody is “wasting cycles” building something that someone else has already or will soon build, but in an alternative universe where the three of them never realized they were all independently planning to spend a day or so implementing a notifications system, they probably could have shipped three more features in the time they spent blocked waiting on agreement.
In the hypothetical scenario above, the approximate effort of each notifications system is about a day’s work. Three teams each spend a day, for a total of three, and it would be easy to make the argument that two of those three were wasted. However, the meetings and controls put in place to defend against the specter of inefficiency reduce the total throughput of the three teams: they’re not wasting effort, but they’re spending time coordinating — time in which no productive cycles are happening.
There are certain problems so common that you’d be mistaken to solve independently without there being very specific extenuating circumstances, like JSON parsing, making HTTP requests, generating PNGs, etc. Using a standard library for any of these things requires virtually no coordination cost, so the efficiency gain has a negligible cost. And there are other problems which aren’t common, but are so expensive to solve independently from scratch that two teams should spend the time coordinating on a common solution. The coordination cost is dwarfed by the implementation cost. But the argument in each case shouldn’t be efficiency. The argument to be made is that throughput is increased.
A good engineering department optimizes for total throughput. There are times when throughput is reduced by inefficiencies. There are other times when throughput is damaged in pursuit of efficiency.
The low-hanging fruit of productivity is often found by unblocking people from expensive agreement and coordination. The right balance of autonomy and coordination is impossible to find if you’re fixated on efficiency.