Top
Best
New

Posted by handfuloflight 12/11/2025

Patterns.dev(www.patterns.dev)
627 points | 153 commentspage 2
css_apologist 12/11/2025|
this site reads like its 2017

its low quality, breadth but no depth

more important is to deeply understand the basics of working with immutable data. try writing applications with no for loops or forEach (and actually use the array methods as they are intended), no cloneDeep hacks and obviously no direct property mutation, always create a new object.

in real world you still use for loops plenty, but as a junior its good to see what its like to live without it for a while.

dominicrose 12/11/2025||
I've used Clojure/Script in the past and it's good to enforce working with immutable data.

Immutable.js has similar data structures but it's not the standard way of doing things and uglier to debug.

Using standard objects, immutability is not enforced in JS and throwing a few Object.freeze calls won't change that so we lose half the benefits that Clojure would bring: parallel/concurrent programming benefits, easier deep equality checks, performance...

If the code is not performance sensitive and can run in a single thread, simply "not mutating some of the mutable data" is a start for someone interested in immutability. That's what ramdajs does, it doesn't invent new data structures or freeze objects but simply returns new ones.

Only a few functions from ramdajs are actually useful in 2025 since JS has evolved with things like array/object destructuring and "..." but in any case it's an inspiring library.

css_apologist 12/11/2025||
I've used these things. IME, nowadays it's not worth the bundle size to bring in these libraries. map/filter seems quite optimized, {...obj} is fast since its only shallow. Yes it does come down to practices vs better libraries, but in practice, it's fine IME

One thing to note, i was very excited that we have a bunch of lazy methods on Iterator protocol, but they are slow as shit as of earlier this year.

I wrote a parser a year ago with extreme use of .map (every step of processing was cloning the tokens), and i thought, let's migrate it to lazy iterator - it got ~10x slower :(. The compile time was fine for my use cases, so i didn't give immutable-js a try, but it was a surprise

I did some benchmarks on map+filter vs mutable for of + push, and on firefox up to 200-300 elements map+filter is actually faster (unforunately not on chrome).

Of course, its not the best, but my experience is that modern js engines are fast enough for most use cases to not have to bring in any libraries anymore

dominicrose 12/16/2025||
I think the goal of lazy iterations is to make less iterations, not to make iterations themselves faster.
css_apologist 12/11/2025||
although this article does get me thinking of documenting the “patterns” i use, and why.
HumanOstrich 12/11/2025||
I was glancing around and landed on the page for the flyweight pattern.[1]

It looks like `addBook` is using the spread operator, which always creates a shallow copy of the book instance properties, thus nullifying any benefits of the flyweight pattern. It also attaches extra arbitrary properties, but still assigns the result to a `book` variable. I don't think this is a great example.

[1]: https://www.patterns.dev/vanilla/flyweight-pattern/

Edit: I forgot to give you kudos for all the effort it must have taken to create all this content, and I appreciate that you're making it available for free.

KPGv2 12/11/2025||
> which always creates a shallow copy of the book instance properties, thus nullifying any benefits of the flyweight pattern

No, the opposite: it highlights the benefits of the flyweight pattern. The shallow copy saves memory. That's the point. You have two identical books. Rather than wasting memory with a deep copy, you make a shallow copy, where all your props point to locations in memory where values are located, and then you modify whatever is different. Now your shallow copy only consumes a small bit of extra memory.

And if those props are all primitives, then you can then modify that shallow copy, and it won't affect the original.

HumanOstrich 12/11/2025||
The point is to not make a copy at all for the shared data of the same book. That's even what the page claims is happening (but it's wrong). That's the whole point of the flyweight pattern[1]. Instead, the example returns the same book instance for the same isbn in `createBook`, then blindly copies the shared data like title, author, and isbn every time in `addBook` to a new object.

> The shallow copy saves memory....

Versus not making a copy? A shallow copy of primitives still copies them and uses additional memory. Maybe there's some low-level optimization that makes it more efficient than that, but it's not relevant here. And there isn't any deep cloning happening in the example.

Might as well get rid of the complexity and instantiate a new Book class every time. And maybe stop shallow-copying class instances into new plain objects. It works for the example but has footguns.

Conveniently, there are other patterns on the site that would help you avoid creating an amalgamation of random merged class instances and objects.

The whole example is a mess.

[1]: https://en.wikipedia.org/wiki/Flyweight_pattern

songodongo 12/11/2025||
Good to know I wasn’t the only one thinking “wait a second…” when reading that one and seeing the spread operator being used.
rswail 12/11/2025||
Patterns are needed for languages for which the actual underlying concept is unavailable.

For example, prototype pattern is for languages that don't have a way to express interfaces/traits etc as something that can be attached to other language entities.

pedrozieg 12/11/2025||
Most teams don’t fail because they picked the wrong framework; they fail because they never ship enough iterations for it to matter.

Anything that reliably shortens that loop is “good tech,” even if it’s ugly, uncool, or built on last decade’s stack.

seabass 12/11/2025||
Love this! Just wanted to note that I think there’s a mistake on the flyweight pattern page’s example. You’re using getting a boolean with Set.has but treating it like a Book (as if you had used Set.get). I also don’t really understand how this saves memory if you’re spreading the result into a new object, but maybe someone here can enlighten me!
seabass 12/11/2025|
Ah I think I understand now. The return type of createBook is true | Book, which is likely a mistake, but happens to work because when you attempt to spread a boolean into an object it removes itself. But if you were to edit the example to have a stable return type of Book then it would no longer save memory, so perhaps that was intentional?
wavemode 12/11/2025||
Great site!

I tend to advocate for people to study design patterns. Not for the purpose that you will necessarily ever use most (or even any) of these exact patterns in your software, but just that you've strengthened your mental muscle for software design in general. I encounter lots of engineers who simply aren't able to think "outside the box" when building something new.

lock1 12/11/2025|
I always wondered if people actually find it beneficial to follow these "design patterns" or not.

Personally, I prefer to learn FP patterns, which tend to be backed with nice mathematical properties behind them.

verdverm 12/11/2025||
Is this JavaScript's take on the GOF book selections plus all the shenans, er "patterns," the ecosystem build tools require?

I was hoping for more high-level architecture based on war stories and experience. This is pretty basic stuff, which has it's value for people earlier in their journey, and does seem to have effort put in from a quick peruse

bingemaker 12/11/2025||
Looks more or less like GoF? Maybe compressing files and optimizing 3rd party js files are not patterns.
pajtai 12/11/2025|
Looks great. Wish it had a table of contents. Am I missing it?
More comments...