Skip to main content

Thousand Paper Cuts

This is the opposite of the 80/20 rule. There are no low hanging fruit that will make the problem go away. Instead, a multitude of small problems, spread widely through the system, add up to large problems. An app is slow and laggy. An organization just stumbles along, getting nowhere. Every QA cycle turns into whack-a-mole, every bug fix introducing more new bugs.

An important property of thousand paper cuts type problems is that the cost of fixing the problem once it manfiests dwarves the cost of preemptive avoidance.

A linear scan instead of an indexed search is fine with implementing a prototype. When the prototype gradually grows into the production version, and users accumulate far more data than you tend to have in your test environment, it starts mattering. Keep this “okay for the time being” attitude through all your work, and eventually you end up with a system that has rust in every joint, and is overall a sluggish mess.

The fix? Do things right the first time around, with respect to ROI, but also with lookahead. I am not trying to advocate for premature optimization. That would imply significant design and implementation effort being spent up front, without knowing whether it will ever pay off. What I’m talking about takes little more additional effort. Just be diligent. If you’re planning to look up items by key, don’t use an array and a find on it to search — use a map instead. For all code you write, think about what the essential complexity of the operation is, and write your code to match that. You’ll be able to get 90% with minimal effort, by just exercising some discipline.

It gets worse with systems. Every non-trivial piece of data flow, every hack, every order-of-execution-matters scenario adds up, and effects are multiplicative. The system becomes cumbersome to reason about, team members’ understanding of it weakens, which generates yet more bugs, hacks, and incorrect, fragile uses. This brings the system to its knees.

The fix? Design your systems to be stupidly simple. Build with uni-directional data flow, immutability, and clear layering from the start if you can, or start to gradually inject them into the system if you have legacy code. Any time the simple system is too restrictive when implementing a new feature, try to reframe the feature in the context of the system. Most of the time, just changing perspective is enough to see the better implementation. If this doesn’t work, there may be something essential in the new feature that will require you to reorganize your code. Strip the noise, and find that essential nugget of systemic mismatch. Really convince yourself that it’s orthogonal to the current design, and then find a way to modify the system layout in a way that accommodates the new use case while preserving the “stupidly simple” property.

At the level of organizations, death by a thousand paper cuts is all too common. You talk, but what you’re trying to communicate isn’t getting across. An agreement is seemingly reached, yet the implementation is going in a direction that nobody agreed on. It’s like the organization has a mind of its own.

The main problem is likely communication. As mentioned in the communication section, words have different meanings to different people. Sharing context successfully is a hard problem. If people in the organization are not aware of these problems, they may fall into the pattern of thinking that obvious things don’t need to be mentioned, without realizing that these things are obvious only to them. They may try to communicate by implication instead of directly. They may keep concerns to themselves instead of voicing them. The result — a familiar rust-at-every-joint, communications and management overhead between every pair of team members. Cumulatively, the effects can bring an organization to its knees.

The fix? Declare clear, simple, straight-forward communication as a priority. Explain to your team members what the price is otherwise. Establish a fixed nomenclature — make sure the same words are used to describe product parts, process parts, etc. Is it a “screen” or a “page”? A “nav bar” or a “toolbar” or a “top nav”? An “issue” or a “ticket”? Pick one and stick to it. Ruthlessly reduce ambiguity and proactively lower cognitive overhead of communication. And after you are done talking about stuff, don’t be afraid to move the conversation to the meta level, do some analysis and talk about how you could have communicated more clearly. Slow down a bit, and grow together, it’ll make you faster.

Next: Fear ⇒

Comments