Sanely handling PR reviews with a rotation 8/18/25

By Chris Johnson

Pull request reviews. The term either fills you with something approaching joy, or, more likely, dread. In my experience, PR reviews are one of the best ways to ensure code quality, catch bugs, help engineers learn about the codebase. But they have to be handled with a bit of intentionality.

If you’ve ever worked on a growing engineering team, you might recognize this story. PR reviews start off fine, but as the codebase grows, suddenly one or two people are buried under a mountain of reviews while everyone else is waiting for days to get their code reviewed. Reviewers are stressed, PRs get stale, and no one is happy.

I humbly suggest a simple rotation that I’ve employed for nearly three years.

Basics of the rotation

  • Each week, one engineer is the primary reviewer, another is the backup.
  • PR authors assign their code to be reviewed by those two.
  • If you happen to open a PR the same week you’re primary, the backup covers your PR.
  • Every Monday morning, the baton passes to the next pair, and the change is announced to the team. 1
  • The schedule is kept in a public document 2 and assignments can be traded to account for vacations, illnesses, etc.

    One or two approvals

Small changes? One review is fine. Bigger, riskier ones? Grab two. The idea is proportionality We’re not dogmatic about it, but the idea is to get more eyes on changes that could have big negative consequences.

If one of the designated reviewers is unavailable, it’s the authors responsibility to grab another teammate for the second review. The process should serve the team, not the other way around.

What to review

What to review deserves it’s own essay, but briefly, these are things I ask my team to review:

  • Functionality: Use test environments to test the basic functionality.
  • Code Quality: Check for clean, readable, and maintainable code. 3
  • Variable and Method Naming: Make sure variable and method names are clear.
  • Performance: Look for potential performance catastrophes. (That nested loop over API calls. The query that’s going to inadvertently scan the entire database.)
  • Security: Identify any security vulnerabilities or potential risks.
  • Testing: Ensure appropriate unit or integration tests are included. The goal isn’t 100% coverage, but critical paths should be tested so we can make future updates with confidence.
  • Documentation: Check that any tricky code is well-commented. If you had to think twice to understand a bit of code, future developers will too.

What shouldn’t you review? Style. If something works and is logically written, don’t block a PR from being merged just because it isn’t exactly like you would have written it. 4

Lessons learned

It’s not all wine and roses, some weeks are heavier on reviews than others. Reviewers might have a tough time getting to their scheduled reviews quickly if the rest of their workload is heavy. But I still think this simple system has had a positive effect on the team. PR authors know exactly who to reach out to for reviews, reviewers don’t get overwhelmed, and knowledge about the codebase grows naturally on the team.

We’re still tuning the rotation, but it’s the first system that’s made PR reviews feel less like a chore and more like a shared responsibility.

  1. I went overboard and wrote a bot that automatically posts the rotation change each Monday. 

  2. I used AI to generate the rotation about 6 months out. AI can also help slot in new teammates as your team grows and changes. 

  3. See my post on programming principles for more. 

  4. If there are style tweaks I want to suggest, I’ll put them in my review, but I’ll grant the approval. Then it’s up to the PR author if they want to adopt my suggestions or not. 

Human-First Programming Principles 8/11/25

By Chris Johnson

After years of writing code, reviewing pull requests, debugging tricky production issues, I’ve developed a few opinions on how to write maintainable software. I’m not going to claim that any of these ideas are particularly revolutionary, but I wanted a document that outlines the principles I use for my records and as a resource for those who work for and with me on projects.

1. Names matter more than you think

The first principle I follow is using descriptive names for variables and methods. It sounds obvious, but the difference between h and hoursSinceLastLogin can mean the difference between a one minute code review and ten minutes of confusion. When you write getUserAccountDetails() instead of getUAD(), sure it’s a few more key strokes today, however future developers (including yourself a few months from now) will thank you for making the code simple to understand.

2. Simple is better than clever

Building on principle one, you should strive for simplicity in your code over cleverness. Sure, it’s impressive that you can write a complex data transformation as a single line with multiple chained array methods, and nested ternaries. But you probably shouldn’t.

This isn’t about dumbing down code, it’s about being aware that maintainability often trumps elegance when you’re writing software with a team. The cleverest code in the world is a liability if your teammates can’t confidently debug or modify it in the future.

Side note: I’m particularly cautious about functional patterns in languages that weren’t designed for them (like JavaScript). I appreciate the elegance of functional programming and have used it where appropriate, but, in my experience, many engineers you work with won’t be comfortable with functional concepts like currying, function composition, or monads. Write software for the team and language you have, and everyone will likely be more productive for it.

3. Keep functions short

Functions should ideally do one thing, and that thing should be in the name (see principle #1). I’ve written my fair share of screen long functions, and they often turn into a future source of pain. Smaller functions tend to be easier to read, test, refactor, and reuse.

A function called validateInput() shouldn’t also send an email, update the database, and turn on your coffee maker. Each of those things should likely be their own functions. This separation makes your code more readable and might even prevent bugs that come from overlooked side effects.

4. Stay local if you can

My last principle is about code organization. I prefer to keep types and utility functions in the same file as modules or components until they need to be shared.

Too often I see projects where every type lives in a types directory and every utility function lives in a utils directory, even when these pieces are only used by a single component. This kind of premature optimization creates unnecessary cognitive overhead. Instead of scrolling through a single file from top to bottom, now I’m switching between a handful of tabs. It makes creating a mental model needlessly difficult.

Code isn’t just for machines

These principles all come from a single maxim, that code is primarily for humans, not computers. The computer doesn’t care if your variable name is descriptive. The computer doesn’t care if your function is five lines or five hundred. But your teammates will care. Future you will care.

My 2024 media diet 1/20/25

By Chris Johnson

For the past few years now, I’ve been keeping track of the media I watch and read. This is my list for 2024 in ascending chronological order:

Books

  • Tinker Tailor Soldier Spy ★★★★☆
  • Kafka Was All the Rage ★★★★☆
  • A Moveable Feast ★★★★☆
  • SPQR: A History of Ancient Rome ★★★★☆
  • Mastery ★★★★★
  • Lisbon: War in the Shadows of the City of Light ★★★★☆
  • A Gentleman in Moscow ★★★★★
  • Tough without a Gun: Humphrey Bogart ★★★★☆
  • Aubrey/Maturin: The Thirteen Gun Salute ★★★★☆
  • The Expanse: Leviathan Wakes ★★★★★
  • Slow Productivity ★★★☆☆
  • Aubrey/Maturin: The Nutmeg of Consolation ★★★★☆
  • The Honourable Schoolboy ★★★★☆
  • Breakfast at Tiffany’s ★★★★★
  • Napoleon: A Life ★★★★☆
  • The Burnout Society ★★★★★
  • Lincoln’s Virtues ★★★☆☆
  • A Perfect Spy ★★★★★

Movies

  • Run Lola Run ★★★★★
  • The Beekeeper ★★★☆☆
  • Anatomy of a Fall ★★★★★
  • The Holdovers ★★★☆☆
  • Dune: Part 2 ★★★★★
  • Monkey Man ★★★☆☆
  • Challengers ★★★★★
  • Mad Max 2: Road Warrior ★★★★★
  • Mad Max 3: Beyond Thunderdome ★★☆☆☆
  • Furiosa ★★☆☆☆
  • Love Lies Bleeding ★★★★☆
  • Deadpool & Wolverine ★★★☆☆
  • Le Samouraï ★★★★☆
  • Bullitt ★★★★☆
  • Wolfs ★★☆☆☆
  • Hit Man ★★★☆☆
  • La Piscine ★★★★★
  • Anora ★★★★★
  • The Witch ★★★★☆
  • Heretic ★★★☆☆
  • Juror #2 ★★★★★
  • Big Trouble in Little China ★★★★☆
  • Queer ★★★★☆
  • Gladiator 2 ★★★☆☆
  • I Am Love ★★★★☆
  • Babygirl ★★★☆☆
  • Nosferatu (2024) ★★☆☆☆
  • Miller’s Crossing ★★★★☆

Plays

  • Asi Wind’s Inner Circle (Magic) ★★★★★
  • Job (by Max Wolf Friedlich) ★★★★★
  • Enemy of the People ★★★★★
  • Mother Play ★★★★
  • Oh, Mary! ★★★★☆

My 2023 media diet 1/18/24

By Chris Johnson

For the past few years now, I’ve been keeping track of the media I watch and read. This is my list for 2023 in ascending chronological order:

Books

  • The Looking Glass War ★★★★☆
  • 4,000 Weeks ★★★★★
  • The Lion in the Living Room ★★★★☆
  • Rat Pack Confidential ★★★☆☆
  • The Alchemist ★★★★★
  • Aubrey/Maturin: The Reverse of the Medal ★★★★☆
  • Why Buddhism is True ★★★★★
  • Aubrey/Maturin: The Letter of Marque ★★★★★
  • Be Useful ★★★★☆
  • Mindset: The New Psychology of Success ★★★★☆
  • A New World Begins ★★★★☆

Movies

  • Avatar 2 ★★★☆☆
  • She Said ★★★★☆
  • Elvis ★★★★☆
  • Beverly Hills Cop ★★★★★
  • Good Liar ★★★☆☆
  • The Banshees of Inisherin ★★★★★
  • Everything Everywhere All at Once ★★★★☆
  • The Menu ★★★★☆
  • The Fabelmans ★★★★★
  • Tár ★★★★★
  • Amsterdam ★★☆☆☆
  • John Wick 4 ★★★☆☆
  • Bullet Train ★★☆☆☆
  • Guardians of the Galaxy Vol. 3 ★★★★☆
  • Asteroid City ★★★☆☆
  • The Life Aquatic with Steve Zissou ★★★★★
  • Mission: Impossible Dead Reckoning Pt. 1 ★★★☆☆
  • Indiana Jones and the Dial of Destiny ★★☆☆☆
  • Barbie ★★★☆☆
  • Oppenheimer ★★★★☆
  • Killers of the Flower Moon ★★★★☆
  • Prey ★★★☆☆
  • The Killer ★★★★☆
  • Napoleon (2023) ★★★☆☆
  • Poor Things ★★★★☆
  • Godzilla Minus One ★★★★☆
  • The Boy and the Heron ★★★★★
  • Maestro ★★★☆☆
  • Ferrari ★★★★☆
  • American Fiction ★★★★★

Plays

  • Harry Potter and the Cursed Child ★★☆☆☆
  • Sweeney Todd ★★★★★

Disabling Intercom during Playwright tests 11/5/23

By Chris Johnson

I recently ran into an issue where the Intercom chat widget was interfering with my Playwright integration tests. The widget was opening up and keeping some key elements from being clickable. A user could have easily dismissed the widget, but I didn’t want to bother dismissing it within Playwright. I couldn’t find any particular guidance on how to keep the widget from loading in the usual places on the web, so I had to come up with my own solution.

What I ended up doing was intercepting all outbound requests Playwright was making and skipping any that called the Intercom domain.

I created this helper function:

import { Page } from '@playwright/test'

export async function blockIntercom(page: Page) {
  await page.route('**/*', route => {
    if (route.request().url().includes('intercom.io')) {
      route.abort()
    } else {
      route.continue()
    }
  })
}

And then called it in the test files that were affected:

import { Page, test } from '@playwright/test'
import { blockIntercom } from 'helpers/block-intercom'

let page: Page

test.beforeAll(async ({ browser }) => {
  page = await browser.newPage()
  blockIntercom(page)
})

// your tests begin here

It shouldn’t be too difficult to modify this to also block chat widgets from other vendors like Zendesk or Drift.

My 2022 media diet 1/10/23

By Chris Johnson

For the past few years now, I’ve been keeping track of the media I watch and read. This is my list for 2022 in ascending chronological order:

Books

  • Homo Deus ★★★★★
  • Death’s End ★★★★☆
  • Waking Up ★★★★★
  • When We Cease to Understand the World ★★★★★
  • 21 Lessons for the 21st Century ★★★★☆
  • Master of the Senate: The Years or Lyndon Johnson ★★★★★

Movies

  • The Highwaymen ★★★★★
  • Body Heat ★★★★★
  • The Card Counter ★★★★☆
  • The French Dispatch ★★★★☆
  • Don’t Look Up ★★★★☆
  • The Tragedy of Macbeth ★★★★★
  • Spencer ★★★☆☆
  • House of Gucci ★★★☆☆
  • Nightmare Alley ★★★★☆
  • West Side Story (2021) ★★★★★
  • Licorice Pizza ★★★★★
  • The Batman ★★★★☆
  • Drive my Car ★★★★☆
  • The Last Detail ★★★☆☆
  • Top Gun: Maverick ★★★★☆
  • One Flew Over the Cuckoos Nest ★★★★★
  • Nope ★★★★☆
  • Enter the Dragon ★★★★☆
  • Don’t Worry Darling ★★★☆☆
  • See How They Run ★★★☆☆
  • When Harry Met Sally ★★★★★
  • Notting Hill ★★★★☆
  • Spirited ★☆☆☆☆
  • Ambulance ★★★★☆
  • Glass Onion ★★★☆☆
  • Long Kiss Goodnight ★★★☆☆

TV Series

  • Midnight Mass ★★★★★
  • Station 11 ★★★★★
  • The Night Manager ★★★★★

Plays

  • Beetlejuice ★★★☆☆
  • American Buffalo ★★★★☆

My 2021 media diet 1/30/22

By Chris Johnson

For the past few years now, I’ve been keeping track of the media I watch and read. This is my list for 2021 in ascending chronological order:

Books

  • The Murder of Roger Ackroyd ★★★★★
  • The 12 Week Year ★★★★☆
  • Cactus League ★★★☆☆
  • Kitchen Confidential ★★★★☆
  • The Spy and the Traitor ★★★★☆
  • Interview with the Vampire ★★★☆☆
  • Can’t Even ★★★☆☆
  • The Magician’s Nephew ★★★★☆
  • Essentialism ★★★★★
  • How to do Nothing ★★★★☆
  • Zero to One ★★★★★
  • Soccernomics ★★★☆☆
  • The Immortal Irishman ★★★★☆

Movies

  • Prospect (2018) ★★★★☆
  • Soul ★★★★☆
  • The Molly Maguires ★★★☆☆
  • The Man Who Would be King ★★★★☆
  • Russia House ★★★★☆
  • Minari ★★★★☆
  • Sound of Metal ★★★★★
  • Margin Call ★★★★★
  • The Trial of the Chicago 7 ★★★★☆
  • Nomadland ★★★★☆
  • Mank ★★★★★
  • Promising Young Woman ★★★★☆
  • The Father ★★★★★
  • Judas and the Black Messiah ★★★★★
  • Ma Rainey’s Black Bottom ★★★★☆
  • Wolfwalkers ★★★★★
  • Another Round ★★★★★
  • All is Lost ★★★★☆
  • In the Heights ★★★★☆
  • The Suicide Squad ★★☆☆☆
  • Reminiscence ★★★☆☆
  • A Most Violent Year ★★★★☆
  • James Bond: No Time To Die ★★★☆☆
  • Hereditary ★★★★☆
  • The Last Duel ★★★★☆
  • Dune Part 1 ★★★★☆
  • The Green Knight ★★★☆☆
  • Robin Hood (2010) ★★★☆☆
  • The Power of the Dog ★★★★☆
  • The Matrix Resurrections ★★★☆☆
  • Tenet ★★★★☆

My 2020 media diet 1/19/21

By Chris Johnson

For the past few years now, I’ve been keeping track of the media I watch and read. This is my list for 2020 in ascending chronological order:

Books

  • Harry Potter and the Goblet of Fire ★★★★☆
  • The Spy Who Came In From the Cold ★★★★★
  • Harry Potter and the Order of the Phoenix ★★★★★
  • Star Trek New Frontier: House of Cards ★★★☆☆
  • Primal Blueprint ★★★★☆
  • Harry Potter and the Half-Blood Prince ★★★★★
  • Stop Reading the News ★★★★★
  • The Dream Machine ★★★★★
  • Grant ★★★★☆
  • The Dark Forest ★★★★★
  • Harry Potter and the Deathly Hallows ★★★★★

Movies

  • 1917 ★★★★★
  • Little Women ★★★★★
  • Dolemite is My Name ★★★★★
  • Marriage Story ★★★★★
  • Jiro Dreams of Sushi ★★★★☆
  • Birds of Prey: Harley Quinn ★★★★☆
  • Contagion ★★★★☆
  • Missing Link ★★★★☆
  • Attack the Block ★★★★★
  • Onward ★★★★☆
  • The General ★★★★☆
  • Hostiles ★★★★☆
  • Barbarella ★★★☆☆
  • The Limey ★★★★☆
  • Bumblebee ★★★★☆
  • Train to Busan ★★★★★
  • Jumanji: The Next Level ★★★★☆
  • Cabin in the Woods ★★★★★
  • Batman Ninja ★★☆☆☆
  • Tremors ★★★★★
  • Her Smell ★★★☆☆
  • The Vast of Night ★★★★☆
  • Sorry to Bother You ★★★★☆
  • 6 Underground ★★★☆☆
  • The Imitation Game ★★★★☆
  • Everybody Knows ★★★★☆
  • Mississippi Grind ★★★☆☆
  • That Darn Cat ★★★☆☆
  • Burning (2018) ★★★★☆
  • Mulan (2020) ★★★☆☆
  • The Lighthouse ★★★★☆
  • Mulan (1998) ★★★★☆
  • Howl’s Moving Castle ★★★★★
  • Glass ★★★☆☆
  • Ponyo ★★★★☆
  • Borat Subsequent Movie Film ★★★☆☆
  • King of New York ★★★☆☆
  • Free Solo ★★★★☆
  • Blue Ruin ★★★★★
  • The Insider ★★★★★
  • Overlord ★★★★☆
  • Mary and the Witch’s Flower ★★★☆☆
  • Wonder Woman 1984 ★★★☆☆
  • Enola Holmes ★★★★☆

Plays

  • Hamilton (Disney+) ★★★★★

Stop reading the news every day 9/25/20

By Chris Johnson

I recently finished a book by Rolf Dobelli titled Stop Reading the News. Dobelli makes a compelling case to switch from daily news consumption to reviewing news once a week or not at all. As Dobelli argues that there’s not a lot you can do about the news literally as it happens, so why amp up your anxiety by consuming it every single day?

Now, I’m not ready to totally abandon the news — especially these days with COVID-19 raging in my home country — so I’m trying out the once a week strategy with a subscription to the print edition of The Economist. They give you the week’s news in a relatively condensed format that you can read in one sitting. Also, since it’s the print edition, I’m not getting lost following links all around the web. I’m also keeping tabs on COVID-19 cases in my area with tools like then Google News Coronavirus map, and as Dobelli suggests, I still read news about tech and development that have an impact on my career.

Stop Reading the News is a short book and I’d suggest giving it a read if you’re at all interested in understanding Dobelli’s reasoning for cutting back on the news and strategies for how to replace news in your life.

Newer model static sites 9/22/20

By Chris Johnson

Sites that are served statically (meaning they aren’t backed by a scripting language or a database) have big advantages in terms of speed, simplicity, and security. But as Leon Paternoster notes, the definition of static sites is changing, and we’re losing speed and simplicity in the process.

Under the traditional static model, the heavy lifting of building pages from includes and local or external data is done when the website is compiled into flat HTML files, whether that’s on a PC or a server. This happens out of view (hence Jekyll, incidentally), completely separately from any user involvement. Javascript is used to enhance UI, perhaps through offering sorting or filtering functions. All the user does is download the HTML file and its assets.

Under a newer model (which even has its own Netlify-created brand name of JAMstack) much of this heavy lifting is moved to the user’s browser. Websites are created as SPAs, where HTML, CSS, data and javascript are downloaded in one bundle and the javascript creates pages based on user interaction.

The issue with a “newer model” static site is that the JavaScript required to render a page is often so large and complex that it can take a significant amount of time to download and then execute on a device. That could be a recipe for frustration when visitors have spotty internet connections or are using relatively slow phones or laptops.