EntriesAbout

Maximalist Minimalism

Premises

Two somewhat-contradictory ideas that I hold:

  1. Too many people in the tech world make too much of a fetish of “minimalism”
  2. Too many people in the tech world vastly over-complicate things.

Now, presenting these two things as opposites is something of a false dichotomy – it’s entirely possible (and maybe even probable) that a surfeit of minimalism at one level may lead to over-complication at another – but the representatives of the two camps as broadly outlined are in generally opposition to each other. We might think of it as the vi/go/musl school versus the vscode/electron/kubernetes school.

One group holds that the problem with technology is over-complicated (and I agree!) and that the solution is to pare things down, remove excess complexity, go back to the good old days, and tends to have a somewhat elitest point of view that the problem is new developers being stupid.

The other position seems to be that the problem with technology is that we’re demanding more than ever out of it (and I agree!) and that the solution is to improve tools, build more complete, more user-friendly abstractions, that ultimately delegate the complexity to a elite caste of toolmakers.

In both cases I largely agree with the premise and some of the conclusions, but tend to oppose the schools as a whole.

Minimalisim

I’ve written about my issues with the “cult of minimalism” before, but in short my problem with it is that it tends to heap blame on the programmer, assert that failures of the tools are failures of the wielder, and seems to me to have a generally reactionary, conservative tenor. It may be true that “it’s the poor craftsperson that blames their tools”, but if the tools are aggressively difficult to use and resources for actually learning how to use said tools are desperately wanting, it’s not especially surprising that people get discouraged and look elsewhere. This point of view ultimately seems to argue for doing less, because it’s easier to do and results in more aesthetically-pleasing programs.

While I certainly can appreciate how nice it is to have a beautiful program, almost mathematical or poetic in its simplicity and directness, if you want to write programs real people actually use, that doesn’t last long. Handling different locales and character sets is often a glaring weakness of minimalist exemplars, not to mention other forms of accessibility. Other programmers may like looking at your code – and that is certainly a valuable thing, especially if you want to encourage contributions! – but users that aren’t programmers will probably be discouraged; both by the lack of features of the program and the condescending attitude such projects tend to display to non-programmer users.

In short, the “minimalist” programming methodology seems to me to be for programmers over users: Make programs that are simple to write and easy to change, rather than trying to anticipate needs. Again, I don’t disagree with that in principle, but in practice people’s needs are complex and addressing that essential complexity will make the code no longer simple; something that tends to be bitterly resisted.

Maximalism

On the other hand, we have giant, complex systems that are used to solve giant, complex problems. Three immediately come to mind for me: SystemD, Electron, and Kubernetes. The first two are roundly despised by not only many in the minimalism camp but by many programmers generally, while the last is (as far as I see) generally tolerated, seen as a necessary evil.

SystemD has been explained and debunked and counter-debunked many, many times already and fortunately seems to now be more broadly accepted by most non-partisans. I won’t really dwell on that too much: My perspective as a long-time Linux user and sort-of sysadmin, I like systemd because it unifies what was previously a bunch of arcane shell scripts and greatly simplifies many tasks. I have written a lot of shell script in my time, I’m comfortable with lots of Linux esoterica, but systemd is just easier and doesn’t really have any downsides to me. Pretty much all of the “downsides” I see people complain about tend to be of a more philosophical nature (the old “Unix way!” canard comes up a lot), but it’s a philosophy I don’t subscribe to.

I can understand why people dislike Electron. Many professional programmers, especially those that started programming some time ago, tend to have a visceral dislike of Javascript and Electron seems to represent Javascript taking over the world of “native apps”. Again, I sympathize – Javascript is not my favourite language, it has many warts, and I really dislike its package ecosystem. However, people complain about Electron apps replacing native apps, how it results in so much RAM consumption, CPU usage, is inefficient and represents “laziness” on the part of developers.

My perspective is generally that it’s not “electron vs native app”, it’s usually “electron vs nothing” – especially for Linux users. It’s a huge pain to write multiple native apps, not to mention that it’s not exactly clear what “native” means for Linux anyway – GTK (3 or 4?)? Qt (with it’s weird licensing issues)? X11? Wayland? No matter what choice you make, people are going to get mad at you

I’m certainly not against native apps. I also develop for iOS, but I can completely understand why one wouldn’t do that! It’s a lot of effort and expense to get someone to learn Objective-C and/or Swift (languages that are essentially only useful for Apple’s platforms), learning UIKit and/or AppKit (and/or Catalyst, and/or SwiftUI), and then wrestling with Apple’s god-awful documentation and IDE, and that’s just for one platform! If you also want a Windows app, you have another gigantic amount to learn, and Linux support is at that point pretty unlikely. Users can derive a lot more benefit from an electron app that is in front of them now, not three years from now, and works on all their friend’s computers as well. I sincerely doubt many users that aren’t programmers know or care what electron is because it doesn’t affect them.

There is a part of electron I dislike though, and that’s the Javascript ecosystem that comes along with it. Much digital ink has been spilled lambasting that, so suffice to be say that it’s frustratingly over-complicated, fragile, constantly changing, and generally a sad state of affairs.

Kubernetes is something that, every time I read about it, I just get frustrated. It seems to be the apex of a certain sort of programmer fashion trend, the exact opposite of the “extreme minimalist” that says “abstract absolutely everything” and “cloud scale”. The notion that we need to be using whatever the FAANG companies are using, to deal with the problems of our massive scale. These things always seem to me like just creating your own problems, making increasingly complicated tools to fix the problems, then layer even more complexity on top to address the complexity of the previous set of tools. Even Docker seemed somewhat ridiculous to me and the extent to which it has metastasized into this leviathan system of orchestrators and containers and oceans of YAML seems nightmarish to me. This is where I start to come down on the side of the minimalists – this is complexity that is unneeded, if people could just learn their tools better! If were actual sysadmins with expertise hadn’t been off-shored and then fired, maybe it would be possible to just deploy applications on a server without it needing a zillion layers of tools and config files.

These massive systems tend to lead to a sort of bifurcation of programmers into the plebians that just use the pretty tinker-toys and the “real” programmers that build the tools for them. Sure, there are going to be different levels of skill and ability, to I fear that this sort of “just use the monolith” approach really discourages learning and makes new programmers learn that the implementation is on another level from them, one they’ll never be able to work at.

Synthesis

That’s the solution then? Unfortunately, complex, gray-array “it-depends”. It’s very unsatisfying to say “do as little as possible, but no less”, because that’s such a subjective, hard-to-nail-down thing. Ultimately though, that’s why programming is a craft that takes time to develop, not just a cookie-cutter approach that can be blindly applied everywhere.

The desire for simple answers is, of course, a much broader problem than just in programming. We live in a complex world and have limited resources, so anything we can do to replace difficult reasoning with easy-to-apply rules is welcome. Of course, those “easy-to-apply rules” are what biases are; something that we generally are taught are “bad”. Even that dismissal as bias as bad is itself an over-simplification though! The bias against biases can be replaced with nuance, realizing that some biases are useful (e.g. if food smells rancid, being biased against eating it is probably a good trait), while some are not. Who has time to carefully examine all their biases though? One of the big advantages of living in a society is that we’re taught biases that save us having to learn bitter lessons ourselves. A senior developer teaching a new hire to “always put curly-braces on your if-statements” is giving them a rule that they’ve learned the hard way, in the hope that the fledgling coder won’t make that mistake again. This sort of cultural knowledge is how we develop and hone our collective craft over time.

However, maturity is realizing that your mentors might not have been wrong, per se, but that they were giving you a simplification that was appropriate. To develop further, you need to learn the reasons behind the biases you were taught. Instead of just pursuing minimalism for the sake of it, try to think about the why: They wrote minimalist code, because it was a time where things were changing rapidly and every user was also a programmer, so making things easier on programmers also paid off for the users. Similarly, giant tools like Kubernetes are made to deal with the problems of scale beyond what almost anyone actually needs to do with: Abstraction has a cost and one should only accept that when it’s a net benefit.

I think the commonality in what I dislike is that programming becomes a fashion statement rather than a means to an end. Both the ultra-minimalists and the sprawling over-engineering maximalists are both trying to use their way of programming to indicate what kind of person they are: Intelligent, frugal, crafty lone-geniuses, or modern, professional, best-practice-gurus.

I certainly enjoy programming for its own sake, but when making something that’s actually for other people, I need to make sacrifices. I sometimes need to throw away the beautiful, elegant code because it wasn’t solving the problem users actually had. By the same token, I can serve users better if I think carefully about what is actually needed now and solve that problem in the most direct way, not the way that’s going to make me look the best.

Of course, I’m quite privileged in that regard – I run my own company and had the access to learn many different languages and frameworks in the past, so I’m aware my options aren’t available to everyone. This isn’t meant to be prescriptive, but more of an attempt for me to attempt to reconcile my opinions to myself.

I just want more people to be able to both feel the satisfaction of making something genuinely useful and being able to fully understand how the whole thing works.

If it’s stupid but it works, it isn’t stupid