The emptiness at the extremes

Immutability will solve all our problems, but only if it’s applied perfectly everywhere.

Mock everything.

Microservices, the more, the smaller, the better.

Advice that can be applied with little understanding of the problem rarely has good results, but it provides short-term satisfaction, a feeling of safety and, thanks to the ease of application, a delusion of speed.

You find a rule that is easy to apply everywhere, without any attached “it depends” clauses, a rule that you can just throw at the problem without doubt or surprise, in other words a rule that allows you to stop thinking, and you run with it. Until, at times years later, you look around and you discover you made a mess.

I’ve dozens of examples of rules that people are expected (and enjoy) to apply mechanically. Picking one group to use as exemplar is difficult, but I think naming patterns should do.

In programming we often have to give names to things. In software we create things very easily, and thus we do it all the time, I love it, but it’s a mixed blessing. It’s a bit like being a too-powerful-for-your-own-good wizard, who wonders what name to give to yet another eldritch entity he materialised with a flicker of his fingers. Is it a physical object? Is it a concept? Is it something that exists already, but you can’t recognise in its current aspect? Or is that similarity only superficial and you should resist the temptation to use the same name as before? And so on.

In short, giving good names is hard; which means that it is easy to give in and use naming patterns.

Once a developer starts using naming patterns they think less and less about the right name for what they are looking at. It could start with things that were legitimately difficult to name (and maybe should not have existed in the first place), but soon even entities that would be relatively easy to name become instant word salads of generic platitudes. Many a thermostat, pro-rata invoice, or window handle have been born as HeatingManagerImpl, ContractDataDto, or IUserInterfaceStrategyManager, without a second thought, nor a second chance.

Turning off the brain while coding is easily mistaken for effectiveness. I’ve even had people complain of the lack of a “naming convention” because “without it, giving names is hard”. My dear, finding good names is supposed to be hard, and I’ll be damned if I give you an excuse to shift to sloppy names under the pretence of standardisation. Take responsibility and call it “Foo#13”, at least the problem will not hide under a coating of glutinous prefixes and postfixes.

This does not mean that there is no useful guidance about giving names, there’s plenty, and here’s some, just to get a feeling :

  • Use simpler, more abstract names for high-level concepts, and more specific, possibly longer, composed names for specific implementations of those abstract concepts.
  • Minimise specialistic jargon, but use names that are meaningful and used by the people who work in the domain you are addressing.
  • Avoid using synonyms for different concepts, and conversely avoid using different words for the same concept.
  • If, after a lot of effort, you still can’t find a good name, do wonder if perhaps you created a weak construct that has no significance and review your design.

Again, these are just examples, far from exhaustive, but they are all providing guidance that will be unlikely to push you into mechanical, rapid, unthinking naming.

Notice that none of the points above make it easier for you to find a name, if anything they make it harder, because they stop you from picking a bad name, while they don’t answer the question “what is the name of this thing?”. That’s still for you to answer, and now you also should avoid some common mistakes.

This is often the defining feature of virtuous guidance: to add constraints that avoid common pitfalls, pushing you towards a harder, truer, path. Without feeding you a solution. It’s a feature of valuable practices and disciplines that has become more visible and noticeable to me over the years. Tdd, for instance, is almost entirely a constraints machine.

The complementary observation goes well beyond rules, to me it has become a ubiquitous heuristic of knowledge-based activities, from software design to organisational thinking, from product strategy to staffing: if it’s setting you on autopilot, it’s likely a bad idea/rule/choice/design/professional stance/mindset.

For simplicity, I’ll call these things that set you on autopilot “fudge”. Because fudge is sweet on the short term and lethal on the long term, because fudging one decision after another is often the result, and finally because “fudge” has a tradition for being used in software engineering talk. I really hope I got my naming right! We will see.

I can easily bring this to the space of development methodologies : every “agile” framework that highlights a recipe is doing a huge disservice to its practitioners. Instead of solving for “x” using all their skill and knowledge in agile principles and practices, where “x” is their context, they apply answer “42” to “x” and then, if they are still awake, they rediscover their skills and knowledge as they try to make “42” work. By the way, that’s the least negative outcome: very often there’s no skill rediscovery, no return to principles-based thinking. As the pace increases (because, hey, that agile transformation has yet to produce results), the tempo is tolerable only if the next organisational decisions are taken with machine-like speed, applying more recipes.

Principles (and careful thinking about problems) die in the race for the next recipe.

So, what I am saying is that the rule is “never apply rules that provide a solution”?

No, because that is itself a rule that provides a solution, it will have you stop thinking, because it is yet another fudge rule. If you try that, reality will once more provide a cold shower to your little, homogeneous set of automated decisions. For instance, you’ll find that trying to work out everything from first principles is too resource intensive, and it doesn’t provide enough structure for large scale collaboration. If you manage to break free from that rule’s spell, you’ll probably decide that you need some quick, problem-solving solutions, some hard and fast structures in your organisation, some basic practices that you won’t reconsider every other day, to free time to use good, hard, practices and disciplines on the creative, deep knowledge-based work.

So the rule is “Think! Find good rules that improve your decision-making, but no rule will ever think for you. Be wary of those that would have you believe otherwise”.

Just enough

The distinction between fudge and non-fudge contains another dimension : even non-fudge practices can be used blindly, especially when you crave that misleading feeling of safety and productivity. For instance, many tdd users picked up the practice with the expectation of not having to know design, because tdd would supposedly design the software for them. Tdd done well will accentuate and accelerate the pains induced by design mistakes, giving you more and earlier opportunities to improve your design, but to improve your design you’ll still need to know, and, more than knowing, to feel, where the breeze of a good solution is breathing from.

One way I model this is with the metaphor of spectra of idea application. Whenever there’s a rule/state/practice/idea, we can identify its opposite, and thus we are defining a spectrum. It’s for me an established fact that even the most virtuous idea turns out to be a horrible liability when you go 100% one way or another of the spectrum. Doing 100% something entails applying it blindly. A very good idea can certainly yield good outcomes for a while when applied blindly, but it’s a very fragile situation. The lack of thought entailed by the 100% application means driving without sensory input and without a feedback loop: it will eventually derail into disaster.

This is what I call the emptiness at the extremes: the lack of good outcomes, the lack of conscious thought, and ultimately the lack of humanity, that is to be found at the extremes of the application of any idea, no matter how good (or bad) it is.

For instance, if I put team empowerment in relation with top-down decision making, I will find at one end the rule “the team has the final say on everything” and on the other end I’ll have “the team does what it is told to do”. I am a huge proponent of team empowerment, but I think that establishing as absolute rule that a team decision will never be overridden introduces a fragility around situations where, for instance, the team starts a self-destructive cycle, or where the team is simply not mature enough.

We need to have just enough top-down decision making to safe-guard against those rare corner cases (presuming that the organisation is doing its job of growing generally mature teams, otherwise those corner cases are not rare at all). That little bit : “just enough”, makes the system centred on team empowerment stable: without actually removing any empowerment it keeps the organisation alert, rather than an automaton repeating a mantra.

Within that “just enough” lies the skill, the ability to think based on principles, the deep knowledge and multivariate model pruning at which trained humans excel. All those elements are required to move out of fudgey-rule-application and into wisdom. They are a hook that allows the complexity of the outside world to seep into the originally “pure”, mechanically applicable, idea, and thus make it worthwhile.

Since the difference between the presence and the absence of the “just enough” clause is the difference between the presence and absence of thought, between idiocy and self-adjustment, and thus between long term disaster and potential flourishing, it would seem that all the value, once the main good idea is found, is coming from that messy hook into the complexity of human skills and context.

I believe the irreducibility of complex systems explains why the lack of a just enough clause is a recipe for instability and disaster for any effort related to knowledge-based work. Still, I would like to describe my own theory for why it is so, from a more evolutionary angle.

Why should it be so? Why we can’t just blindly apply rules?

Why are we doomed to choose between the guaranteed eventual failure brought by clear, thought-sterilising fudge rules and messy, still at least potentially wrong, hard to explain disciplines?

Because, I believe, knowledge-based work is defined by difference : it’s the space where we have not yet developed a mechanical strategy for good results. As soon as a problem is solved, especially in software, where instantiating a library that solves that problem is a matter of instants, that problem does not belong anymore to our field, it belongs to the background, to the scaffolding of civilisation.

This has put evolutionary pressure on all the remaining problems : in order for a problem to persist, and thus catch your attention as a knowledge worker (i.e. you have not solved it with a google search, a chat with GPT, and resulting seamless instantiation of a solution), it must fall into those problems that have yet to get a mechanical solution. Presuming that you can pick some rule and expecting to solve that problem without continuous adjustment and ingenuity, means facing one of the fractal tigers of our universe with a stick.

So there’s no hope to solve the problems that plague knowledge-based work?

No, just like careful design and excellent coding can achieve good software, and that has become easier since the days of punch-cards, there’s hope: by careful experimentation, and by using all our ingenuity, we can build better and better theories, defining more powerful models, and reduce the space of knowledge-based work, of heuristics, of craftsmanship.

But that’s highly focused work, not stuff that you do in-between steering committees, and certainly not without very good formal training.

Until that happens to whatever you are dealing with today, we are all better off not thinking that any of the easy solutions at the extremes will lead us out of the forest, we better stay awake and wary of any rule-induced comfort zone.

I stopped using “fudge” towards the end. Probably not a good name then.