Blog
Posts on software development, careers, and craft.
Problem: localStorage isn’t strongly typed
Problem: localStorage isn’t strongly typed. You read and write to it via a string key, and the value returned is always a string. 👎 Solution: 1 In...
Tip: Avoid AWS CodeCommit
Tip: Avoid AWS CodeCommit. One of my clients just switched from AWS CodeCommit to GitHub. I couldn't be happier. Doing code reviews and configuring...
Problem: Sometimes devs accidentally reorder imports while coding
Problem: Sometimes devs accidentally reorder imports while coding. This leads to needless diffs. Solution: eslint-plugin-import's import/order rule...
Problem: A function is confusing, but you need to enhance it to support a...
Problem: A function is confusing, but you need to enhance it to support a new feature. Solution: Write unit tests that document the *current* behav...
Problem: If you lazy load routes, React Router's loaders won't run until...
Problem: If you lazy load routes, React Router's loaders won't run until after the lazy route downloads and parses. Solution: 1. Add a "lazy" prope...
Problem: You have TypeScript types, but want to use Zod too (for *runtime*...
Problem: You have TypeScript types, but want to use Zod too (for *runtime* validation) Solution: 1. Paste your TS type into transform tools to gene...
You don’t need an architect
You don’t need an architect. But you do need at least one person who thinks architecturally. Common titles: Team lead Senior Dev Architect Principa...
You don’t need a daily standup
You don’t need a daily standup. But you do need to communicate often. You don’t need formal retrospectives. But you do need to regularly discuss im...
Avoid Sprints
Avoid Sprints. Sprints create an arbitrary deadline every x days. This creates estimation overhead, and fosters short-term thinking. 👎 Instead: 1....
Problem: Sometimes people use needless curly braces around static values
Problem: Sometimes people use needless curly braces around static values. Solution: Automatically remove needless curly braces via ESLint. Rule: ht...
Some teams struggle because there’s too much friction in making improvements
Some teams struggle because there’s too much friction in making improvements. If a dev has to create a ticket, sell management, size the task, and...
React-query tip: You don't have to mess with error handling on each query
React-query tip: You don't have to mess with error handling on each query. Instead, you can automatically fallback to the nearest error boundary if...
If managers fixate on deadlines rather than quality, the staff will too
If managers fixate on deadlines rather than quality, the staff will too. Developers assure they make deadlines by: 🚩Copy/pasting 🚩Cutting corners...
Problem: You need to make a breaking change, but can’t update all call sites...
Problem: You need to make a breaking change, but can’t update all call sites at once. Solution: Expand, migrate, contract. 1. Expand. Add the new A...
I'm working with a SPA that has a dedicated backend composed of over a dozen...
I'm working with a SPA that has a dedicated backend composed of over a dozen microservices. Each service has its own repo, and its own DB, even tho...
To me, TypeScript is easily the most attractive language for implementing...
To me, TypeScript is easily the most attractive language for implementing web services. Why? Because we can build the UI and services *in the same...
Just learned about transform tools
Just learned about transform tools. This site converts a huge number of formats. JSON GraphQL TypeScript Zod YAML TOML CSS Tailwind OpenAPI schema...
Problem: You’re testing in Playwright, and using Mock Service Worker (msw)...
Problem: You’re testing in Playwright, and using Mock Service Worker (msw) with to mock endpoints. You want to customize the msw responses for each...
Types
Types. Are. Important. I'm working with a codebase littered with weights. It's written in TypeScript, but weight unit is stored as a "string". 👎 R...
Problem: You’re using TypeScript and you don’t want to manually define types...
Problem: You’re using TypeScript and you don’t want to manually define types for each REST endpoint response. Solution: quicktype. Paste JSON into...
The world is filled with code that barely works: 🚩Slow 🚩Insecure...
The world is filled with code that barely works: 🚩Slow 🚩Insecure 🚩Inefficient 🚩Unreadable 🚩Inaccessible 🚩Requires pristine input 🚩No error h...
Habit: I talk to myself while coding
Habit: I talk to myself while coding. I find coding is easier when I verbalize my thinking. I basically pretend I’m teaching. This forces me to con...
I've been asked to fix a broken page, inherited from an outside dev team
I've been asked to fix a broken page, inherited from an outside dev team. Heavy use of "any". No tests. I just came across these 2 lines, and I'm s...
JS arrow functions are great
JS arrow functions are great. ✅ Concise ✅ Optional implicit return ✅ Don’t have their own “this” context But, I don’t recommended using them everyw...
If coding is hard, we're probably trying to move to fast
If coding is hard, we're probably trying to move to fast. Signs we're trying to move too fast: 🚫 Rework 🚫 Inconsistency 🚫 Unclear tickets 🚫 Bad...
In databases, normalization is important
In databases, normalization is important. It avoids wasting space, and more importantly, avoids out-of-sync data. On the UI, the same principle hol...
The problem with a team of only junior developers: Anti-patterns proliferate
The problem with a team of only junior developers: Anti-patterns proliferate. One dev does it the "hard" way, or the "wrong" way, and the others co...
Habit for creating smaller PRs, sooner: Suffix branch names with "phase-x"...
Habit for creating smaller PRs, sooner: Suffix branch names with "phase-x" Example: ticket-1-phase-1-improve-naming ticket-1-phase-2-improve-perfor...
Automate checks that can be automated
Automate checks that can be automated. ✅ Code compiles ✅ Tests pass ✅ Formatted ✅ Honors code standards Then our code reviews can focus on checks t...
TypeScript tip: Use “never” to assure every case in a switch is handled
TypeScript tip: Use “never” to assure every case in a switch is handled. With this example, if a case is missing, TypeScript fails to compile. 👍 #...