When I first started programming I was like a gap year student exploring some far-flung bazaar. Every twist a new adventure, each turn a novel experience. Intelligible languages swirling around my ears, but recognisable expressions and hints at meaning abounded. Discovering new paths through what felt like a hidden world was so exciting that it pushed me to dive headfirst down the rabbit hole.
As I acquired more skills and wrangled more conceptual models I was buoyed by my mastery of the machine (the sort of mastery that any good craftsperson only feels for a brief period before learning how little they know.) But when chasing the horizon there’s always more to explore.
But then something kicked-in around 4 or 5 years after I first tickled the keyboard with the intent of development. I was turning the pages of pixels on the web and even the odd dead tree to quench my thirst for new ways of thinking and controlling the big grey box in the corner of my parent’s lounge. (Aside: I think this new found hobby was significantly cheaper than paying for child care!)
Up until then I had built innumerable dummy interfaces in Visual Studio Basic, built a death clock in C (I promise I had a happy childhood), and picked up my surfboard to explore the web.
But I was constantly just lighting mental matches, not quite starting an enduring fire. I started to tap out classes and dynamic websites. I was left alone in a professional kitchen without a single day of catering college to guide me, just a vague idea of what some of the utensils would do.
I started to yearn for complexity. I skimmed tutorials on map-reduce and heard about a mythical program called borg. I discovered Apache and then Linux.
I jumped up the abstraction stack right up to web development and as I did the whole ecosystem was evolving around me faster than ever. I discovered Chris Coyier’s epic stylistic adventure simply by Googling “css tricks” and John Resig’s toolkit before it was ubiquitous. This continued until I had around me a vast array of tools and an infinite number of combinations thereof.
Before I knew it my new focus was on mastering this complexity. To find a new mental model of the machine and build a grand network of high-speed rail stations and interlinks with me at the centre, making the trains run on time.
The allure of complexity is potent. I was gripped by its siren song for a good chunk of my development career, and I’ve only just kicked the habit. Although I’d say I’m still a recovering addict. Throughout my professional life while under the spell I did get glimpses of a life without such needless complexity – usually when time pressures would squeeze project scope and negate the possibility of a sprawling codebase.
I’ve come to realise that this desire for more complexity is a natural side-effect of learning to program if left unchecked. Anyone that studies computer science knows that it’s essentially an exercise in looking behind the curtain. But even without any formal education, the more advanced you are in you learning, the fewer black-boxes you should have in front of you.
In fact, as you master each level it’s implicit that there will be a next. And each complexity hurdle you overcome makes you feel great.
Before you know it you’re applying ultra complexity to every situation. Someone needs a new website? Better deploy Kubernetes to power your microservices which talk to your SPA.
“But Tom, you’re just being a curmudgeon. Get with the program man! Look at how easy it is to do this thing here!”
The majority of developers are statistically distinctly average. But that’s okay. The majority of chefs (insert any other profession) are too. A pub lunch doesn’t need to be a mind-altering experience. Fast food is measured by speed not flavour.
But because being a good developer means constantly learning and trading up your toolkit, many look to the 0.01% of companies that require different tools to the rest of the community. Netflix has oodles of microservices, so does Monzo. They’re building whole districts of skyscrapers, not a house in the country.
That’s not to say that we should ignore them. Key advancements typically only occur in such environments, and can benefit the whole community in the long run.
Let’s take React. I bloody love React and its cousin React Native. But we’re now in the position that a huge number of developers don’t know how to build a website without it, but more of a concern – they don’t understand the tradeoffs of using such a tool. And I’m not talking about speed here, I’m talking complexity.
When you build a React app (insert other front-end framework here), you amp up the complexity by an order of magnitude. You’ll need to build out your views, bake in state management, synchronise with the server, cover latency and security issues, loading states, and ensure that you can debug it in production. Oh, and you’ll need a complete API layer building out.
The biggest hint that you’ve fucked it is when someone suggests server-side rendering to improve performance.
Contrast this with frameworks like Django, Rails, WordPress, and countless others that allow you to render complete, performant sites without rebuilding views once the user’s browser has loaded.
The same applies to tools like k8s and paradigms like microservices. They’re extremely powerful methods for building certain types of software, but they’re the industrial skyscraper air con systems to your trusty desk fan.
I’ve come to believe that the really great engineerings among us abhor needless complexity, while most see it as inevitable.
Not doing something in the first place is the best course of action. But removing complexity is the next best step.