« Simulated Annealing

There's no accounting for taste

Future-proofing your career as a software engineer

Looking ahead to the future of programming that increasingly involves LLMs, it’s becoming clear that the most important thing for software engineers to cultivate is taste. As I discuss in GenAI is not a silver bullet, training great software designers will continue to be the essential challenge of the industry at large. The opinions and style of these humans is what will distinguish great software from mediocre as the cost of outputting the code itself continues to precipitously drop.

What is engineering taste

Even though we’re still in the early days of AI-assisted software development, we are already seeing a big gap who can most effectively leverage LLM tools. Senior engineers can consistently get more long-term value by deftly minimizing autogenerated bad code through best practices and technical discipline.

Non-engineers and less experienced developers often hit a wall at 70% of a project because they lack of knowledge and inadvertently create mounting tech debt. Minor mistakes can compound into a terrible mess of a codebase. And even if the code itself might work, it can suffer from fundamental limitations in the chosen architecture. By its very nature code is not self-healing and is prone to software rot, so much so that most of the work of software engineering is actually maintaining legacy code to ensure that systems don’t actively degrade.

Unfortunately there is no easy shortcut to upleveling to a senior engineer.1 While many of the elements of high quality technical craft can be learned through study, there is a certain intangible intuition that can be only gained through lived experience.2

This kind of expertise is even reflected in our technical jargon. Typically, engineers use language that is concrete and often obnoxiously precise. But inevitably there are vague problems that have equally squishy terms. Systems can have “code smells” and proposed solutions don’t pass the “sniff test”. Even inexperienced developers can detect these suspicious patterns, but they don’t know enough to determine if it’s a real problem or how to fix them. Advice like YAGNI and YAGRI are obvious, yet can be easily dismissed unless you have deeply internalized these lessons. These principles eventually are drilled into your psyche from repeat struggles with overengineering or missing logging context.

Even worse, there are entire classes of software patterns with hidden footguns. Steven Sinofsky, who led Office and Windows divisions at Microsoft, lists engineering patterns that sound good but almost never work as intended. The design choices themselves are not flawed, but there is vastly more nuance and complexity than appears on the surface:

I offer this recognizing engineering is also a social science and what works/does not work is context dependent. One life lesson is that every time you say to an engineer (or post on X) that something won’t work it quickly becomes a challenge to prove otherwise. That’s why most of engineering management (and software architecture) is a combination of “rules of thumb” and lessons learned the hard way.

Senior engineers are not just differentiated for their ability to churn out a high volume of code. They can also draw on a deep well of experience building software with a large group of people. This experience is crucial understand how theory actually gets translated into reality, since previous success with the identical tools and architecture may not lead to same outcome in a new environment. Engineering disasters still happen at companies even despite hiring a lot of smart, experienced people to work together. As Mike Tyson once said, “Everybody has a plan until they get punched in the mouth.”

And for those still worried about their competitive advantage against LLMs, look no further than what engineers themselves define as the best among them. Above a certain threshold of technical skill, the attributes which define the most talented engineers are judgement, prioritization, and decision-making. These individuals are able to independently determine what is the highest leverage work. As John Allspaw writes about expert proficiency:

Experts operate from a mature, holistic well-tried understanding, intuitively and without conscious deliberation. This is a function of experience. They do not see problems as one thing and solutions as another, they act.

The best engineers will also carve out time in their day to make risky side bets that sometimes unlock an entirely new areas of strategic investments. Principal and distinguished engineers rise to that level by producing ideas and solutions that no one else can generate.

These observations on the nature of the most talented engineers naturally leads to the following insight: that LLMs, which by definition synthesize and generate output based on their training corpus, cannot create uniquely new technology innovations. AI-assisted code tools do best in languages and systems with high ecosystem stability, where there is a plethora of examples to guide token generation. The current productivity improvements that LLMs promise is also based on the assumption that the industry at large produces a general high quality of software, which is not even necessarily the case based on long-term studies on software project success rates.

In addition, models are by default backwards-looking. We have not yet solved the question of how to update LLMs with cutting edge knowledge on an ongoing basis. This has significant implications for software development, where we are constantly pushing the frontier of paradigms and frameworks. Incorporating brand new engineering trends and programming language design will require new techniques in evolving LLMs.

Adapting to a changing industry

Now that we’ve established that senior experts will be more relevant than ever in AI-assisted software development, how will these new tools affect the training and development of engineers?

We are facing an unprecedented increase in spammy behavior as gen AI enables more crappy resumes and cheating during technical interviews. Tech companies are shrinking headcount year over year. Entry-level roles are increasingly harder to land, with even new grads with prestigious credentials struggling to get jobs in FAANG. The era of dropouts and nontraditional backgrounds is over.

All signs point to the tech industry undergoing the kind of professionalization3 that brings it more in line with finance or consulting: high barrier to entry, massive churn within the lower ranks, and a narrowing pyramid at the top of the hierarchy for managers and senior team members. I certainly hope that the more extreme cases of high turnover and aggressive austerity practiced by tech leadership goes away, but many of the transformations towards a smaller, leaner workforce are likely here to stay.

But it’s not all doom and gloom! One exciting possibility that is unlocked by LLMs is that people will get to spend more time doing creative high-level work and less on the drudgery of software engineering.

Less than a decade ago, many of the best engineers were partially defined by how good they were at manual memory management and hunting down null pointer exceptions. Now most of these problems are handled for us, both by automated systems and better-designed languages that steer engineers into the pit of success, so we can focus on higher-level problems. I see AI-assisted coding as the natural next step in this evolution by simplifying a lot of the boring tasks that are currently needed to make software function.

But because so much of software engineering for so long required proficiency at this kind of bug-fixing, we routinely exclude people in their early careers who are good at high-level systems design but bad at esoteric technical knowledge. Tailscale CEO Avery Pennarun observes how our industry defaults for career progression fails to account for these kinds of individuals:

After helping a few dozen people with their assessments, I noticed a trend. Most developers mapped well onto the ladder, but some didn’t fit, even though they seemed like great engineers to me.

There were two groups of misfits:

  1. People who maxed out as a senior engineer (building things) but didn’t seem to want to, or be able to, make it to staff engineer (translating business problems).
  2. People who were ranked at junior levels, but were better at translating business problems than at fixing bugs.

(…)

People in group #2 weren’t supposed to exist. They were doing some hard jobs - translating business problems into designs - with great expertise, but these accomplishments weren’t interesting to the junior-level promotion committees, who had been trained to look for “exactly one level up” attributes like deep technical knowledge in one or two specific areas, a history of rapid and numerous bug fixes, small independent launches, and so on. Meanwhile, their peers who couldn’t (yet) architect their way out of a paper bag rose more quickly through the early ranks, because they wrote reams of code fast.

In our current way of evaluating engineers where code volume is still heavily weighted, systems design and “glue work” ability is systematically undervalued at certain career stages. Junior engineers are forced to follow this rigid progression, discouraged from develop engineering taste early in their careers, or else risk their next promotions.

But not forever. Thanks to AI-assisted code, folks will have a more even playing field in terms of code output. Therefore, the most highly differentiated folks will be those who have the ability to translate business problems into great designs. Companies will be heavily incentivized to quickly identify and invest in these individuals with senior potential.

Do the work

The only way to develop taste is to do a lot of high-quality work. Explore problem spaces, get feedback from experienced mentors and peers, read and review really good code, and write a lot of it on your own. Avoid skill atrophy from unnecessarily replacing your own reasoning with AI. Develop your own opinions about where and when to use LLMs as part of your workflow. Care a lot about what you create.

So let’s get to work.


1. If there was one, after all, it would be a silver bullet and we would not be debating the merits of software engineering taste.

2. I know this makes me sound like a woo-woo Zen practitioner who thinks that skill can only be gained through suffering and inscrutable aphorisms. While I do in fact like such philosophical explorations, I also remember how frustrating it was early in my career to hear "you'll eventually understand once you get more experience" and not get any concrete explanations. But it's not untrue either.

3. Because the industry has changed so dramatically, take any career advice you read with a grain of salt. Mine included.


This article was last updated on 6/29/2025. v1 is 1,738 words and took 6.5 hours to write and edit.