Let me start with a short scene that happened some time ago, at the peak of the IT job market’s craziness.
We were interviewing a senior candidate with 10+ years of professional experience in serious, enterprise brands: mostly large organizations that do business the “traditional way” and do not have to compete vigorously (as their position is well-moated). It was the first candidate of such a profile that we interviewed - we were running out of Ruby/Elixir candidates, so we were determined to hire ANY software engineer open to re-qualifying (to Elixir/Phoenix tech stack).
My co-interviewer (let’s call him “K”) was my most trusted aide - a true right-hand man. A badass engineer all the people loved to work with: pragmatic, reliable, sharp, goal-oriented - working with him was always a true pleasure. But K came from a very different work environment than our interviewee - he worked for indie software houses in a very competitive environment. K was always paid for the tangible results. K was always fully held accountable for his words (including technical/architectural decisions and recommendations), and, due to fast development processes, outcomes and gratification (was he right or not?) were not delayed long.
The interview went quickly. We have played our parts, K has asked his questions, and presented his problems to be solved by the candidate. He did his usual dose of deep dives and follow-ups as well, but I’ve seen some confusion on his face. The moment the door closed behind the candidate’s back (yes, this was the onsite interview) - K gasped and asked me (not his exact words, of course, but that’s how I recall them):
“What the hell did he speak about? Does ANYONE really work like what he just said? Why are any companies hiring such folks?”
If you’re wondering what has upset K so much, you’ll need to read this whole blog post (or cheat-skim to the very end 😄).
OK, first things first ... We need to build up some chain of thought that will make the forthcoming conclusions reasonable.
The employees
The ZIRP period (& the massive hiring demand in IT) turned developers into "sacred cows" of a global job market. It was so hard to get anyone able to code on board that even a major lack of pragmatism was tolerated (as an unavoidable "tax" on efficiency, one doesn’t talk about openly) - grab ‘em before someone else does!
As those market conditions lasted for quite a long time, smart folks could exploit them to accelerate career progression in software development (”either you promote me or someone else will”). Unsurprisingly, in many cases, the rapidly increasing "seniority" (e.g., from zero up to “senior” level in 2 years) was illusory - based on collecting more and more tech acronyms in CVs (due to frequent job hopping) while getting feet (barely) wet in the most trendy topics around (microservices, DDD, hexagonal architecture, eventsourcing, etc.).
Why am I so dismissive about that (“getting feet wet”)? Because it was mostly sheer theory, very far from practical reality - drawn from popular books (or - even worse - just their summaries ...), blog posts, or online courses (frequently of a questionable quality, sometimes a straight sham that promised to “turn you into a fully fledged architect in 4 weeks”). There’s nothing wrong with theory per se, but quoting Werner Vogels (CTO of Amazon):
“There’s no compression algorithm for experience.”
So here we have the cohorts of those young folks, fed with bullshit bingo, mostly unproven in truly challenging conditions, but with very high self-esteem.
The employers
But these are just employees, what about employers? Employers had their issues as well ...
Let’s be honest - we’re all fed with spoonfuls of stories about exceptional companies with unique cultures, the best people (”A players who want to play with A players only”), outstanding work environments, and working on products that change the world. But such organizations (if they exist ...) are extremely rare exceptions - the reality is much more mundane. An average organization:
- has an average (or worse) culture that doesn’t stand out (at least positively)
- faces issues with really basic things like setting up effective development processes or building a data-driven feedback loop
- did not manage to cultivate a result/value-driven mindset (maybe except the Sales team)
- fails to inspire its employees in any way (aka make their work meaningful in a way that resonates with intrinsic motivations)
Of these four (which, of course, do not exhaust the entire list of typical organizational sins ...), the final two are probably the more impactful in the long term. Young, even relatively ambitious people, are keen on doing something that will, in the end, make them feel PROUD/SATISFIED - if an organization fails to create conditions for that, it’s a massively wasted opportunity.
The collision course
If we mix these inexperienced, but overconfident employees, who have a skewed understanding of the true purpose of their work, with dysfunctional employers who fail to engage their crew, what do we get? The bored software developers who look for ANYTHING to care about ... Not surprisingly, they typically end up with something within their comfort zone, something straight from their “bullshit bingo”. As the overall success seems too ephemeral and beyond their influence, they focus on “technical success” achieved by “technical excellence” in all its possible weird dimensions: code aesthetics, architectural cleanliness, “good practices/patterns” purity, etc. As if that’s what customers/users care about ...
TBH, engineers who suffer from this condition are quite easy to tell:
- The most frequent terms/concepts they mention & refer to are "hexagonal architecture", "event-driven"/"event-sourcing", "aggregates", "microservices" ...
- They always have to use Kafka for something (because Kafka “decouples things” & “is scalable” ...).
- Even if everything they put their hands on is "domain-driven", they would rather avoid talking to non-developers and struggle to explain the value of products they've created so far.
- When they have to code something live, 75% is boilerplate (“solid architecture has to be created first”), and they always run out of time (regardless of what they build).
- They fail at reflecting ANY business abstractions in their code, but they produce tons of "domain services", "application services", "event handlers", “data access objects”, and all other useless crap (aka purely technical abstractions, stacked one on top of the other) instead.
- Their naming is freaking terrible - rushed, inconsistent, ungrammatical; apparently, their version of DDD excludes such meaningful details like Ubiquitous Language.
Instead of crafting and connecting DOMAIN abstractions, they focus on 100%-artificial TECHNICAL abstractions that do not solve business problems, but “make the architecture more CLEAN and AESTHETIC”.
On the other hand (YES, I am over-generalizing a bit, but I’m not ashamed of that) ...
- They never had to optimize anything IRL - fortunately, their favorite cloud has so many tiers, and there's always Redis for caching ...
- (High) Availability is never an issue (according to them ...), as they deploy on Kubernetes 😅.
- It's not just that they can't craft testable code - in fact, the majority don't even know what “testable” means (on practical terms).
- They don't know how to craft a proper boundary contract - what matters is "to have resources", "to use HTTP verbs" and “to return proper HTTP codes: 2XX, 3XX, 4XX, 5XX”.
- Very few have any practical experience with RUNNING the code (in production, under real obligations) - proper instrumentation/observability, understanding of the consequences of distribution (cascading time-outs/failures, race conditions, ghost reads, etc.), techniques of effective trouble-shooting, etc.
- The code they write is terrible for reading - they don't know how to properly structure, comment, and organize the solution (even at a small scale); “properly” in this case means, e.g., atomic functional changes should touch the least possible amount of code, it’s possible to zoom in/out through solution’s abstraction/detail levels, implementation details are hidden behind deliberately designed, business-understandable contracts, etc..
- They struggle with explaining the rationale behind their architectural choices - the answer is typically: "this is by the XYZ book", "this makes the architecture clean", “this way we can apply pattern ABC”, etc.
To truly understand the nature of some challenges in software development, one has to experience them in practice, experiment with various solutions, and “feel the pain” (consequences). Possibly from various perspectives (e.g., service provider and service consumer). That’s much more useful than sheer theory, processed and "dosed" by someone else. There are no shortcuts here.
Not evenly distributed
As you’ve already guessed, the candidate I’ve mentioned in the short story above was a devoted zealot of this “school”:
- All he cared about was the “technical success” expressed in his understanding of what “technical excellence” looks like.
- His work quality criteria were 100% about code and what he meant by “architecture” (which, in fact, was the low-level code structure & composition), not runtime characteristics (e.g., famous architectural “-ities”)
- He never saw that, but he was already stuck in an endless loop of refactoring and rewrites, aimed at fixing imperfections and flaws of existing architecture (typically his own past bad decisions, unfinished “transformations”, and whatever he erroneously qualified as “technical debt”) - the majority of them imagined, exaggerated and/or simply meaningless.
Undoubtedly, he was a smart individual, a skilled code-crafter who knew the language/framework syntax very well, and a passionate enthusiast of several catchy “trends” in modern software development (even if his understanding of those was pretty shallow, due to focusing on WHAT instead of WHY). Unfortunately, he was also a MEDIOCRE (at most) ENGINEER - definitely closer to “junior” than “senior” level. Why so?
- His decisions/recommendations were driven by some weird (and ephemeral) “code aesthetics” (instead of end-user/business value).
- When asked for justifications/clarifications of his technical choices, he was never able to establish a chain of reasoning that led to any tangible data points/facts.
- He lacked pragmatism at every possible level/dimension.
- In the end, he was not able (I know - it’s nearly unthinkable!) to connect his everyday work to how the company makes money/creates value. From his standpoint, he seemed to have been hired to do “great engineering” (as he understood it), and the rest was someone else’s concern. And he was earning NNN not because he could create more value than that, but because “that’s how much the job market values individuals like him”.
Well, you know what? Market is a b*tch ☹️ ...
Btw. contrary to naive belief, solving the problems by mechanically applying patterns is not and never was a sign of master proficiency. Have you heard about the concept of Shu-Ha-Ri? In case you didn’t, feel free to check this post out.
The sad thing is - he was not the only one. The population of like-minded software engineers is substantial and, according to my observations, it was growing steadily (at least until recently). It’s definitely over-represented in large enterprises, among the ones who use the tech stacks most commonly used in “legacy tech” (.NET, Java). I attribute it to their weak engineering cultures, low transparency/accountability, and limited expectations regarding the results/value delivered. AKA: developers were completely out of focus, playing around with whatever they found fancy, and their managers/directors didn’t even know/care.
The issue is much less visible in software houses, especially those that work in "fixed-price" mode and/or use niche, "hippie" technologies (Ruby, Golang, Elixir), and it's nearly non-existent in the top-performing engineering workshops of strong culture (e.g., hyper-scalers), especially the most data-driven ones (where bogus opinions crumble when faced with raw facts). The same applies to truly product-focused companies (start-ups/scale-ups) where there's simply no space/tolerance for such bullshit.
It ain’t figure skating
Cut the crap out.
Serious software engineering ain’t ART, and the “artistic impression” doesn’t matter AT ALL. What matters is not “aesthetics” but whether things do what they are supposed to do or not. And - regardless of whether we like it or not - the reliability and speed of delivery. This is not figure skating, but if you’re into sports, you can think about it as running a marathon - what matters is pragmatism, discipline, consistency and simplicity. These few do much more when it comes to scaling than all the distributed computing and enterprise integration patterns combined.
Perfectionism is among your worst enemies. There are 1000 things you could do now that seem to make sense, so the trick is in picking THE ONE that actually brings most of it. It’s called pragmatism, and it’s an inherent part of this job.
Feel free to read any books and go through any training courses you fancy - it’s your time and money after all, and maybe you’ll get the inspiration you’re looking for. But always apply your own critical thinking, e.g.:
- The authors/tutors/speakers - what did they build/achieve? When? In what conditions? What is their credibility based upon?
- Do I understand what problem X solves? Do I have this problem? Is this problem at the top of my list?
- The actual high-performing companies (in my league when it comes to complexity/scale/inertia/etc) - how do they solve this problem?
I guarantee you that the actual solutions that have made a difference in the past actually are not that appealing, “aesthetic”, and covered by so many fancy courses, but they have one, underappreciated advantage - they work.
Parting words
And to give you some food for thought ... Maybe you haven’t experienced that personally yet, but the market IS TRULY SHIFTING. Employers’ position has improved a lot, and they won’t hesitate to exploit this long-awaited advantage.
Senior+ engineers are NOW expected to be real team force multipliers who make an actual difference. Whose impact goes beyond themselves and their own work. They have to establish credibility with an explicit list of specific, meaningful achievements, with their personal stamps pressed up against them. And don’t expect anyone to be impressed with items like (without a deeper, value-oriented context):
- ... introduced functional programming to the team
- ... refactored the main application into 18 “microservices”, each of them at most 500 lines of code
- ... replaced RESTful API with GraphQL
- ... migrated data (the whole 800 MB!) from PostgreSQL to Cassandra
So, what’s on your achievement list?
