Approximate reading time: 4-5 minutes. Full example code available as codesandbox and repository . In the first part , we saw how to take a fundamental, but usually implicit aspect of a component — the “phases” it can go through — and make it explicit, both to fellow developers and to developer tools; and how the increase in clarity translates into maintainability and reason-ability. In this part,…
Approximate reading time: 5 minutes. Full example code available as codesandbox and repository . If you’ve written anything but the most basic component, you know that logic in React can turn opaque real fast: you begin with a few booleans — tracking whether a menu is open, whether a request is loading. You throw in some hooks: data fetching, form validation, accessing URL parameters. Soon you’re…
Something that frustrates even the most honest effort to enact an efficient testing strategy is misunderstanding this: prepare input run computation assert output For this: prepare arguments run function assert return value But arguments aren’t the only way data gets into a function. This is input: const activateUser = async ( userId : string ) => { // ... const blockedUserIds : string [] =…
When I open a file and see process.env used like this, I know I’m in trouble: function Cart () { useEffect ( () => { fetch ( `${ process . env . REACT_APP_API_BASE_URL } /cart ` ) . then ( ( res ) => { // ... Why? Well, suppose I offer you a strategy to make your app work locally, yet break in production, in a way that your users will notice but you won’t, is hard to debug, and is guaranteed to…
NextJS’s conventions are not TDD-friendly, but with some work and a little structure we can enjoy a smooth red-green ride. Let’s say we need a NextJS API route that gives us dictionary definitions. The route handler should validate the request, query a 3rd-party dictionary API, extract desired data from the response, and relay it to the front end. We want a fast feedback loop and low chances of…
I recently started hosting AMA-style cafe chats with developers at various stages of their journey, about software engineering and anything else within my technical experience. Below are some notes from the chat on Nov 16th, 2022. Imagine you feed this to your front-end i18n library: const i18enStrings = { " home.title " : " Life, universe, and everything " , " home.subtitle " : " A guide " , } ;…
I recently started hosting AMA-style cafe chats with developers at various stages of their journey, about software engineering and anything else within my technical experience. Below are some rough & rapid-fire notes from the chat on Oct 21st, 2022. “I never did any formal design, where can I start?” A dead-easy yet high-return strategy : take a core functionality of the system (e.g. “purchasing…
Install Eldev Eldev is make (and then some) for Emacs Lisp development. curl -fsSL https://raw.github.com/doublep/eldev/master/webinstall/eldev | sh The eldev executable will be installed in ~/.local/bin . Create a project directory ~ /projects$ mkdir emacs-simple-calculator ~ /projects$ cd emacs-simple-calculator ~ /projects/emacs-simple-calculator$ git init Create the main project file…
I recently started hosting AMA-style cafe chats with developers at various stages of their journey, about software engineering and anything else within my technical experience. Below are some rough & rapid-fire notes from the chat on Oct 21st, 2022. Getting started You can test at various levels, from an individual function that knows nothing about browsers to an entire application running in a…
I recently started hosting AMA-style cafe chats with developers at various stages of their journey, about software engineering and anything else within my technical experience. Below are some rough & rapid-fire notes from the chat on Oct 21st, 2022. “Why test?” Tricky question because it puts you in the mindset of writing test code after application code (rarely you’d think IRL of testing…
[Originally written for people onboarding a project I’ve been leading, to explain why services are structured the way they are, and to provide a set of reasoned guidelines.] 1. Decouple service configuration, definition, creation, and startup If your index.ts looks like this: import express from " express " ; const app = express () ; app . get ( " / " , ( req , res ) => { /* ... */ } ) ; app .…
web3-mock supports Cypress and JSDOM test environments out of the box. However, I prefer Playwright to those as it provides a compelling set of benefits: familiar Jest matchers, a fixture-based runner, and execution in multiple real browser environments. Getting web3-mock to work with Playwright requires setup that is minimal but not obvious, hence this quick note. The test definitions configures…
Structure describes and prescribes; it tells about the system while nudging you into thinking of, and using it, in a certain way—hopefully, a way that was chosen deliberately, wisely, and points toward the pit of success . Discussion of React project structures usually centers on the descriptive (“what does folder/file X contain?”) with an intent of easing navigation (“where do I find…
The “conventional commit” format advocates prefixing commit messages with keywords to give both humans and machines a quick idea of what’s affected: 41e7be2 feat: notify user on new messages f3b33ab build: enable caching to decrease build times 7501fb2 fix(api): detect invalid query parameter f5baa4d docs: typo 06e851a perf(ui): optimize loading time The keyword mostly answers the question: “How…
(The following is expanded from my comment at #storybook/10987 ) Storybook provides, among other things, a canvas to develop UI components interactively and in isolation. In any kind of digital work, interactivity comes not only from the absence of manual steps between making a change and seeing the outcome, but also from a feedback loop tight enough to keep your mind on the task: a word processor…
Stateful systems that get into inconsistent states are a frequent source of bugs. Making conceptually interdependent data also programmatically interdependent is one way of addressing the root of the problem. When a bug breaks production, it’s good to ask: “Why didn’t a test catch that?”. An even better question is “Why did the code build at all?”, but it isn’t asked nearly as often. Why? Perhaps…
For many tasks in a developer’s day, a well-tuned compilation mode is more efficient than reaching for a shell (fewer keystrokes, less context switching) and lighter on the brain than specialized major modes (no new key bindings). Emacs’s “compilation” mode is not limited to running compilers. You can run bundlers for front-end development, test runners for red-green-refactor TDD, project-wide…
Functions that ask for more than they need trick the developer into writing unnecessary code. At best, this slows down future development; at worst, it harms runtime qualities: of the present system. Imagine that you inherited this code: const post = await api . fetchPostById ( ' abc123 ' ) // => { // id: 'abc123', // title: 'The dangers of greedy functions', // authorName: 'Max' // } const…