Over a lifetime of wrangling projects and relationships one repeatedly encounters a decision point with three options around managing sub-optimal outcomes. These options exist in all contexts and carry similar costs, benefits, and risks. Maintaining awareness of them and choosing deliberately between them makes all the difference. These options are:
I imagine that many of my most expensive mistakes in life stem from losing sight of this or failing to prioritize making such a hard decision.
In my time at Bridgewater Associates I had many opportunities to reflect on this meta-challenge, perhaps provoked in substantial measure by staring at the Dot Collector (jump to 9:00) and thinking on the oft thin line between “Problems – Not Tolerating Them”, “Determination”, and “Practical Thinking” in many contexts, a realm where “Seeing Multiple Possibilities” and “Dealing With Ambiguity” hold central importance. A high tolerance for pain is a powerful but dangerous personality trait. One must take great care to separate “can” from “should” here.
For the sake of brevity I will focus on the application of this thinking to Software Engineering in a highly entrepreneurial context, a domain with which I have wrestled for most of my career at many different kinds of employers.
The key elements where one will have investments and opportunities include:
Wisdom involves constantly making an explicit decision between renovation, toleration, or separation for matters in each of these realms. Meanwhile the criteria by which one ought reason about ongoing approaches include:
- Present Value
- Future Value
- Support Cost
- Opportunity Cost
- Risk Profile
As a Maker who takes pride in one’s work, therein resides a strong desire for continual and unending improvement, but the optimal capture of value generally comes from an implementation that falls far short of perfection. As a Dreamer who can imagine the applicability of one’s work to many problems, therein resides a tendency to keep fighting for one’s envisioned utopia, but there is no validation of your ideas quite like users, funding, and revenue. As an Entrepreneur one needs to be both of these things, but within reason, tempered by humility, practicality, and data-driven analysis that underpin ruthless prioritization, fanatical focus, and judicious risk management.
Dijkstra perhaps nails a central problem in insisting that ‘we should not regard [lines of code] as “lines produced” but as “lines spent”‘. With every line of code we produce we create a maintenance burden, increase the cognitive load to add other new features, forgo countless other opportunities, decrease the system’s reliability, and add complexities and risk around security. Sometimes Good Enough is truly Good Enough. Use that third-party tool that gives you 90% of what you need and move on. Maybe tolerate that annoying but rare bug with a frustrating but bearable manual remediation approach. Or, which is a much harder pill to swallow, but sometimes the right choice: Burn it down.
Letting go of things is hard. Firing people, abandoning products, scrapping processes, ditching technologies, and leaving markets HURTS. But being willing to do so is key in being able to innovate.
If you want to win, then you have to be agile. If you want to be agile, then you have to be able to pivot quickly _and_ progress rapidly. This entails a combination of:
- Continually making the right foundational investments
- Maturing processes in sync with value realization
- Aggressively pruning fruitless approaches to free resources
Tech has gotten incredibly complicated, most problems have multiple acceptable solutions, and having your engineers slog through duplicative, non-differentiating, infrastructure-level sludge as you progress through a series of application-layer pivots is horrifically expensive, so some foundational investments in DevOps and Data Engineering are critical. Bias toward continual renovation here, but don’t prematurely optimize and don’t be afraid to give up on tech that isn’t working.
Change control and automated testing are wonderful things for maintaining agility but treat them as a double-edged sword. They are wonderful for being able to move fast _without_ breaking things when you’ve gotten proven value creation whose disruption would be seriously damaging to client relations. They can prove a pointless encumbrance when you don’t even know what you ought be building and nobody cares about it yet. Unless you find yourself subject to undue risk or drag then be prepared to tolerate shortcomings in these realms.
When wrangling application-layer development: fail fast, fail often, and do so in a highly informed way. In the short-term, leverage usage telemetry and analytics to understand how people are employing your system and where their engagement breaks down. In the medium-term, gauge interest by a willingness to become a paying customer. In the long-term, customer retention and market capitalization tell the story.
Give people what they want enough to pay to have. Time-box your bets on things where you can’t seem to get that signal. Focus and prioritize your efforts as if those were your most important tasks because they are. Always remember all of your options. Steer clear of the Sunk Costs Fallacy. Be willing to set fire to what is not working and use its light to guide your way.