Showing posts with label Career. Show all posts
Showing posts with label Career. Show all posts

Have Your Claude Call My Claude

A blog post titled AI;DR (AI; Didn’t Read) by Rick Manelius blew up on Hacker News last week. The discussion on HN is amazing, it's like a group therapy session. You can probably guess the premise from the title, but the post is about a problem many of us are having, which is how to respond to people who copy and paste LLM-generated walls of text and expect you, another person, to read it.

I share the author's frustration, and I've been thinking a lot about how to handle it myself lately. If I can tell at a glance that someone copied and pasted Claude's output as something they intend for me to read, it's hard for me to not feel a sudden rush of indignation rising up. 

My policy that I'm trying out is that when I detect a long LLM-generated answer from someone, if it's about a topic that I can't simply ignore, is to fire up my own Claude instance and paste their answer for Claude to summarize for me. There's a pleasant equivalence there that feels right: zero effort met with zero effort.

As Rick mentions in his post, there's an amazing site dontpastetheai.com that feels to me like the bygone-era equivalent of lmgtfy.com. I don't think I quite have the snark in my body to reply to a coworker with AI;DR or a link to a website that mocks what they did, but I do think it's well within bounds to reply to obvious AI slop with your own obvious AI slop.

The productivity benefits of LLMs can't be ignored, but I think we need to remind each other from time to time that we're not just meat pipes connecting two instances of Claude to each other. If that were the case, then why are we here at all?

The Reverse Centaur

I recently watched a couple interviews with Cory Doctorow discussing AI. He explained the concept of the "Reverse Centaur" from the title of his upcoming book.

Here's how he defines that term on his blog:

In automation theory, a “centaur” is a person who is assisted by a machine. You’re a human head being carried around on a tireless robot body. Driving a car makes you a centaur, and so does using autocomplete.

...a reverse centaur is a machine head on a human body, a person who is serving as a squishy meat appendage for an uncaring machine.

...

Obviously, it’s nice to be a centaur, and it’s horrible to be a reverse centaur. There are lots of AI tools that are potentially very centaur-like, but my thesis is that these tools are created and funded for the express purpose of creating reverse-centaurs, which is something none of us want to be.

I think that's such a potent framing, and it matches my experience with GenAI tools like Claude and Copilot. I actually find them pleasant to use when I'm the head of the centaur. There are a lot of tedious little tasks involved in software engineering that I’m happy to outsource to an eager assistant. I maintain my autonomy, intelligence, and dignity in this arrangement.

But I've also encountered advocates in the software industry for the reverse centaur arrangement, where AI agents are autonomously producing all the code, with human engineers essentially grading their work and scolding them. That arrangement I find depressing and alienating. 

In Doctorow's interview with Democracy Now!, he mentions another concept called the "accountability sink", which means the poor human who gets blamed when the AI agents make mistakes that get past the human's red pen.

An often used example of "good AI" is software that can spot hard-to-find tumors on X-rays, even the tumors that a human radiologist missed. Doctorow warns against turning radiologists into accountability sinks:

...if the AI misses a tumor, this will be the human radiologist’s fault, because they are the "human in the loop." It’s their signature on the diagnosis.

The radiologist’s job isn’t really to oversee the AI’s work, it’s to take the blame for the AI’s mistakes.

Over many years of working in the software industry I've seen the pattern of a certain kind of shitty job where the boss wants to hire an accountability sink for a collection of inexpensive offshore developers. A kind of designated responsible party for low quality output.

Imagine if instead of being the accountability sink for contingent workers in a distant timezone, you're now responsible for what the chat bot living in a data center produces. Yikes!

I'll try to hold out being the top end of the centaur for as long as I can.

Dysfunctional In a Chill Way

I've had many jobs over 20+ years in the software industry, and every one of them has been dysfunctional to some degree. Of course, that's normal. No person is without flaws, and the same is true of jobs. Even my best jobs had dysfunction.

There are many ways for a job to be dysfunctional...

  • Micromanagement
  • Unreasonable deadlines
  • Poor communication
  • Etc.

But something I've learned over time is that jobs can be dysfunctional in a miserable way or a chill way.

A company doesn't need to be as dysfunctional as Kruger Industrial Smoothing, but a little dysfunction can be a positive thing for a job...if it's the right kind of dysfunction.

Some of the dysfunctions of a job (e.g., micromanagement) can make one's life stressful. But not always. The chill dysfunctional flip side of micromanagement, little-to-no supervision, can be awesome depending on your situation:

  • Time to work on your own priorities
  • Build according to your own standard of quality
  • Decide what you think is important
  • Relaxed pace

Just like every person, every job has dysfunction. If they're flawed in a chill way, you're doing pretty well.

A Human Writes This Blog

I had to turn off comments on this blog several years ago because most of the comments were being left by bots, and it felt like an uphill battle trying to manually remove them over hundreds of blog posts. I'm really bummed about that, because (back when people still read blogs) I would get a steady trickle of comments from real people who wanted to say something about my posts. It feels more like a void nowadays writing here, but I have just as much to say as I always did, so I keep writing. 

And it saddens me a little bit that blogging is not as common now as it used to be when I started this blog in the late 2000s. It just got too easy to write something on the internet in other ways (Twitter, Facebook, etc.). There has never been more writing on the internet than now, and writing has never been as disposable as it is now.

I've been thinking about putting a note in the sidebar of this blog that says something like, "This blog is never written by AI." Because my personal opinion about GenAI, is that, while there are legitimate uses for it, I believe it's demeaning to expect a human being to seriously read content that an AI has generated. Get another bot to read that shit.

I won't let this blog become part of the dead internet, where bots write for other bots. Hey bots, you're welcome to read this blog, but a human will continue writing it.

Would it be way easier if I just prompted ChatGPT with a blog post idea, watched it spit out text, and then copied and pasted it as a blog post. Hell yes. Would I ever do that? Hell no. Because this blog is about my personal experiences in the software industry, and if I let a bot write it, there's no point to continuing. And I could never feel good about asking another human being to read it.

Sorry readers, you're stuck with me. Enjoy all the rambling, disconnected thoughts, and awkward transitions that only a human can produce. ✌️

Who Wrote This Crap?

I remember many years ago interviewing at a software consultancy where one of the consultants in the meeting was talking about a project they had going on. He was marveling at how fast the team of junior developers on the project was "cranking...out...code." I'll never forget the way he said it, and the look of awe on his face as he slowly shook his head back and forth.

This of course happened well before the advent of LLM assistants that can produce code at an astonishing speed. I wonder if that consultant's head would have literally exploded if I had showed him GitHub Copilot or Claude Code at the time.

Hell, I remember being gobsmacked as a junior engineer myself by CodeSmith, which was an early code generator product for C#. It could automatically spit out huge amounts of boilerplate code that an engineer would typically write by hand. I heard about it from a coworker at my very first job in the software industry, and I remember how unnerved I felt, thinking about a program that can automatically write code (isn't that why I'm here?).

The next code generator that came into my life was Ruby on Rails, which I first tried a couple years later. By that time, I had experienced what it was like to write the most tedious code in most applications, which was code wiring up database tables to web forms, and all the plumbing to pipe the data through each layer. It was a mind-numbing yet essential task, and almost every application needed it. Rails came at me like a breath of fresh air. At this point, I was like, oh yeah, this rules. I hated writing all that data access CRUD, and Rails made it largely disappear. Code generation clicked for me.

In the .NET world, where I've mostly worked for my career, we had a series of object-relational mappers that could generate classes off of your database schema, and resulted in engineers having to write way less code that shuttles data from a web application to a database and back. To name a few, we had NHibernate, SubSonic, LINQ to SQL, and then Entity Framework. I welcomed these tools with open arms, but I do remember there being pushback at the time from more senior people at my companies who were accustomed to writing this kind of code by hand and didn't trust what the tools were doing under the covers.

The common denominator in my early experience with code generation was eliminating the manual work of writing a lot of extremely predictable, relatively dumb, utterly tedious code that was also essential. And this usually took the form of data access code that moved data between layers of a web application, from the front-end to the database, where you had SQL tables that corresponded to C# classes, that corresponded to web forms. Classic CRUD. It's usually highly predictable stuff, and ripe for code generation. Yes, there were times where the tooling would break down, and an engineer would have to get under the covers and debug an edge case that the tool couldn't handle automatically, but, in my experience this was relatively rare.

What I'm seeing in the industry now with AI coding assistants like Copilot feels fundamentally different to me. I've witnessed fellow engineers in recent years generating code more akin to "business logic". This is the kind of code that's specific to the domain of the company and not transferable from codebase-to-codebase. I've also seen fellow engineers letting AI write the code for areas of the codebase that they don't understand well. For example, they may not know how to do a certain thing with React, so they describe what they're trying to do to Copilot, which then generates code that the engineer accepts without understanding, as long as it seems to work.

What's fundamentally different to me about the scenarios I just described and the code generation scenarios of yore, was that the pre-AI code generators were deterministic, and they were applied only to non-domain-specific logic.

What happens when a codebase is peppered with business logic that no human working at the company wrote, and hence cannot definitively explain? I have already seen first-hand times when bugs in important processes were not discovered until the AI-generated code had been in production for weeks. The engineer committing the code did not know that what Copilot generated did not match the logic they intended. Maybe I can write another whole blog post about this topic, but I'll say briefly here that in many scenarios, increasing the speed at which the code is produced is less important than a human understanding what it does at a granular level. In other words, speed of coding is not a bottleneck.

Another consideration is that AI code generators like Copilot are non-deterministic. As in, you can run them multiple times with the same input and they will produce different results. Going back to my examples before of pre-AI tools, the code generation features of CodeSmith and Entity Framework are deterministic. You can run them multiple times with the same input, and they will give you the same output every time. This is because a human software engineer wrote the code behind those tools, and the rules are directly and unambiguously traceable back to the lines of code a human wrote while designing them.

I can't help but wonder if, as an industry, we're hurtling toward a future where many production codebases will be littered with code that no human at the company understands or could definitively explain, not years later, but even weeks later. My personal relationship to AI-generated code as a working software engineer is that I will not commit code that I cannot explain. And when doing code reviews, I cannot accept the explanation that code included in the pull request was AI-generated and hence the submitter does not know what it does.

I also have to wonder if the AI slop era we're all in at the moment says something about the illusory nature of quality. Maybe quality was just an unintended side effect of manual coding that business leaders never really cared much about in the first place. In my multi-decade career in the software industry, the emergence of Copilot represents the first time I've ever experienced non-technical people mandating the use of a particular tool to software engineers. It seems that the idea of faster code production was so mouthwatering that quality flew out the window within seconds.

Who wrote this crap? Maybe the answer never mattered.


User Advocate vs. Front-End Engineer

I really enjoy doing UI work: being close to the user's mind, thinking deeply about interaction design, and how small changes can massively improve someone's day. But in order to market oneself as a “Front-End Engineer” in the current landscape requires dogged attention to fashion trends, and I'm on Team Evergreen, baby.

Early in my career in web development, I loved reading Jakob Nielsen and Steve Krug, but at some point I had to accept that maintaining intimate awareness of the specifics of JavaScript Framework Du Jour was not sustainable for me. Call me "full-stack", that's fine.

Front-end is the most ripe for résumé-driven engineering. Default skepticism is always warranted for new technologies, but in front-end, it is truly a necessity to avoid lighting your company's money on fire.

I found a rather cathartic post by Marco Rogers on Hacker News recently called The Frontend Treadmill. I fully agree with Marco's take: 

If you are building a product that you hope has longevity, your frontend framework is the least interesting technical decision for you to make. And all of the time you spend arguing about it is wasted energy.

I would not necessarily describe myself as a React fan, but I am very happy that it feels like we finally landed on a framework that can survive for several years, with wide adoption by startups and enterprises alike. Let's go, Lindy effect. Maybe React can be the framework equivalent of what jQuery did as a library. 

Above All Else, Sustainability

From the principles of the Agile Manifesto:

Agile processes promote sustainable development. The sponsors, developers, and users should be able to maintain a constant pace indefinitely.

Extreme measures are always doomed beyond a limited time horizon. Whether we're talking about diets or software development practices, without sustainability you have nothing.

Initiatives to increase productivity, improve quality, lower costs, or any other "good thing" simply don't matter if they're not sustainable.

A common topic in Agile circles is "sustainable pace", which usually focuses on the futility of working overtime, typically over 40 hours a week. I would argue that sustainable pace is about more than just the number of hours clocked in a work day or work week. 

Is the work emotionally sustainable? Do people hate working here? Do people end the work week feeling a sense of accomplishment? Do people feel like their leaders have reasonable expectations? Are they constantly battling reality?

Sometimes the degree to which an enforcer must continuously apply pressure to get people to follow a process indicates how sustainable the process is. Powering through is not a sign of discipline, it’s a sign of delusion.

Ignorance of reality is unsustainable. Coercion is unsustainable. Surveillance is unsustainable.

Can I and the people around me keep this up forever? If not, it's time to pause and reflect. Above all else, sustainability.

The Financial Architecture of Software

Conway's Law is foundational to software engineering. It says:

Organizations which design systems...are constrained to produce designs which are copies of the communication structures of these organizations.

If you've ever had any job in the software industry, you've almost certainly seen this play out in the architecture of your codebase. Group A works on Thing X and Group B works on Thing Y, so Thing X is in one [project, repository, web service] and Thing Y is in another [project, repository, web service]. You can read the organizational structure in the structure of the technology. It helps to make sense of why things are the way they are. The silos of communication are reflected in the solutions.

But I recently came across this interview on InfoQ with Ian Miell, who I've mentioned on this blog before. He has interesting things to say about the sociology of software development, and in this interview he talks about a book he's writing about the financial architecture of software:

The material aspects of the world ultimately determine the software we build and specifically the decisions we make at a grand scale about the software that we build. 

I remember being frustrated and confused as a junior engineer, not understanding why certain things are prioritized in a company and others aren't. Obvious best practices from the industry at large don't get traction in certain places, what seem like universal good things like "quality" don't seem to matter, or why values spoken about at the company level seem unevenly distributed and applied.

Ian explains...

When I have a code base, I want to make sure all the tabs are correctly aligned before I do anything else that might take time, or I wanted to make sure the naming paths are consistent. But you get larger scale problems where engineers say, "No, we have to fix this now because it's a huge thing". And you say, "Well, I get it, but that's going to take us a month and in that month people are going to be looking at me as the leader of this team and saying, 'What have you delivered?' And I can try and explain to them what I've done, but it's not going to apply".

Hard work is not always rewarded. It depends on who sees the work, what their individual priorities are, and how much money they control. My advice to my younger self would be to pay close attention to what your specific boss thinks is important, and show yourself working on those things. The next level is understanding what your boss's boss thinks is important and by what criteria they're judging your boss; then you'll really understand what kind of work is rewarded.

As Ian describes...

Who owns the budget is a fascinating question. ...I start the book with a story about a very successful engineer, I call her Jan. She becomes a leader of a small group of engineers and she builds a platform in her spare time with those engineers, like a Kubernetes platform. And she does it within a central IT function and she builds it and she takes it, she shows it to her manager and the manager's like, "Well, this doesn't help me hit my goals for the year. This doesn't help me get a promotion, this doesn't help me get a pay rise". And she's nonplussed like. "I'm trying to deliver faster, cheaper, better. That's what the company is, we're supposed to be agile. I'm trying to help the whole business".

And it might sound naive, but a lot of people think this way. I certainly did. Where you're thinking, well, I'm doing what's good for the company, but the system is not structured in that way. It's not designed to be run that way because people are complicated and their interactions are complicated, so you silo things and you have different budgets and so on, and the end result is that you are slaving away at the central IT function, trying to make the business better as a whole, but it's not accounted for.

Understanding where the money comes from sheds light on the technology decisions, where quality matters a lot and where it's almost an afterthought, and why different teams are more scrutinized than others. In the end, follow the money.


There's a Fine Line Between Increasing Productivity and De-skilling

In the software engineering profession, there's a concept called "resumeware". It's software that was made with the engineers involved in the design specifically making choices about technology stacks in order to have marketable experience to put on their resume in order to improve their future job prospects, regardless of whether they're a reasonable choice for the system at hand. You can kind of tell when you're looking at resumeware because it looks like the architects threw in every fashionable programming language, library, framework, and architectural pattern into an incoherent hodgepodge.

You could say this is a cynical take on the employer-employee relationship, and perhaps, taking advantage of one's aura of expertise. And that could be true. There's a balance to be had in any job between giving your employer a good return on your salary and the desire of an at-will employee to increase their transferable skills. I think every employer knows this--in fact the good ones use this as a recruitment advantage.

The flip side of this coin is de-skilling, the centuries old drive by employers to reduce the skill needed to produce a product, as part of the endless push to reduce labor costs. Today generative AI is hailed as the ultimate de-skilling force. Employees across all kinds of industries (including software engineering) are feeling the heat from their bosses to increase their use of GenAI in their everyday work. I think that history shows plainly that the march of capital toward greater efficiency is unstoppable. Smashing looms is not a sustainable defense.

When I look into my crystal ball, I see a "Great Sort" coming to the software industry. Just as the middle class of well...life...continues to shrink, I can see the same thing coming to the skilled profession of the software engineer. The question is: Do you want to be sorted to the bottom or the top? Do you want your work to become more skilled or less skilled?

I really do feel for junior software engineers coming out of college in 2025, the time of your career when you're the least skilled, and trying to find a great job while you're trying to get your foot in the door in the age of GenAI. The least skilled are the most vulnerable.

For those among us fortunate enough to be past our junior years to the "experienced" stage of our careers already, what does the future hold? My personal perspective is that I, as I always have, fully embrace the idea of reducing the tedious aspects of my daily work. Programming can be bloody annoying a lot of the time. Assembly language is not a skill I want to have because C# exists, and it's way less annoying to use. There is no way in hell that I'm going to write code in Notepad with a command-line compiler (like I did in college) when IntelliSense and Visual Studio exist. Remember trying to track down the cause of weird error messages in your program before Stack Overflow existed? I do! And it fucking sucked.

I will never take the stance that I want to stay inefficient. I do not want to do my work in a more tedious, annoying way so that I can bill more hours to do the work. But at the same time, I will not de-skill myself for anyone. My general feeling about the big, scary "AI" future of software engineering is that I'm happy to use any tool that makes my job less annoying. My real skill is in producing great software. I am not attached to the tools that I use to do it today or tomorrow. If a statistical word predictor trained on the entirety of Stack Overflow, and fully integrated into my code editor, saves me having to read endless Stack Overflow posts in dozens of tabs in my web browser to produce the same end result, then bring it on.

My personal rubric for productivity-enhancing tools is this: Is my work getting less annoying or am I getting dumber? I refuse to get dumber. Getting dumber is the feeling of sorting to the bottom. If a statistical word predictor can do my job better than me, then I need to learn to do something harder. I will not try to compete at the level of the tool. I will be sorted up, not down.

Just as any employer has the natural right to decrease their cost to make a product, I retain the right to increase my transferable skills. There's a thin line between increasing productivity and de-skilling. I'm all for increasing productivity, but I will not de-skill myself. 

Calibrating Your Care

I've been a subscriber to the r/ExperiencedDevs subreddit for a few months, and I've noticed a common pattern.

Someone will post a question to the group desperately seeking advice about some stressful situation that they are clearly very worked up about at their job. The author's specific concern or complaint could be just about anything, but the general feeling is that from their point of view everything seems to be on fire around them and none of their peers or managers are doing anything about it.

Being around social media for many years trains one to expect posts like these to be opportunities for commenters to rage about the injustice on display and to pile on with their own indignation about incompetent managers and clueless coworkers.

Instead, many of the highest voted comments to the post will be something to the effect of:

With all due respect, I think you care too much about this.

Or...

You seem to be taking this personally, and there's no need to do that.

I was definitely surprised at first by responses like this being highly upvoted, but I just kept seeing them from different people on different posts, with very little pushback from other commenters.

Early in my career, I took things at work very personally. I saw it as a badge of honor to care more than the people around you. I should be mad if things are not being done the right way.

The unpalatable truth, in many cases, is that this thing that seems of grave importance to you...actually doesn't matter as much as you think it does. And the clueless coworkers and managers around you actually understand something important that you don't. In fact, you might be the clueless one.

It's easy to get caught in the spotlight effect, where you assume your thoughts and feelings about a situation are the right ones. And it's easy to believe that your view of what's important is shared by everyone.

If your ground level belief is that everything is on fire and no one cares, you’re probably right. But you have to keep in mind that no one else sees the world through your eyes. You may be reading the room inaccurately. Your boss may have more context around the project than your daily experience.

One could take the advice that "You care too much" as being told "You should be dead inside." I would say, just be prepared to lower the stakes in your mind. Be humble about your own role in the world of people around you. Get some mental distance from the situation and try to read the room.

Everybody gets to decide what they care about. Calibrate your care.

Don't Let an LLM Write Your Unit Tests

Writing unit tests is one of those tasks that software engineers often see as tedious. In fact, I've heard from fellow engineers that unit test generation is one of their favorite uses of LLMs. Let the AI write them! I've always been deeply uncomfortable with this use of LLMs, even though I'm all for reducing the tedious aspects of work in general.

Unit tests are not boilerplate code. If you've read a lot of bad unit tests, then you may get that impression, though. If your only goal in writing unit tests is Coverage number goes up!” then by all means let an LLM write your unit tests.

But I would argue that writing great unit tests means thinking carefully about what is valuable about the system under test. An LLM is great at generating reams of code in an instant, but it will never know anything about the value of the product your codebase represents.

If our goal instead is “Let’s ensure that our product is retaining its value as we add more code to our codebase.” then a human who understands the value of the product should write the tests.

Unit tests have yet another critical function, which is to provide runnable documentation about the system for other engineers to read. Want to know how some part of the codebase is supposed to work? Go read the unit tests; they represent the valuable features of the software that an engineer wanted to point out.

Code is written once, but read many times. And test coverage is just a number. If you want tests that matter, write them yourself.

Copilot Is Outsourcing 2.0

Decision-makers can remain irrational longer than you can remain solvent. (Or, in this context, remain employed.)

- Will Larson, "Career Advice in 2025"

"AI" coding tools like Copilot went from a mere curiosity to full-blown silver bullet territory in a few short years. I'm all for reducing the accidental complexity Fred Brooks wrote about in his classic essay on software engineering, but what’s driving me a little bit crazy lately is talk amongst people (mostly non-engineers) around the industry that Copilot and the like are magical productivity machines.

I'm not the only seasoned engineer to notice that this present moment feels eerily similar to the outsourcing craze of the 2000s. The dream of every non-technical executive who had a bunch of software engineers on their payroll was to lay them off and replace them with people in faraway countries with a lower standard of living who they could pay less to do the same job. Well...it didn't exactly work out that way. It turns out that software engineers are not, in fact, fungible code-typing machines. Outsourcing jobs to cheaper parts of the world is very much still a thing, but it took several years of reality colliding with the dream to bring expectations down to a reasonable level.

In 2025, the executive's dream is back, and bigger than ever. What's better than paying humans in other parts of the planet less to do the same job? We can get AI™ to do the job for even less!

The outsized hype around AI coding tools is premised on the idea that software engineers are primarily code-writers. If we could get machines to type the code, then we can save a ton of money, right? The reality in my experience is that typing code faster is not a bottleneck for any software engineer that you would want working on your product. Writing code is a small percentage of what a software engineer actually does.

I remember a friend of mine from college asking me many years ago, when learning that I was studying Computer Science, if I was worried about destroying my hands from typing so much. He apparently imagined that the career I was training for was similar to a court stenographer. In the software industry, we used to refer to engineers who produced huge volumes of repetitive code quickly as "code monkeys". This matches the outside perception of someone furiously hacking away at a keyboard, with speed of keystrokes making the overall impression.

The thing is, a “code monkey” is replaceable by AI. If there's anything we've learned over the last 200 years or so, it's that machines can do repetitive, mindless tasks faster and more cheaply than humans. If the work of a software engineer really looked like: 1. Do a Google search. 2. Copy and paste code from your web browser into your code editor. 3. Hit a button to commit to your team's code repository; then heck yeah, a machine can do those things way faster than a human.

I don't fear being replaced by an AI that can copy and paste code from the internet faster than I can. I do worry about non-technical executives either firing me or not hiring me based on marketing, or a belief that this is what software engineers primarily do to create software that is valuable to an actual business.

Just like the executive's dream of outsourcing faded to a modest incremental reduction in the cost of developing software, I believe that so to will the dream of the AI engineer. I don't need to ask Fred Brooks what he would have thought (RIP).

Software Engineer Career Levels at Companies You've Heard Of

I found a site called Progression.fyi that curates a list of "career frameworks," or in other words, the level-progression system of titles that a bunch of tech companies use for their software engineers. It's pretty interesting to peruse.

Several of these companies define what the often nebulous title of Staff Engineer means to them, which I find particularly compelling.

Here are a few companies you've probably heard of, with links to their pages where they define their career progressions for software engineers:


Are You a Stable or Volatile?

I've written before on this blog about the different personality traits of software engineers, and how different traits balance each other on a team.

Some of the spectra I came up with were:

  • Dreamers ↔ Pragmatists
  • Big Picture ↔ Detail-Oriented
  • Move Fast & Break Things ↔ Slow & Methodical
  • Optimists ↔ Pessimists
  • Answerers ↔ Questioners
Recently I read a comment on Hacker News (which I can't find now) that mentioned a blog post from 2012 on Rands In Repose, a blog I've been familiar with for years, but somehow this post had escaped me.

The author, Michael Lopp, introduces the Stables and Volatiles divide, which feels to me like a meta-category that encompasses the ones I listed above.


You can probably guess just from the names, but Stables tend to like having a well-defined plan, are more risk-sensitive, predictable, and reliable. Volatiles are disruptive, like to blaze their own trail, dislike process, and have a strong bias for shipping something (even if it's ugly and unstable).

Lopp says:
Stables will feel like they’re endlessly babysitting and cleaning up Volatiles’ messes, while Volatiles will feel like the Stables’ lack of creativity and risk acceptance is holding back the company and innovation as a whole. Their perspectives, while divergent, are essential to a healthy business.

I believe a healthy company that wants to continue to grow and invent needs to equally invest in both their Stables and their Volatiles.
I think the Stable / Volatile concept feels very true to my experience, and it's one I'll keep with me. Assuming that everyone on a team is equally intelligent, competent, and well-intentioned, you need people of both the Stable and Volatile persuasions. Even though they annoy each other, a project staffed by only one or the other type is doomed.

Legacy Systems Age in Reverse

I feel like every job I've ever had in software there has been some old legacy system hanging around that everyone denigrated and perennially spoke about replacing with a newer, shinier system. That replacement was always coming any day now. By the time I'd moved on to a new job, that legacy system was still running, quietly doing some important function for the business, having somehow survived the demise everyone predicted.

The first release of jQuery was in 2006. Within a few years--and every year after--web developers would talk continuously about how outmoded jQuery was, and that no self-respecting developer would still be using it when so many newer, better JavaScript libraries had come along to replace it. Well, guess what. In 2024 (18 years later), jQuery is still in active development, and according to the official jQuery blog, 90% of all websites use jQuery currently. As someone who's been working in the web development space since roughly the dawn of jQuery, I can say that it is still extremely rare that I see a codebase that doesn't use jQuery somewhere, whether as a direct dependency, a transitive dependency, or as part of some 3rd-party tool integrated into the product. jQuery will outlast the human species.

Software systems exhibit the Lindy effect:

The Lindy effect (also known as Lindy's Law) is a theorized phenomenon by which the future life expectancy of some non-perishable things, like a technology or an idea, is proportional to their current age. Thus, the Lindy effect proposes the longer a period something has survived to exist or be used in the present, the longer its remaining life expectancy. Longevity implies a resistance to change, obsolescence, or competition, and greater odds of continued existence into the future. Where the Lindy effect applies, mortality rate decreases with time.

They actually age in reverse. Every year they exist doubles their additional life expectancy. That old system that everyone thinks will be replaced any day now is gaining strength before your eyes, becoming every day less likely to be replaced.

New technologies are the least likely to survive another day, another year. Just as a business that's existed for 100 years is more likely to survive to its 101st year than a 2-year-old business is likely to see its 3rd year.

The implications of the Lindy effect to any of us working in "technology" are so widespread that it's hard to overstate. We're in an industry obsessed with the new, but the new things are constantly passing away as the old geezers are running laps around them. Any new programming language you're excited about right now will be dead long before C is. VS Code will kick the bucket before Vim. Be kind to those elderly technologies around you, because they'll be here long after you're gone.

Continuity of Leadership

There's a Kafkaesque situation that develops in companies that cannot retain senior employees. A team feels a sense of urgency about shipping software, but no one can tell them what to build.

Engineers are responsible for making the products that sustain the company, but there's no one around who can say what the products should do exactly.

It's like a movie where the protagonist wakes up every morning with no knowledge of what happened the day before, and tries to piece together his identity from artifacts scattered about.

Big organizational initiatives fail repeatedly because there's no one around from the beginning to the end of the initiative. People working on the initiative find that they can't even remember why the initiative was necessary. The leader who championed the initiative isn't around to take credit for its completion, so there's no one working on the initiative at any given time who cares about its completion.

Cross-team relationships barely exist because whoever is leading one team at the moment doesn't know the leaders of the other teams and has no history with them.

Leaders are continually "backfilling" for other leaders that left, being asked questions that they can't answer.

Morale stays at a low simmer. People show up to work each Monday morning knowing they won’t be productive. Another week where they won’t know if they did good work or not, because no one can define the goal.

An organization without continuity of leadership is an organization with amnesia.

Daring to Care

The most effective technical leader I ever worked with had a track record for coming onto a project and whipping it into shape. His ideas were not groundbreaking. He was not a genius engineer. He was a smart guy, but not necessarily the smartest guy in the room. He wasn't an expert politician, or a charmer. His superpower was that he simply cared more than anyone else around him about the project's success, and he would not back down when implementing improvements. When he noticed an area for improvement, he just did whatever it took to fix it. He would calmly but with absolute persistence run through his argument with whoever he needed to convince that it was the right thing to do. It didn't matter how many people he had to convince, how high up they were, how difficult it was to convince them. He just wouldn't stop if he knew he was right. No improvement was too small or too big. I remember him saying to me once that he didn't understand why people around him would acknowledge obvious problems, but not fix them themselves. What I didn't say, but was thinking silently, was "because no one else here cares as much as you do."

There's risk that comes with caring about something. If I take the initiative to fix the slow build process, then I'm now responsible for it. If I break something, everyone's going to look at me. I might have to talk to the Infrastructure team. Jeez, those guys take so long to get back to you. I'll have to open tickets. I might have to bother people I don't know well to make my task their priority. The build process works now, right? Yeah, it takes longer than it probably needs to, but it works. Do I really care enough to take all this on?

The individuals who rise to the top aren't always the smartest, the most creative, the most charming. They just give a damn. They care more than the people around them. When someone truly cares, they will find no shortage of problems to solve around them. They will find solutions. They will push through objections. They will argue with people. They will take on responsibility for things they don't strictly need to, things no one asked them to take responsibility for.

The open question is: How do you get someone to care? Why do some people care so much more about a project than those around them? Those people are worth their weight in gold.

Escaping the Bikeshed

I wrote in 2017 a post called Don't Trap Your Clients in the Bikeshed. That post was about avoiding the trap of seeking feedback on trivial decisions from clients before they're necessary.

Sometimes in software development a group of stakeholders will become very suddenly interested in a particular aspect of the software, and intense debate will ensue with a flurry of changes discussed in an area that everyone has an opinion about. In these occasions, as an engineer, your clients have put you in the bikeshed.

What do you do as an engineer when you find yourself in the bikeshed?

Slow Down

The pressure to immediately address every opinion can be daunting. Try not to get caught up in the whirlwind. Let the group debate while you maintain a healthy distance.

Pause for Documentation

Gently remind people that in order to get features into software, they need to write down clearly what they want. They have a responsibility to be clear about what they're asking for. That's the bargain.

Invoke the Process

QAs need to know what to test. A larger audience needs to know what changes are making it into the software. Customers need to know what's on the horizon. Releases need to be organized. Changes in one part of the codebase impact other areas.

Your engineering team has an established process for making and releasing your software. In the fervor to change the bikeshed, interested parties get excited to see their opinions realized. How long does it take to paint the thing blue? It's clearly not blue right now, and I want it to be blue.

Remind people why the process exists, and the drawbacks of making changes to a software system that don't follow the same process as other changes.

Expose the Bones

Sometimes it's really an issue of transparency. Non-engineers get frustrated that they don't understand why a feature is behaving the way it is. It can help to "expose the bones" as it were. Make a report that anyone can see that shows key metrics (how many requests, how long is it taking, who's using it, etc.). It can help to surface the internals of a feature. Make a page that shows diagnostic information about the input to a feature, how the feature calculated a result, and what the "raw" result is.

Remove Engineering From the Loop

Ultimately the goal is to remove engineering from the debate. If there's an intense debate about the color of the bikeshed, engineering can build a configuration option into the software where non-engineers can change the color at will. Try to distill the points of contention down to self-service features that don't require engineers to make code changes to the system.

Tell Us Why We’re Doing This

I’m constantly shocked that business people don’t make much of an effort to communicate to engineers the impact of their work. It’s par for the course that the engineers don’t know how many users their product has, how many clients they have, how much revenue the product makes, etc. It’s so common in fact that I wonder sometimes if it’s intentional.

There is an Agile concept known as the information radiator. Some companies will put dedicated big screen TVs throughout their offices that show key metrics at a glance. If you have a remote-first culture, a television isn't going to do much good, but a web-based dashboard placed somewhere the whole team goes every day (like your issue tracker) is a great substitute. 

These ideas are more about passive awareness, but I think the next step up is active discussion. If you're doing some kind of regular all-hands meetings, like a retrospective, that's a perfect time to pull up that dashboard as a team and discuss it together.

How do we know we did a good job over the last sprint? Yeah, we marked all of our tickets as "Done", but so what? How do we know that our customers are happy with our work? Company leaders always want to know how to get their employees more "engaged" in their work. Show your team how their day-to-day tasks impact real end users. Working a backlog of items sprint after sprint is so far removed from the impact of the work. Why are we doing these things?

How many users did we add over the last two weeks? How many new customers came on board? How many usages of [NEW FEATURE X] did we have? 

I feel like I'll be banging this drum for the rest of my career: Engineers are not robots. We want to know the high level goals of our work and how our work impacts real people.

Please, tell us why we're doing this.

Slow Is a Superpower

Every company needs people who can work quickly. Stuff happens. Production goes down. We found a showstopper bug right before a big release. So-and-so called in sick--can you finish their thing that was due today?

Some engineers distinguish themselves by how much chaos you can throw at them. The plate-spinners. The late night heroes. Someone has to save the day. 

But it's also possible to distinguish oneself--and build a reputation--as a slow and methodical engineer. Someone needs to take really deep, nasty problems, and figure them out once and for all.

Someone needs to do the work where the attention to detail required is so tedious and annoying to mere mortals, that only a select few are steadfast enough to see it through to completion.

After five different engineers have spent a couple hours each on that bug, and only emerging with theories about what might be wrong, someone needs to spend a week going all the way to the bottom of the rabbit hole, and emerging with the rabbit in hand.

After generations of engineers have struggled to set up Project X locally on their machines, relying on hearsay and ancient scrolls to get to barely functional, and then moving on and never thinking about it again, we need a hero who goes through the process from scratch, writes down every damn thing that goes wrong, every caveat, every blind alley, records the verbal legends, takes screenshots marked up with the important bits circled, and meticulously documents in a format so easy-to-understand and beautiful, that the next generation of engineers will never again waste another moment setting up Product X in a breezy afternoon with all of their questions anticipated and answered before they even have a chance to ask them.

Who will think through the edge cases, draw the diagrams, note the long-term implications, ask the hard questions (and answer them), write the comments, edit for clarity, and study every changed line in a 57-file merge request?

Slow is a superpower. Not everyone can do it.