A maze that exists only as a data structure in memory is a bit useless. We need some way to make it legible to human beings. So Iβve written an article that addresses how we do that.
βhttps://jrsinclair.com/articles/2025/rendering-mazes-on-the-web/
25.08.2025 08:18 β π 0 π 0 π¬ 0 π 0
Thinking about this some more, I do wonder if explore-expand-extract tracks as a specific application of Dave Snowdenβs Cynefin framework.
25.07.2025 22:28 β π 0 π 0 π¬ 0 π 0
YouTube video by GOTO Conferences
3X Explore, Expand, Extract β’ Kent Beck β’ YOW! 2018
I can't believe I haven't come across this talk by @kentbeck.com before. It has so much explanatory power.
www.youtube.com/watch?v=Wazq...
23.07.2025 22:21 β π 6 π 2 π¬ 1 π 1
In Praise of βNormalβ Engineers
This article was originally commissioned by Luca Rossi (paywalled) for refactoring.fm, on February 11th, 2025. Luca edited a version of it that emphasized the importance of building β10x engiβ¦
@charity.wtf talks a lot of sense, as usual:
> [10x Engineers exist] So what? It doesnβt matter. [β¦] What matters is how fast the team can collectively write, test, review, ship, maintain, refactor, extend, architect, and revise the software that they own.
charity.wtf/2025/06/19/i...
09.07.2025 06:40 β π 0 π 0 π¬ 0 π 0
What do you think? Does this theory make sense, or am I simply defending my biases?
02.04.2025 09:36 β π 0 π 0 π¬ 0 π 0
As a side effect of this structured thinking process, you also generate automated tests that provide immediate feedback on your progress. And if you're following _all_ the steps (red, green, refactor), the code improves with every iteration.
02.04.2025 09:36 β π 0 π 0 π¬ 1 π 0
Itβs because that initial investment of self-discipline pays off. And the return on investment is huge. Problems are easier to solve if you are clear and specific about what the issue actually is.
And thatβs not all.
02.04.2025 09:36 β π 0 π 0 π¬ 1 π 0
Instead, TDD forces you to be very specific upfront about _what_ you want to achieve. And that feels like less fun and more effort than diving in and coding a solution. It takes mental effort.
Why, then, do some people love TDD so much?
02.04.2025 09:36 β π 0 π 0 π¬ 1 π 0
I have a theory. People struggle with TDD because it feels like hard work. This is because many of us code to think. We're assigned a task, and we start hacking away in the IDE. The solution languidly emerges as we learn more by writing code.
But TDD wonβt let you do that.
02.04.2025 09:36 β π 0 π 0 π¬ 1 π 0
What would you use these for? Well, if you have large arrays, they can (sometimes) be a more efficient alternative than `.filter()` if you know where the data you want is at the start (or the end) of the array. They also come in handy when writing parsers.
01.04.2025 03:24 β π 0 π 0 π¬ 0 π 0
Screenshot of some JavaScript code. The code is as follows:
const dropWhile = (pred, arr) => {
const idx = arr.findIndex(x => !pred(x));
return arr.slice(idx);
}
console.log(dropWhile(isVowel, ['a', 'e', 'i', 'o', 'u', 'b']));
// πͺ΅ ['b']
The second, dropWhile(), does the opposite. It traverses your array and ignores items until a predicate returns false. Then it will give you the rest of the array.
01.04.2025 03:24 β π 1 π 0 π¬ 1 π 0
Screenshot of JavaScript code. The code is as follows:
const isVowel = (c) => ['a', 'e', 'i', 'o', 'u'].includes(c);
const takeWhile = (pred, arr) => {
const idx = arr.findIndex(x => !pred(x));
return arr.slice(0, idx);
}
console.log(takeWhile(isVowel, ['a', 'e', 'i', 'o', 'u', 'b']));
// πͺ΅ ['a', 'e', 'i', 'o', 'u']
The first, takeWhile(), traverses your array and keeps adding items to a new array until a predicate returns false.
01.04.2025 03:24 β π 0 π 0 π¬ 1 π 0
A couple of array utilities you won't find in Array.prototype π§΅
01.04.2025 03:24 β π 0 π 0 π¬ 1 π 0
A quote by John Ousterhout, from the book 'A Philosophy of Software Design'.
βMost modules have more users than developers, so it is better for the developers to suffer than the users. As a module developer, you should strive to make life as easy as possible for the users of your module, even if that means extra work for you. Another way of expressing this idea is that it is more important for a module to have a simple interface than a simple implementation.β
In some ways, this is so obvious it shouldn't need stating. But it does. And the tension is real. We want our code to be elegant, simple, concise. Yet, we rarely trade that off against the complexity that elegance creates in the interfaces (user interfaces and APIs) we develop.
30.03.2025 21:34 β π 1 π 0 π¬ 1 π 0
How to deal with dirty side effects in your pure functional JavaScript
If you start learning about functional programming, it wonβt be long before you come across the idea of pure functions. And as you go on, you will discover functional programmers appear to be obsessed...
From the archives: jrsinclair.com/articles/201...
Functional programmers are obsessed with purity. βPure functions let you reason about your codeβ. βThey give you referential transparency!β And they have a point. Purity is good. But what do you do with the impure bits of your code?
27.03.2025 21:22 β π 0 π 0 π¬ 0 π 0
// With our Map-based approach, we essentially reimplemented
// the Set data structure. We might as well use the Set
// constructor directly.
const uniq = (xs) => [...new Set(...xs)];
const fruits = ['apple', 'banana', 'apple', 'orange', 'banana'];
console.log(uniq(fruits)); // πͺ΅ ['apple', 'banana', 'orange']
All we've really done with the third option, though, is re-implement the Set structure from scratch. So, we might as well use that. The most efficient option also happens to be the most concise.
26.03.2025 22:39 β π 1 π 0 π¬ 0 π 0
// To avoid traversing the array more than we need to,
// we can use a Map to keep track of the elements we've
// seen so far. This way we only traverse the array once.
const uniq = (xs) => Array.of(
(xs.reduce((m, x) => m.set(x, true), new Map())).keys()
);
const fruits = ['apple', 'banana', 'apple', 'orange', 'banana'];
console.log(uniq(fruits)); // πͺ΅ ['apple', 'banana', 'orange']
To avoid traversing the array more than we need to, we can use a Map to keep track of the elements we've seen so far. This way we only traverse the array once. Once we've been through the list, we return the keys of the Map as an array.
26.03.2025 22:39 β π 0 π 0 π¬ 1 π 0
// A more efficient approach is to use .indexOf() to
// check if the current element is the first occurrence
// of that element in the array.
const uniq = (xs) => xs.filter(
(x, i) => xs.indexOf(x) === i
);
const fruits = ['apple', 'banana', 'apple', 'orange', 'banana'];
console.log(uniq(fruits)); // πͺ΅ ['apple', 'banana', 'orange']
A (slightly) more efficient approach is to use .indexOf() to check if the current element is the first occurrence of that element in the array. But it still traverses the array many more times than it needs to.
26.03.2025 22:39 β π 0 π 0 π¬ 1 π 0
// NaΓ―ve solution. This is inefficient because it
// traverses the array multiple times, and creates
// lots of new intermediate arrays. It works, though.
const uniq = (xs) => xs.filter(
(x, i) => !xs.slice(i + 1).includes(x)
);
const fruits = ['apple', 'banana', 'apple', 'orange', 'banana'];
console.log(uniq(fruits)); // πͺ΅ ['apple', 'banana', 'orange']
Our first approach uses a filter and `.includes()`. This is inefficient because it traverses the array multiple times, and creates lots of new intermediate arrays. It works, though.
26.03.2025 22:39 β π 0 π 0 π¬ 1 π 0
Four ways to remove duplicates from an array in JavaScript. π§΅
P.S. Use the last one.
26.03.2025 22:39 β π 2 π 0 π¬ 1 π 0
Screenshot of a code snippet showing the use of an array tuple as a Maybe construct. Code reads as follows:
// Suppose we want to retreive the weather conditions
// for a given location. Perhaps we've retreived some
// data from a weather API and we need to process it.
const sensors = {
['Dartmoor']: { value: 10, unit: 'C' },
['Baker Street']: { value: 18, unit: 'C' },
['Scotland Yard']: { value: 68, unit: 'F' },
}
const conditions = {
['Dartmoor']: 'Foggy',
['Baker Street']: 'Sunny',
['Scotland Yard']: 'Rainy',
}
const toCelsius = (fahrenheit) => (fahrenheit - 32) * (5 / 9);
// Here we define a function that wraps our value in an
// array if it's not nullish. We can then use .map(),
// .flatMap(), .reduce() etc. to safely handle the
// nullish case.
const maybe = (value) => value == null ? [] : [value];
const getWeather = (location) => maybe(sensors[location])
.map(({unit, value}) => unit === 'F' ? toCelsius(value) : value)
.flatMap(
(temperature) => maybe(conditions[location])
.map((condition) => ({temperature, condition}))
)
.map(({temperature, condition}) => `${location}: ${temperature}Β°C, ${condition}`)
.reduce((_, x) => x, 'Weather conditions not available');
console.log(getWeather('Dartmoor')); // πͺ΅ 'Dartmoor: 10Β°C, Foggy'
console.log(getWeather('Scotland Yard')); // πͺ΅ 'Scotland Yard: 20Β°C, Rainy'
console.log(getWeather('Diogenes Club')); // πͺ΅ 'Weather conditions not available'
Did you know that you can use an array tuple in place of a Maybe structure? It elegantly handles empty values using familiar `.map()`, `.flatMap()`, and `.reduce()` methods. I think it's rather neat. Credit goes to @jmsfbs@pixelfed.social for introducing me to the idea.
25.03.2025 21:48 β π 0 π 0 π¬ 0 π 0
Ousterhout argues that general purpose code tends to be simpler. It doesn't need to handle lots of special cases with copious if-statements and control structures. This kind of code handles those cases "ya ain't gonna need" _without any modification_.
24.03.2025 22:07 β π 0 π 0 π¬ 0 π 0
In case you haven't come across it, YAGNI stands for "ya ain't gonna need it." The idea is that we want to avoid over-complicating things to solve for problems we may never encounter. Applied carelessly, you may end up with an over-specialized design.
24.03.2025 22:07 β π 0 π 0 π¬ 1 π 0
I love this quote from John Ousterhout:
> I have found over and over that specialization leads to complexity; I now think that over-specialization may be the single greatest cause of complexity in software.
On the surface, it appears to contradict YAGNI, but not necessarily.
24.03.2025 22:07 β π 0 π 0 π¬ 1 π 0
Screenshot of some JavaScript code showing two variables being swapped using array destructuring. The code reads as follows:
let a = 'left';
let b = 'right';
console.log([a, b]);
// πͺ΅ ["left", "right"]
// Swap two variables with array destructuring.
[b, a] = [a, b]
console.log([a, b]);
// πͺ΅ ["right", "left"]
It's old news now, but swapping variables with destructuring still blows my mind every time I see it.
23.03.2025 21:21 β π 0 π 0 π¬ 0 π 0
Youβre right, itβs sad that you canβt generally assume that people know that ?? Is available when they use || for setting defaults. Knowledge about new language features takes some time to disperse.
21.03.2025 00:45 β π 0 π 0 π¬ 1 π 0
Thereβs nothing wrong with using || if it suits your use case. As you suggest, if youβre dealing with user-supplied data, thatβs a slightly different use case to one where a developer omits an optional config parameter.
21.03.2025 00:43 β π 1 π 0 π¬ 0 π 0
Screenshot of JavaScript code illustrating use of the nullish coalescing operator. The code reads as follows:
function doSomething(configParam) {
const config = configParam || DEFAULT_VAL; // β
// Rest of code
}
// The code above breaks if config param is a primitive
// type (not an object). For example:
'' || 'Unexpected' // β‘οΈ 'Unexpected'
0 || 'Unexpected' // β‘οΈ 'Unexpected'
false || 'Unexpected' // β‘οΈ 'Unexpected'
// Instead, use the ?? operator
function doSomething(configParam) {
const config = configParam ?? DEFAULT_VAL; // β
// Rest of code
}
I still see lots of people setting default values in JS using the || operator. This is fine if the values you're dealing with are always objects. But if you deal with numbers, booleans or strings, this can be problematic. In most cases, the ?? operator is a better choice.
20.03.2025 22:26 β π 2 π 0 π¬ 1 π 0
computers can be understood β’ she/her, β’ β’ Chicago
Web components at Microsoft. Co-host at ShopTalk. Previously Luro and Paravel. Blogger.
π€ designer, developer, blogger
β€οΈ lover of food & websites
π· icon-noisseur iosicongallery.com
π https://mastodon.social/@jimniels
π https://blog.jim-nielsen.com
π https://notes.jim-nielsen.com
Production-ready software in TypeScript. Open-source library.
βWebsite & Docs: https://effect.website/
βCommunity & Support: http://discord.gg/effect-ts
Dean @TalbotTheology
Edtr @OutreachMag
Pstr @MarinersChurch
Dstngushd Vstng Scholar @WycliffeHall at Oxford
https://linktr.ee/edstetzer
Physicist, mathematician, programmer.
"The Dao of Functional Programming"
Regularly updated work in progress. PDF on GitHub:
https://github.com/BartoszMilewski/DaoFP/blob/master/DaoFP.pdf
Mediocre middle-aged white man from Ireland living in Brighton, England working with Clearleft.
I play traditional Irish music on mandolin and I play slide bouzouki in the band Salter Cane.
https://adactio.com
Irish writer and speaker: let's rewild the internet!
Dog lady. Forest bather. She/her
http://www.mariafarrell.com
Rep: https://greeneheaton.co.uk/agents/antony-topping/
No DMs
Web Designer/Dev. Accessibility & Performance Fan. Mediocre surfer.
Engineer: Squarespace Performance & Accessibility
My Web components course: $25 if you use the code TWENTYFIVE https://scottjehl.com/learn/webcomponentsdemystified/
scottjehl.com
A person who enjoys creating things with friends & does not enjoy fascism
π³οΈββ§οΈ Queer art & code (& "ideology")
πΈοΈ Web dev/teaching @OddBird.dev
π
CSS @ W3C Working Group
π©πΌβπ€ Art @ TeacupGorilla.com & GrapefruitLab.com
MiriamSuzanne.com
Lead Software Engineer, Frontend Dev, Speaker, Eng Manager (she/her) | GDE Web Tech, Microsoft Regional Director (MVP program) | http://instagram.com/adognamedjello
I make some bits of the web
Elsewhere:
http://200ok.blog/
https://mastodon.social/@200ok
https://www.instagram.com/200ok/
Melbourne, Australia. he/him
Conferences and more for web and digital professionals since 2006
https://webdirections.org
Great grand father of responsive web design. Web Daoist. Organiser of the Web Directions conferences webdirections.org
Built the streaming service for conferences conffab.com
post clips to Bluesky from any webpage webdirections.org/bluesky-poster
Software craftsman π¨βπ§
π¦ CSS Modules co-creator / πΏ Remix + React Router at Shopify / π§ Vanilla Extract / MelbJS organiser / dad x4
π₯ Developer relations engineer for Langflow getting involved in all things AI, agents, and MCP.
π£οΈ speaker | π writer | π sausage dog owner | he/him
https://philna.sh/