Blog

Posts on software development, careers, and craft.

I avoid boolean function arguments

I avoid boolean function arguments. Here’s why. 🚩 They’re hard to read. 🚩 They infer the function does two different things Here's two common exa...

Today I thought “I can do this change in one big PR

Today I thought “I can do this change in one big PR. It’ll be fine.” I was wrong. I should have known. If a PR is big, find a way to split it.

Needless complexity: Using multiple terms to describe the same concept

Needless complexity: Using multiple terms to describe the same concept. I often see this in code reviews. For example, code may use all these words...

Security is important

Security is important. But some companies take it too far. “We can't because of security" is often used to block reasonable requests. Examples: You...

Before creating a custom hook, I search the web

Before creating a custom hook, I search the web. Often, an open source custom hook already exists. A few favorites: useDebounce useLocalStorage use...

It blows my mind that companies expect developers to work on slow virtual...

It blows my mind that companies expect developers to work on slow virtual machines, slow remote sessions, or slow, old hardware. When I have to wor...

GitHub CoPilot + TypeScript is an awesome combo

GitHub CoPilot + TypeScript is an awesome combo. Example: I'm improving types and CoPilot was smart enough to parse the entire file and see what va...

Doing a code review without running the code is like doing a quality check...

Doing a code review without running the code is like doing a quality check blindfolded. 🚩I have to use my imagination. 🚩I have to run the code in...

Zod is great, but it’s for *runtime* validation

Zod is great, but it’s for *runtime* validation. I've seen some teams using Zod's infer for nearly all their types. This just adds overhead and abs...

Yesterday, I suggested naming functions passed to useEffect

Yesterday, I suggested naming functions passed to useEffect. A few people suggested just using a comment. I disagree. Here's why. Code > comment...

Problem: React's useEffect only specifies when code should run

Problem: React's useEffect only specifies when code should run. It doesn’t document why it should run or what it should do. This makes useEffect ha...

It's surprising how often I see pull requests with these 2 attributes: 1

It's surprising how often I see pull requests with these 2 attributes: 1. Technically impressive, well-documented, and creative. 2. Needlessly comp...

A giant pull request is typically a mistake

A giant pull request is typically a mistake. Three techniques to avoid giant PRs: 1. Reduce scope. Ask, “could this ticket be any smaller?” 2. Spli...

Using TypeScript

Using TypeScript? Here's an ESLint rule I wish was enabled from the beginning: no-type-assertion Some of my clients have 500+ type assertions in th...

There are lots of ways to draw lines between junior and senior developers

There are lots of ways to draw lines between junior and senior developers. Here's a distinction I find useful. A senior developer makes suggestions...

"Every time you remove duplication, you add coupling." - @ardalis So before...

"Every time you remove duplication, you add coupling." - @ardalis So before eliminating duplicated code, I have to ask: Is the coupling I'm about t...

DRY = Don’t repeat yourself

DRY = Don’t repeat yourself. It’s generally a helpful principle. But, like many principles, it can be taken too far. My concern: If you dislike DRY...

“React has become complicated.” Don’t like RSC

“React has become complicated.” Don’t like RSC? Ignore it. I can keep building plain old SPAs in React. The new stuff is optional. In fact, React i...

TypeScript Problem: I need a specific property, but I don’t know the exact type

TypeScript Problem: I need a specific property, but I don’t know the exact type. Solution: SomethingWithX. It's a better choice than “any” because...

Me, reviewing a PR: Why are doing this weird thing

Me, reviewing a PR: Why are doing this weird thing? Author: The data is messed up. This fixes it. Me: Can we fix the root cause instead? If we can'...

Problem: I accidentally closed a tab or a file

Problem: I accidentally closed a tab or a file. Solution: Hit Cmd+Shift+T (Mac) or Ctrl+Shift+T (Win) to reopen the last closed tab. Bonus: It work...

I’m not strict about types because I enjoy being strict

I’m not strict about types because I enjoy being strict. I’m strict about types because: ✅ Types help us code faster. ✅ Types help us read faster....

Problem: Your code base probably contains a lot of copy/pasted code, but...

Problem: Your code base probably contains a lot of copy/pasted code, but it's hard to find. Solution: jscpd jscpd is a command line tool that finds...

Two Related Problems: 1

Two Related Problems: 1. useEffect is overused. 2. It's often hard to tell a useEffect is needless, because “useEffect” merely tells me *when* some...

I’ve been working in TypeScript for years and I think I’ve used “ts-ignore”...

I’ve been working in TypeScript for years and I think I’ve used “ts-ignore” about twice. I’ve found it’s rarely necessary and a strong sign somethi...

JavaScript habit: I prefer to use a "point-free" style

JavaScript habit: I prefer to use a "point-free" style. With a point-free style, args are passed to the function automatically. Less code. Same res...

When coding, I have at least 4 audiences: 1

When coding, I have at least 4 audiences: 1. My team 2. The compiler 3. Me in the future 4. The team in the future (who will lack our current conte...

React’s context works great for global state that changes rarely

React’s context works great for global state that changes rarely. But there are many alternatives that may be preferable depending on use case: Thi...

I like RSC

I like RSC. But it’s not perfect. Problems I’ve noticed: 1. Next.js is the only mature implementation I’ve seen so far. 2. Need a complex server co...

One of my favorite React Hook Form features: I can use a Zod schema to...

One of my favorite React Hook Form features: I can use a Zod schema to configure form validation with a single line of code. See the highlighted li...