Strong opinions, held for years, quietly abandoned. This is a list of things I used to believe and don’t anymore.

Compiled languages are safer than interpreted ones

I came up writing Java, and Java taught me that correctness was the compiler’s job. If it built, it was probably right; if it didn’t, the compiler told me where I’d gone wrong. That felt like safety. It took me years to notice it was mostly a crutch, as I learned to lean on the toolchain when I didn’t know the language well enough to reason in the language itself.

What actually replaced the compiler was learning to write real tests. Tests define the system’s behavior, and correctly describing that behavior is hard in any language. But once done, the compiler stops looking like a safety net and starts looking like spellcheck: useful, occasionally smug, no substitute for knowing what you mean.

Nothing makes an interpreted language inherently less safe. The strategies you use to prove correctness are different, that’s all. I watched this play out at Betterment, where we had a lot of FUD about writing financial services products in Ruby. To my knowledge custody and trading still run on Java or Scala. And yet enormous, load-bearing chunks of the investor experience have run reliably on Ruby for years. Nothing about Java made us inherently less likely to ship bugs, and it was a lot less fun to write.

Good, expressive code doesn’t need comments

When I fell in love with Ruby, I fell in love with how much you could say with a name. You can write validate :reservation_must_be_for_today_if_city_is_mealpal_now_only and the code narrates itself. A class is a pipeline of whole business rules you can read out loud, no comment required. For a while, I treated that as a moral position: if your code needs a comment, your code isn’t good enough. I went looking for the most expressive Ruby I could write, banning myself (and my team!) from using comments so the code itself had to carry the meaning.

Overjoyed to be free of Java’s overzealous autogenerated multi-line comments, I had overcorrected. Expressive code can show you what it does and how it does it. It can’t tell you why — why this tradeoff, why we explicitly don’t do the obvious thing, why this innocuous line is load-bearing and will page you at 2am if you touch it. Comments that capture the why, and sometimes the how, are some of the most valuable lines in a codebase. Good documentation is what lets you change one thing without re-reading everything.1

The software is the thing that matters most

I used to think the software was the work. Make it elegant, make it fast, make it correct, and the rest would follow. Then I spent a few years at MealPal, where the software was never the thing that made it work.

The joke I used to make was that the software didn’t matter, because the food was the product. People weren’t paying for an app; they were paying for a $5 lunch that should have cost $15. Get the price right and customers will forgive a staggering amount of user-experience pain — at the right price you could take orders off a spreadsheet and people would still line up. (This is not a hypothetical opinion about spreadsheets.) They were buying lunch, not software.

What makes or breaks a company is almost never the software. It’s the people, the philosophy, the focus, the discipline, a genuine understanding of the problem you’re solving and the nerve to reject everything that isn’t that. The best companies I’ve seen don’t build software and hope a business forms around it. They know exactly what they are, and the software serves that. Software is mostly words, and words are only as good as the thing they’re trying to say.

Managers get in the way, and they don’t want my help

For most of my early career I thought managers were overhead — people whose job was to fit me into an org chart, whose work was at best none of my business. I didn’t want their help and couldn’t imagine they wanted mine.

Then I worked for one who did it differently. I was frustrated, loudly, that we kept not fixing things everyone agreed were broken, and instead of managing the frustration out of me he pointed it at a target. Go fix it, he said. That’s your mandate now. Go make it better. He’s the one who first called me a wolf, and then did the thing a good manager does with a wolf: gave it a direction and got out of the way. The space he gave me turned into real leverage — speed, reliability, the whole team’s day-to-day experience of the work, all visibly better because someone with authority decided my restlessness was an asset instead of a problem.

That’s the shift, and it’s the whole thing: the difference between a manager who exists to fit you into an org and one who exists to help you realize your potential inside it. The second kind isn’t overhead. The second kind is the highest-leverage relationship you have. I believed managers got in the way right up until one cleared the way, and then I spent the back half of my career trying to be that for other people. Most of my README is a list of promises I made to myself in the shape of the manager I wish I’d had sooner.

The best outcome is convincing you I’m right

The most senior engineers I came up under shared a trait: they always seemed to be right, or they made sure to be proven right. I admired it, and I took the wrong lesson from it. I decided the goal of a disagreement was to win — to be the one holding the correct answer at the end. Will Larson, in Staff Engineer, talks about cultivating “the skill of never being wrong,” a sharp and slightly dangerous framing, because it’s easy to hear it as never appear wrong instead of be careful and calibrated enough that you rarely are.

Two things cured me. The first is the law of triviality — the reliable way a group will spend ten minutes nodding along to a million-dollar decision and then two hours arguing about the bike shed. Where there’s a real winner, everyone sees it and moves on; the exhausting fights are almost always over what matters least. The second is hindsight. I’ve fought hard for positions I knew were right, won, and watched the outcome be forgotten within the month — nine times out of ten, the win was worth nothing. And I’ve been on the receiving end, where someone needs to be right so badly there’s no room left for anyone else’s idea. It’s a miserable way to spend a meeting.

What I do now is start one step back. Do we even agree on the problem? An astonishing amount of disagreement about solutions is really disagreement about the problem. Once we agree on what we’re solving, and that now is the time to solve it, the question stops being whose idea wins and becomes how we get the best outcome. “What if we did X instead?” does the same work as “we should do X” without making it mine to defend.

It’s good and right to appear smart

This is the one underneath all the others. For a long time I thought sounding smart was a virtue — that the job was to be the most impressive mind in the room, to have the airtight answer ready before anyone else finished the question.

The cure was noticing who I actually wanted to work with. The people whose meetings I looked forward to were the ones who made everyone around them feel smarter — who showed up curious about how to approach a problem rather than armored with the answer. The opposite kind arrives having pre-solved everything, every edge case sealed off, and presents a design with no door left open for anyone else to walk through — then treats any alternative as an attack to be repelled.

The reason I’m sure about this is that I’ve been the villain of it. MealPal’s web app was AngularJS — Angular 1, a genuinely painful framework — and a mid-level engineer had taken it on herself to port the thing to React on the side. In a room with the whole team, I made an offhand crack that we probably wouldn’t even have a web app in a year because we were going all-in on mobile. I’m sure I sounded strategic, well-informed, and decisive. One flippant sentence, and I’d dismissed genuinely good work she’d been doing in front of the whole team. It’s a mistake I’ve tried my best to learn from.

Here’s what I didn’t appreciate. Passion projects are how incremental progress actually happens — how a codebase buried in debt slowly digs out, how someone goes from quietly proving a strategy works to changing the whole team’s direction. I didn’t only make one engineer feel small; I discouraged the exact mechanism by which good engineers make things better when no one told them to. That’s the real tax on appearing smart: you pay it, but you charge it to everyone around you.

My devotion to a company will be reciprocated

I used to believe in a kind of cosmic justice about work: that if I gave a company everything — nights, weekends, loyalty, the whole grit reflex I’m a little too proud of — it would, eventually, give it back. Do great work quietly and you’ll be taken care of. It’s a comforting belief and it is almost entirely false.

There is no silent meritocracy. No one is watching your contributions as closely as you assume, and “do excellent work and wait to be noticed” is a strategy for being underleveled with great reviews. Employment is a contract — a real one, with two sides who each have to keep getting what they came for. I get paid, I get to learn, I get exposure and range and interesting problems. The company gets sharp work, a better culture and progress against the things it’s trying to build. The exact mix is different for everyone, and that’s fine. What’s not fine is assuming the other side is tracking your account balance.

The trap I kept falling into was believing that performing well in a role was a claim on the next one. It isn’t. Doing a job well proves exactly one thing: that you’re well-suited to that job. If you’re ready for something bigger — more scope, a different challenge, a real change — it’s on you to say so, out loud, to the person who can do something about it. There were stretches where I didn’t, where I waited to be offered what I should have asked for, and I paid for the silence in time I don’t get back. Advocate for yourself. No one is coming to do it for you, and the people worth working for would rather you asked.


Changing your mind is the work. Read these back to back and they practically harmonize; I overvalued the artifact and undervalued the problem, or I overvalued being right and undervalued the people in the room. Correctness over understanding. The code over the company. My idea over the better idea. Sounding smart over making anyone else smarter.

There will be more. I’m sure this list is missing a few I haven’t caught yet. The next version of me is already reading this and shaking his head, adding entries to the README.


  1. I drafted this entry before LLMs were any good, and it’s the one that aged. “Comments that restate the what are useless” needs an asterisk now that the what is also addressed to a machine reading your code at 3am. I still think the why is what matters most. I’m less sure the what is worthless. ↩︎