Blog

Posts on software development, careers, and craft.

Problem: You want to access some React state outside of React, in plain JS/TS

Problem: You want to access some React state outside of React, in plain JS/TS. Solution: Move the state out of React. Put it in Zustand instead. Zu...

So much needless UI complexity stems from REST APIs that do these two...

So much needless UI complexity stems from REST APIs that do these two things: Return null or undefined instead of an empty string. Return null or u...

A common coding mistake: Inconsistent terms

A common coding mistake: Inconsistent terms. Example: I'm reviewing a PR that alternates between these terms: saving pending creating submitting Us...

A key debugging skill: Decomposition

A key debugging skill: Decomposition. “Thinking is all about the ability to look at complex situations and strip away things that don't count—the a...

A surprising thing about owning a Tesla: Nearly everything is automated

A surprising thing about owning a Tesla: Nearly everything is automated. When I walk up, the doors sense my phone and unlock. When I get in, the ca...

An epidemic problem in software: Teams with missing skill sets

An epidemic problem in software: Teams with missing skill sets. I find teams often lack expertise in these skills: Devops Testing Security Accessib...

A recipe for fast, reliable end-to-end tests (no mocks): 1

A recipe for fast, reliable end-to-end tests (no mocks): 1. Create a test DB instance. 2. Create SQL scripts to populate the test DB with enough da...

Situation: A React component with 5 useEffect calls has a bug

Situation: A React component with 5 useEffect calls has a bug. Solution: Add a 6th useEffect to fix the bug. Just kidding. That's not a solution. I...

Folder pattern I’m enjoying: “Local” shared directories

Folder pattern I’m enjoying: “Local” shared directories. 1. First, create a shared directory at the root. This contains code shared across the enti...

In TypeScript, declaring types saves me more time than it costs me: ✅Speeds...

In TypeScript, declaring types saves me more time than it costs me: ✅Speeds up my reading. ✅Catches my errors earlier. ✅Clarifies my mental model....

Problem: If an endpoint returns JSON with properties I don't expect, I want...

Problem: If an endpoint returns JSON with properties I don't expect, I want to know about it. Solution: Use Zod with strict().

Disabled input fields aren't a loading strategy

Disabled input fields aren't a loading strategy. Show a loading indicator. Disabled buttons aren't a validation strategy. Show a helpful message wh...

Problem: Ideally, everyone is responsible for quality

Problem: Ideally, everyone is responsible for quality. But, if everyone is responsible, no one is responsible. Solution: Establish a code owner. Th...

“Deploy daily.” It’s a wonderful goal

“Deploy daily.” It’s a wonderful goal. But to safely deploy daily, you need a mature foundation: Automated build & tests No-downtime automated...

Rule for choosing between a URL path and search param: Search params are...

Rule for choosing between a URL path and search param: Search params are optional. So, if it’s required to render the page make it part of the URL'...

If the team is ignoring PRs that’s a management problem

If the team is ignoring PRs that’s a management problem. Managers need to make it clear that code reviews are important. The team needs to know: 1....

"We don't do code reviews

"We don't do code reviews. We trust our developers". You have no idea how often I run a PR and find it's broken. It's *extremely* common. Even from...

How I get my PRs merged fast: 1

How I get my PRs merged fast: 1. Keep the scope small 2. Provide a clear title and test plan 3. Write tests that document the expected behavior 4....

Some developers, when presented with a new library, immediately say “We need...

Some developers, when presented with a new library, immediately say “We need to build an abstraction around this before we use it.” You don’t know...

I often see aria-labels that look like an id: 🚩...

I often see aria-labels that look like an id: 🚩 aria-label="delete-user-button" An aria-label should have a *user-friendly* label that describes w...

React habit: Avoid putting things that only need to render once in a component

React habit: Avoid putting things that only need to render once in a component. Instead, I put things that only need to render once in root.render....

Just noticed another benefit of using Zod: It draws attention to bad...

Just noticed another benefit of using Zod: It draws attention to bad endpoint designs. Example: Why is the backend returning null if there are no t...

Problem: For accessibility and SEO, each page should have an H1 tag

Problem: For accessibility and SEO, each page should have an H1 tag. And heading tags should be in ascending order. But it’s easy to mess this up b...

I believe the pendulum shift back to server-rendering will help many teams...

I believe the pendulum shift back to server-rendering will help many teams write better software. Why? By improving developer communication. Back i...

There are infinite ways to write software poorly

There are infinite ways to write software poorly. There are few ways to write software well. We're a young industry, but we know what works: Break...

When I was a manager, some people came to me with problems

When I was a manager, some people came to me with problems. Others came to me with solutions. Guess who got promoted? Don't merely report problems....

When testing for expected strings, I typically assert explicit strings, not...

When testing for expected strings, I typically assert explicit strings, not the result of function invocations. Example: Here’s why: - Asserting fo...

General HTML rule: “disabled” optimizes for DX

General HTML rule: “disabled” optimizes for DX. It’s simple and easy for developers. “aria-disabled” optimizes for UX. It improves accessibility an...

Many UI teams are making a fundamental mistake: They’re not using mocks...

Many UI teams are making a fundamental mistake: They’re not using mocks effectively. The solution? Mock Driven Development.™️ 1. *Before* coding, l...

Sometimes, an Array.find is a sign of sloppy code

Sometimes, an Array.find is a sign of sloppy code. Example: Code passes around an id, and then multiple spots search an array for the full record....