The old way
Rethink Everything
Almost every best practice I taught was an optimization for the human programmer. The human isn't the one writing the code anymore, so I'm rethinking all of it.
I tweeted this the other day:
A lot of people agreed. A lot of people got mad. Either way, I owe the argument.
Quick context, and I'll only do this once. I co-founded Flatiron School and taught thousands of people to code, mostly Ruby and Rails. For years I stood in front of students and preached: code is written for humans to read. DRY it up. Write your unit tests. Never do the big rewrite. Keep the monolith majestic. And please, for the love of god, stop reaching for microservices.
I believed all of it. I was right, too, for the world we were in.
What I used to preach
Years ago I wrote an essay about why we taught Ruby first. Rereading it now is strange.
I wrote that Ruby was the only language I knew of that was invented for your happiness. That it "values you, the programmer, over the machine." I wrote that programming is an art, like poetry or music, and that the most important thing a student could learn was to "fall deeply and profoundly in love with code."
I meant every word. I still do, mostly.
I also quoted Dijkstra: "The tools we use have a profound (and devious!) influence on our thinking habits." My point was that Ruby's values shape how Rubyists think. Happy programmers play. Free programmers invent. That's why Rubyists gave us Rails and Bundler and GitHub.
Here's what I didn't see coming. Dijkstra was right, and the tool changed.
Who is the programmer now?
Ruby valued the programmer over the machine. So did almost every best practice we have. Each one was an optimization for a human who had to read the code, maintain it in two years, get hired and onboarded, and hold a system in their head while getting tired and forgetting things.
Readability was for humans. DRY was so a human wouldn't forget to update the second copy. The testing pyramid existed because humans hated maintaining slow browser tests. Picking the language your team already knew was about hiring humans. Shipping an Electron app instead of three native ones was about the humans you could afford. Paying Vercel was because a human didn't want to learn nginx.
I'm not the programmer anymore. Not mostly. Agents write the code. Agents read it. Agents maintain it. I plan, I verify, and I decide. My own happiness at the keyboard, the thing Ruby was built around, isn't the constraint.
So the values reshuffle. Maintainability, team familiarity, speed to expertise, one language everywhere: all of that has slid way down the list. Context, isolation, fast feedback loops, and parallel work streams have shot up.
Once I started asking "is this optimized for me, or for the agent?" I couldn't stop. Nearly everything I believed failed the test.
What I've changed my mind about
Each of these gets its own post with a real example and an honest comparison, old way next to new way, because opinions without examples are just tweets.
-
1
Code is written for humans to readStop writing and reading codeYou're never going to maintain it. My job is plans, specs, and verifying behavior. Reading every diff line by line is the new bottleneck, and the bottleneck is me.
-
2
Never rewrite from scratchRewrites might be better than massive refactorsThe old codebase is the perfect cheat sheet for an agent to plan against. Wrap it in e2e tests, have one good planning session, and a working port is often a one shot. "Never rewrite" was advice for a different economy.
-
3
Use the language your team already knowsLanguage strengths over language familiarityI'm a Rubyist shipping Go and Swift. The agent is fluent in everything, so pick the language that's best at the job, not the one your team happens to know.
-
4
Build it once for the web and wrap itGo native everywhereWe used the web as a platform because it was easier for humans. Electron, web views, React Native, one codebase for every screen. Agents write Swift and Kotlin just fine. Stop settling and build the real native app.
-
5
Keep the monolith majesticMicroservices in a monorepoI hated microservices. Agents excel at them. Small services mean small context and no stepping on each other. One monorepo means any agent can still see the whole system when it needs to.
-
6
Pay someone else to run your serversOwn your infrastructureManage your own until you really need managed. Bare metal over cloud. Leave Vercel behind. Coolify on a cheap box plus an agent that knows Linux better than I ever will.
-
7
Don't repeat yourselfDuplication over abstractionNot ActiveRecord. I mean the app level modules, mixins, and dependency injection that force everyone through one shared file. Two agents editing the same concern is a merge conflict waiting to happen. Let things duplicate.
-
8
Types are ceremonyTypes help agentsTypeScript, I don't hate you anymore. The cost of types was paid by the human typing them. Now the compiler is a free, instant feedback loop for the agent.
-
9
Respect the testing pyramidMore e2e tests, fewer unit testsE2E tests were brittle to maintain, and now the agent maintains them. Left alone, agents write piles of unit tests that prove nothing. Test that the user can do the thing.
-
10
Refactor for readabilityOptimize for the agentRefactoring for my readability isn't worth it anymore. I ask the agent to refactor the code so it's easier for it to work with. Explicit over magic. Greppable over clever.
Kill nostalgia
I know how this sounds coming from a Ruby guy. Rails is still home. I build on it every day, and I still think Ruby is the most beautiful language I've ever written.
But most of the pushback I get, and most of the pushback I give myself, isn't technical. It's identity. We spent years getting good at a craft, and admitting the craft moved feels like a betrayal.
In that same essay I told students not to define themselves by their first programming language. Languages are tools. The real skill is learning how to learn. I said it about Java versus Ruby, back when that felt like a big deal.
Turns out the advice was bigger than I knew. Don't define yourself by your first language, or your favorite framework, or the practices you spent a decade teaching. This series is me taking my own advice, a little late.
Some of these I'll be wrong about. I'd rather find out by building than by defending what I already believed.