Tool Complexity Might Have a Cure: Those Pesky People Who Say No
·Marco Rogers started a remarkable thread on Mastodon, which absolutely struck it home for me. Teams absolutely do get mired up in complex tooling. They absolutely can be unprepared, and there absolutely is a skew between the newly-minted “frontend” and “backend” ecosystems. I might have a few things to say about this.
There is an important point that simplicity is luxury and I am not disputing it. What I am disputing, however, is the notion that complexity cannot be contained. That complexity - and tool complexity specifically - is something we should just “get on with”.
And complexity has end-user impact too. Just a few articles to whet your appetite:
- The Market for Lemons by Alex Russell
- JavaScript Bloat in 2024 by Nikita
- React Server Components: the Good, the Bad, and the Ugly by Mayank
- and many, many more.
I don’t have exhaustive solutions or exact causation. But I do have a hypothesis of what might be one of the root causes of this complexity - it is that hands-off engineering management is a problem. Yes, caring about people, doing 1:1s, talking to stakeholders, determining career ladders and writing quarterly budgets and roadmaps is very important. But let’s not forget: software gets created. To create software, we often bump into choosing prior art - either to use, or to copy, or to study. There is a very strong undercurrent in the “modern scale-up space”, which goes roughly like this:
- People and teams need autonomy, so let them use what they pick
- Individuals within teams need to be empowered, so let them use what they pick
- We care about engineers being employable if they leave. We can’t make them code in COBOL forever just because if it happens to be our “golden path” at the company.
- We have time - and budget - to experiment with all of that. Let a 1000 flowers bloom and then we just trample over what remains and form an architecture guild to determine what “the golden path” should be
- Fresh hires will bring expertise in their favourite tools. We will disenfranchise them if we forbid these “brought along tools” from getting used.
- We won’t be able to hire and retain talent if we force them to use older, less-fancy tools.
These are workable propositions. And they are humanistic in the end - individuals on the team - and teams - can feel empowered to pick their own tooling. You don’t need to get a stamp of approval to try that new database. No directorial mandate to install that new linter. No guild confirmation to try rewriting a few modules in TypeScript. And it will make you more employable if you learn and deploy the latest alpha version of next.js instead of that antiquated pile of goop in Laravel or Rails that actually happens to earn your current company money.
But there are assumptions embedded in those propositions which are rapidly getting less and less certain.
- We have enough people to have a “frontend guild” and a “backend guild” and an “every-little-other-thing guild” to deliberate over those decisions
- We have people who will retool away from “the fancy new little thing” if it turns out to be sour grapes
- We keep teams stable and do not reorg frequently, there are no layoffs and little churn. A person doing a retool can focus not only on the retooling itself, but also on the fixing of the myriad of edge cases that emerge, on building up expertise, on documentation - and ultimately on sunsetting that tool if it turns out to be the wrong choice. They will not move on to their next backlog grooming sesh at the scrum factory in 2 weeks.
- We have enough time to help the person who misjudged an implementation or a tool choice revert. We don’t need to dump accountability on the person themselves - they have so much to do, also with all this feature dev going on!
And this all is fine-and-well as long as these assumptions hold. But the money is running out. Investors are getting impatient. The feature factory wheels have to turn faster, reorgs have to speed up - do we really need to do that nuxt-to-next transition, or move from REST to GraphQL, or do a monorepo?
All the while, there are folks in your org who knew that it would come to this. That guy who wrote the first version of the product in bare PHP, who was seen lamenting that “why is this team trying create-react-app instead of building proper browsing history support”. The lady who was asking “do we really need to use Kubernetes if we ever run just 4 servers?” The two fellows who were saying “probably Redux is going to go out of fashion soon, maybe it is not such a good idea to go all-in on it”. They were all so annoying, remember? They were no managers - and if they were, their job would have been to talk to stakeholders and do 1:1s. Them telling other engineers “not to use that thing, because it is probably irresponsible” would be “micromanaging” - and they would be entering the role of a tech lead role which is a trap.
We have effectively divorced experience from authority. And what happens when you divorce experience and authority in a production environment is that people will make worse choices. Not because they are bad at their job - not at all. But because they haven’t seen how bad tech debt can get given a long-enough streak of mistaken technology choices and experiments, and because they do not necessarily have the autonomy (and the knowledge) to work themselves out of a corner if they paint themselves into one. Seeing that corner can be difficult. Investment into an approach can be high. And it can be done for all the different reasons:
- “I want to build X with my favourite tech, because I know it inside-out” - but then you get moved to a different team, and yet another freshly formed team gets formed to support X. They carry your can.
- “Learning this tech and building X in it will make me more employable” - sure, and we know that “working at the same place forever” is a losing economic strategy. But once you do build up that experience and do leave, the people supporting X will be stuck with your choices
- “Know so-and-so are touting that this tech is Just The Best Thing Ever™®©, period. It is an industry standard!” - well, how about those people being employed at places where there are incentives to sell you this tech and to create moat? What if what you are getting sold services instead of “the right tool for the job”? Everyone can be gullible given enough persuasion.
- “This Y tech we use here is so old, barely anyone wants to touch it” - Tech being “old” does not mean anything on its own. Software rots - that is important. Are you dealing with rotting software (viscosity, rigidity, brittleness) or truly with an unsupported and unusable tech?
The issue is that we have removed people saying those things from the decision loop. If the pace is fast enough, if the pressure is on - and the VC money amply available - on a freshly formed team the likely outcome will be “as long as X gets built by end of Q3” everyone gets what they want. Stakeholders get their feature. Some folks on the team earn promotions. Some get to try the tech they aspired to try. But this assumes that the software does not get touched later, does not get expanded, does not get worked on - it is a very wasteful approach to tools and to the product. But the guy who would tell you is gone already - remember how he got dragged to HR for saying “we should not write any Cucumber here because it is nonsense!” He got the message, and after a brief PIP has left for greener pastures.
The folks on the team might simply not be prepared to revert out of mistaken tech choices. They do not have the authority, the experience and the time to be truly accountable for these choices. “Being accountable” includes “this was a terrible idea, let’s rip this out” too. “Being accountable” includes “this tech migration is a dead end and is costing us too much, let’s abort and backtrack”. “Being accountable” includes “I like that other tech better, but this tech is already in use and pays our salaries”. And yes - “Being accountable” includes saying “this was my decision, I take full responsibility for it on a personal level and I regret it, how do we revert?”, a.k.a. having the gusto to say I fucked up.
This, right here:
I am not trying to convince you that you must have a grumpy senior engineer on your team who is going to forbid the youngsters to play with new toys. I am not advocating for keeping toxic people around. What I am advocating, however, is that we abandon this notion that decisions about picking tech on teams are done either by-commitee or by separate team members for their personal enjoyment. We need folks respected enough (and experienced enough) that their “No” would not be a gatekeeper, “old man yells at cloud” type of “no”. Not a cry for “how everything used to be better”. We need their “No” to be the “there be dragons” kind. The “we will be starting on this and busy with it for 2 years and not be any better off for it” kind.
There was a great point in the discussion: whether backend folks escaped the “tooling trap” and the “retooling trap”. They did not. But the Cambrian explosion of tooling in backend went about around the early 2000s - when everyone was trying to sell you SOAP, and Middleware™, and J2EE, and many other amazing things. Back then quite some people started working on small teams where using all of that was simply too much - and they were solely responsible for delivery. Being personally accountable and responsible does get you places. If there is no “frontend guild” to pull you out of a trough where you got yourself by trying out React server components, you will try them (or similar tech) a couple of times, and learn both what the strengths and weaknesses are, and how to revert out of it. That reverting requires both experience and autonomy. You can give people space to acquire that experience on your team, but it takes time - and budget. And it takes actual, applied accountability - a.k.a. “you broke it, you fix it”. I, personally, never use fancy cloud databases exactly because I am accountable for them not breaking on us. I am accountable for reverting out of them if they don’t work, or cost too much. I am accountable for every member of my team spending extra 10 seconds on every Git commit because suddenly your entire codebase runs Prettier through a commit hook (I would not allow such a thing, and - yes - this is a real story). And I could never give my team a guarantee of that support if I were only allowed to discuss “how do you see yourself at this job in 5 years”. We don’t have 5 years. We have a week.
There is some more color to add to the question of Web/UI engineers being often regarded less than other kinds of engineers though. I have never seen this being the case (lucky, I know). What I did see is that we have devalued full-stack web engineers, because “they would be bad at both”, because “modern frontend is too complex”. Where that has led is that the (not-at-all-)mythical full stack engineers are exactly the people who would YAGNI at you for using all this fancy stuff you so ardently advocate for. Because from a full-stack perspective a lot of problems in frontend are not that hard - if you approach them holistically. No, we are not going to use a programming language’s import
keyword to bundle SVG animations into our source code. No, we are not going to be rendering JSON fragments when the user already gets complete HTML. No, we are not going to create a whole new API just to load one flat gallery of photos - a pre-rendered div
will do just fine! Once those people get reprimanded often enough - they will stop speaking.
Another tricky part with bad FE decisions being hard to revert from is that there is just way more of frontend. React specifically encourages you to make smaller and smaller components, touting composition as the benefit you will get from that. And you will, but you will find yourself with a codebase which has thousands of components. Good luck codemodding/changing them all in a safe, compatible way - and if you used something like Redux it is likely that a few hundreds of those components will depend on Redux, in an intricate way too. With backend work, you can sometimes rip out an entire service and replace it with another (if you haven’t allowed very complex interfaces into it) - not so with a thousand components, which also need to be updated incrementally.
Note that I am not saying that “all this new fancy FE stuff is just too fancy” - not at all. The React crowd have done some exceptional work with tackling some very real complexity for specific types of software. A lot of what they learned applies elsewhere, and can - and should - be amalgamated into other technology we use. I am not saying that “we should use less fancy tech” just because I would want to remove tech introduced by people who disparage me and quit my company. I am talking about the fact that you need people on your team (or teams) who both do hands-on work - and do it well, and are empowered to make decisions, with empathy.
And yes, sometimes they will say “no” to that new fancy linter/JS router/Rust WASM module/Neo4J. They likely mean it well. The free lunch is just about over and their insights may prove very valuable.