Patterns.dev
Posted by handfuloflight 1 day ago
Comments
Comment by emaro 1 day ago
Now I'm working on an old (+10 years) JS application. Similar patterns were implemented, but in this case it's not helpful at all. The code looks very corporate and Java EE style, with a ton of getters and setters (`getName() {}`, not `get name() {}`, factories, facades, adapters, etc, etc. It's usually completely unclear what the benefit of the pattern is, and code is more complicated, for instance because creating new instances of business objects is split into `Object.build` which calls `new Object`, with no guidelines at all what part of the initialization should be in `build` and what should be in the constructor.
The gist of my comment is that patterns can be useful, but usually they're overused and if you implement one without understanding why and without benefiting from faster understanding the code because the pattern is applied consistently over multiple instances, the result is worse than just implementing what you need in a readable way (YAGNI).
Comment by layer8 22 hours ago
The point of design patterns is less about the individual patterns, than about having "design pattern" as a general concept of coding patterns relevant to software design, that you name and describe because they keep reoccurring.
Comment by zeroq 22 hours ago
For me design patterns are more of vocabulary than a tool.
It's not about - hey I found this book and we'll be using these building block from now on - rather, it's about having words that everyone immediately recognizes and associate with exact same ideas.
Comment by naasking 20 hours ago
Comment by moron4hire 18 hours ago
Comment by no_wizard 16 hours ago
There's a couple really well documented and understood ways of doing this in the language. I'm not sure what you're specifically referencing without more information.
>I wouldn't so much as call what JS does "reflection" any more than "making objects out of poorly implemented hashmaps."
Is this anymore different than .NET deriving everything from a base `System.Object`[0] type?
Also, what is missing in JS reflection wise that you can't do that would make sense for its environment? (namely, this excludes compile time reflection stuff I know .NET can do, it wouldn't make sense for a scripting language as it currently is)
[0]: https://learn.microsoft.com/en-us/dotnet/api/system.object?v...
Comment by moron4hire 15 hours ago
But that actually tells you very little. You might be able to tell that it takes a certain number of parameters, if you are running on a system that implements Function.prototype.length. But you will have no way of telling what the arguments to those parameters should be, or even what they were even named. There's no way to tell if the function is a method that needs to be `.call()`ed with a value for "this", or if it's just a function that happens to live in an object literal, or if it's actually a class constructor that must be called with `new`! And there is certainly no way to tell whether the function returns a value, say nothing about the type of value it returns.
With .NET reflection, I can do ask those things I lament missing in JS, and guarantee the type safeness of it.
Comment by matheusmoreira 12 hours ago
Comment by moron4hire 11 hours ago
Comment by actionfromafar 17 hours ago
Comment by socalgal2 15 hours ago
Most lisp programs are about writing DSLs using defmacro.
What's the similarity to lisp except that both are programming languages?
Comment by actionfromafar 13 hours ago
Comment by moron4hire 17 hours ago
And there are many other such features that were once unique/unique-ish to Lisp, that were major selling points for using Lisp at the time, but are now pretty common across a very diverse set of languages. Garbage collection being one. Higher order functions being another.
Lisp's big idea that stuck to being unique to Lisp is homoiconicity. It's the one thing that continues to be valuable enough to warrant using Lisp, despite everything else that has been stolen and copied.
Of course, not that I ever used Common Lisp, and not that I use Racket anymore. I enjoyed the hell out of programming in Racket. Up until the point I needed to access a database. Man, who's got time for that Jankasarous Rex? But I really would love a homoiconic language for the .NET CLR. That would be pretty sweet.
Comment by actionfromafar 13 hours ago
Comment by skydhash 1 day ago
Comment by ssrc 20 hours ago
Funny thing, Peter Norvig also has this position, that patterns only apply to languages like Java, but his book on Lisp and the Python course he had on Udemy (?) are super-pattern-y.
Comment by liampulles 7 hours ago
Java is kind of "begging" for patterns IMO, with all its static package protected final stuff and beliefs around encapsulation. Go is plainer, which is to its benefit.
Comment by mrsmrtss 17 hours ago
Comment by richardlblair 23 hours ago
Comment by jonkoops 1 day ago
Comment by threetonesun 22 hours ago
Comment by arscan 19 hours ago
Comment by gcau 17 hours ago
Comment by kbolino 14 hours ago
Comment by arscan 11 hours ago
Comment by threetonesun 13 hours ago
Comment by thunderfork 11 hours ago
Comment by daxfohl 20 hours ago
And that's all before new requirements that break the pattern, or other engineers that don't have time to grok the design and hack in something that looks like a switch block for their thing, which eventually takes over most of the code anyway.
Comment by ozim 18 hours ago
Parent comment is not like that.
Comment by khannn 18 hours ago
Comment by baq 1 day ago
e.g. observer pattern in java is what, [array of functions].forEach() in js? not worth calling that by name. another example, singletons - in Python, it's just a module (caveats apply obviously, but if we apply them, some also apply in java).
this is why designing a minimal language to make it 'simple' is misguided: you'll end up having to reinvent the design pattern language anyway. there are good reasons to design a simple language, but simple for the sake of simple is missing the point.
Comment by nl 1 day ago
Almost 20 years ago.. damn.
https://creativecommons.org/2006/02/14/yahoodesignpatternlib...
https://web.archive.org/web/20060221111812/http://developer....
They had a great comparison of the different behaviors leaderboards could encourage in users.
Comment by culi 1 day ago
Comment by paulirish 1 day ago
Comment by 101008 1 day ago
Comment by no_wizard 1 day ago
Comment by cachius 22 hours ago
Short history lesson:
https://medium.com/hackernoon/the-rise-and-fall-of-ext-js-c9...
In August 2006, a guy by the name of Jack Slocum (now CEO of Alta5) began to blog of his experiments with YUI. Over time, these experiments became more complex and Jack would start to bundle them into what would later be named YUI-ext (Yahoo UI extensions) — the precursor to Ext JS (Extensible JavaScript).
Jack Slocum’s blog was used to communicate his vision for YUI-ext and garnered community support from around the world. The release of the Grid component for YUI-ext would forever change the trajectory of the library and the community as the GridPanel would become the core UI component for many applications to come.
Throughout its early life, Jack continued to build upon YUI-ext by adding features to the framework, such as animations, Modals, Tab Panel, Resizable elements and a layout manager that greatly expanded upon the YUI framework. These components would seldom extend the YUI library and had their own rendering functions.
YUI-ext created a foundation for web programmers unlike anything the world had seen before and many developers flocked to the framework and invested in the newly formed community. The net result was the explosive expansion of YUI-ext.
From YUI-ext to Ext JS In January 2007 we found Jack extremely busy to push out YUI-ext 0.40 and it is this version where we find the namespace of the framework change from YAHOO.ext to a much simpler Ext (pronounced “ekst J S” or “E-X-T J S” by some of us old-school community members).
February 2007, Ext JS 1.0 was being developed in tandem with a new website, ExtJS.com. In April 2007, the launch of ExtJS.com was announced to the community along with the release of Ext JS 1.0.
https://web.archive.org/web/20230222210535/https://jackslocu...
For those that don’t know, Ext JS was one of the first JavaScript frameworks in the early days of Web 2.0. It was the first framework to offer a complete package of everything needed to build full-fledged applications using just JavaScript in a web browser. At one point, it was used by over 2 million developers worldwide, 70% of the fortune 500, and 8 of the top 10 financial institutions. It was years ahead of everyone else, open source, and had an incredible community of passionate people contributing to its success.
As that success grew, so did the number of copycat competitors. They eventually started taking the code and assets and embedding them into their own frameworks. Adobe embedded it in Cold Fusion and other competitive frameworks followed their lead without any contribution to the framework or community.
At the time the thought of competing directly against a behemoth like Adobe was scary. How could they take our product and offer it as their own? I took what I thought was the right action to “protect” Ext JS from being “stolen” by changing to a more restrictive license. That was a huge mistake.
Looking back in hindsight, without the fear, I have a much clearer picture. I see what truly made Ext JS great was not the code - it was all the people who loved, contributed and supported it. As we worked on making our own dreams a reality, we helped others do the same, sharing our knowledge, code, and solving tough challenges together.
That is what really mattered — our community. That is what I should have protected, not the code. You were my closest friends. I am sorry I changed the license after we all came to an agreement on the first license. That was a breach of integrity and you deserved better. I would do it differently if I could.
Comment by dahcryn 1 day ago
Comment by dimaor 1 day ago
Comment by 8cvor6j844qw_d6 1 day ago
Anyone has other sites like these to share?
- Domain-driven design, design patterns, and antipatterns
- Refactoring and Design Patterns
- Standard Patterns in Choice-Based Games
https://heterogenoustasks.wordpress.com/2015/01/26/standard-...
Comment by culi 1 day ago
Great meta resource for building UI components.
Comment by sdovan1 1 day ago
Comment by elktown 1 day ago
Comment by gopher_space 19 hours ago
Comment by crabmusket 1 day ago
https://learn.microsoft.com/en-us/azure/architecture/pattern...
Comment by esfandia 1 day ago
Comment by bbminner 1 day ago
Comment by rambleraptor 1 day ago
Comment by JimDabell 1 day ago
Comment by rambleraptor 1 day ago
Comment by culi 1 day ago
Comment by slig 19 hours ago
Comment by endymion-light 1 day ago
Comment by begueradj 1 day ago
Comment by socketcluster 1 day ago
Juniors often think that learning design patterns is some kind of career hack which will allow them to skip ahead a decade of experience... There is some utility in many design patterns but the problem is that juniors often miss the nuance and the motivation behind the patterns and they tend to misuse them; often creating more complexity than they would have created had they not used design patterns.
There are situations where design patterns may be useful but they're much more rare than most people think. A lot of juniors seem to think that every problem requires them to apply a design pattern from their toolbox. They try to frame every problem within the constraints of design patterns that they know. This can create problems.
In fact, there are many coding patterns which are far simpler than 'design patterns' and much more useful, but nobody talks about them because they're too trivial to discuss. For example, I've seen people write code which relies heavily on design patterns but then that same code uses an O(n^2) nested loop to find items that are common between two arrays. There is a simple 'pattern' you can use to store the items of the first array in a Set or HashMap and then finding common items is O(n) because Set and HashMap lookups are O(1)... Very useful pattern but I don't believe it has a name. I use it literally ALL the time. The idea of storing intermediate state in some kind of HashMap is a game-changer IMO but there's no name for that pattern of coding. In general, knowing what data structure is most appropriate for various scenarios is a game changer... But still, don't abuse. Basic data structures like arrays are fine most of the time.
Anyway, it's good to absorb the wisdom behind some design patterns but you should not try to fit every problem to them and dont say stuff like "For this problem, I applied Design Pattern X" - If you do, senior engineers will know you're a junior. If you use a design pattern correctly, it will probably not look exactly like in the textbook. It's kind of hard to give it a name. It may be a mix of patterns. It's the principle that counts. Reality is too complex for rigid design patterns.
On the other hand, some design patterns are too common and obvious to deserve a name. For example, the factory pattern is super common... I use it all the time but it's so basic and obvious that I will sound like a total noob if I go around calling my function "socket factory pattern"... I will call it "Utility function to obtain a socket" or something. I will never refer to it as a factory pattern, it's a bit cringe.
Comment by palata 1 day ago
Just like we have words for a nail, a screw, a hammer. If you had to say "I used a tool that I find works well with nails", that would be annoying and ambiguous.
Now of course, if you quickly screwed something with your swiss-army knife and a junior came and told you that this is wrong, because you should always use a proper screwdriver, and therefore you should rent a car and drive 30min to go buy it right now, you would kindly tell them to fuck off. Doesn't mean that there is no value in the concept of a screwdriver itself.
Comment by Yokohiii 1 day ago
The thought model complicates the process of writing new code, "what pattern do i need here?" and the perception of existing code, "oh this is pattern X, why isn't that communicated clearly?". The truth is that design patterns are at best stagnant in quality and quantity over time (GoF is over 30 years old!), but the quantity and quality of problems is infinite.
I've thought in patterns quite some time in my early career. With my colleague back then everything was an pattern and we were kind of in sync with that approach. But it quickly falls apart if you have peers that are less try hard on it. You can spend days, weeks, months to study design patterns and then have to explain it to someone in 5 minutes that simply doesn't care. I can't blame anyone to not care, so that has to be accounted for.
I think the common language argument is tempting, but also too stressed. Good and useful programming knowledge is bound by reality. An integer is a indisputable thing that is always useful. A "singleton" is just a fancy rephrasing of "global state".
Comment by palata 22 hours ago
Say I build a tool that makes it easier for me to drive a nail and call it a "Naildriver". If I show it to a colleague, they may be able to tell me "oh, this is generally called a hammer!". Maybe they will even tell me how I may improve my hammer, because they happen to like to learn about hammers in their free time. Or maybe now that they said it's a known concept, I will enjoy reading about hammers online (doesn't mean I will now read the entire encyclopedia of tools).
The fact that there is a name for the concept ("it's called a hammer") does not say you have to know the word. It's just useful to have a word for it, because then we can reference it in discussions and share knowledge about it more easily.
Comment by berkes 21 hours ago
To keep in your analogy, if you have a 3KG naildriver with a 2m handle you'll quickly find out that driving nails into a drywall with that leaves you with no wall. And that it's a bad idea to use a "Naildriver" to drive these "spiralled-slothead-nails" (aka screws) into wood.
But with a common language, such as design patterns, you can easily learn where they are good, what their limits are, in what cases other patterns fit better, and what pitfalls to avoid and so on.
If I search the web for "why is it so hard for my naildriver to drive in spiralled-slothead-nails" I'll get zero results. But when I search for "why is it hard to hammer in a screw" I'll get good results. May sound like a silly example, but for me that sillyness illustrates how obvious designpatters should be.
Comment by palata 21 hours ago
And it doesn't mean at all that everybody should learn the whole encyclopedia of tools by heart. But having it formalised somewhere is useful: as soon as someone tells me "what you're trying to do sounds like this design pattern", I can start searching and reading about it.
Of course if that someone tells me "you suck, you should know that there is a design pattern for that because you should read about design patterns every night before you go to sleep", it will be different :-).
Comment by Yokohiii 18 hours ago
I think Julian Assange once said he would refer to things in discussion just as "Tomato" (or similar), in discussion to have a shortcut for something unnamed with some meaning. We do this all day in programming, we give a complex component a name and it means a lot more then just the actual word. The problem is that this specific meaning is often not universal, it's contextual.
If you take a hammer, an integer and design patterns, the latter is the least universal thing. They depend on domain, context and conventions, and can change quite a lot depending on the language. Removing hammers and integers from the world would cause collapse, removing design patterns would do almost nothing.
I guess the active celebration of design patterns as a catalogue of general wisdom is my primary issue here. I'd welcome any project/team/company that maintains a catalogue of their individual "patterns". But a universal source of truth has too much bible flavor to me. (Oh it also dictates OOP by default which renders it's inherent "wisdom" completely useless in many languages)
Comment by palata 14 hours ago
But formalising concepts with words makes sense. If your company maintains a catalogue of their patterns, and someone happens to know that this specific pattern is usually called a "singleton", I would find it weird to call it a tomato.
Some patterns have different names in different contexts or languages, and that's fine. I don't find it weird to have a discussion around "in this language there is this pattern that they call X, does that ring a bell for you working on that other language? The idea is [...]", and maybe the answer is "yep we have it too" or "oh, we call that Y, but that's pretty similar".
Comment by Yokohiii 12 hours ago
Comment by palata 6 hours ago
I've had some debates with junior devs who really wanted to enforce their newly-learned patterns, and my experience there is that passed a certain point, there is no convincing anymore: if they really insist about overengineering something with their newly-learned concept and the hierarchy doesn't allow me to prevent them from doing it, anyway they will do it. So instead of fighting I just let them, and if it turns out to be a waste of time in the end... well that's not my problem: I was not in a position to prevent it in the first place.
It's not only patterns though: some juniors have a way to try to use every exciting framework or library or tool they just discovered.
Comment by Izkata 1 day ago
This is a "hash join" in relational databases. You can see it in the query planner output of at least postgres.
Comment by viraptor 1 day ago
There are two cases that are unique though: state machines and visitors are so much things on their own, that you'll use those names almost every time you run into the pattern.
Comment by microtherion 1 day ago
Yes, but what about factory factories? https://factoryfactoryfactory.net
Comment by zelphirkalt 19 hours ago
The magical "visitor" pattern becomes nothing more than simple callback passing or passing a function, which is one of the most natural things to do in a modern programming language.
State machines at least are useful as a conceptual thing, to find a way to think about how one solves a problem, no matter how they are ultimately implemented in the end.
Comment by vips7L 17 hours ago
Comment by zelphirkalt 11 hours ago
Comment by TINJ 1 day ago
Isn't this called 'dynamic programming'? It's actually a habit people should pick up when grinding leetcode.
Comment by viraptor 1 day ago
Comment by arethuza 22 hours ago
Comment by zelphirkalt 19 hours ago
Comment by svilen_dobrev 1 day ago
But anyway, this site seems javascript/frontend wanna-bees oriented.. please don't take those tutorials as mantras-to-follow-at-any-rate. See if you can take the knowledge and move on.
A very good book, besides the GoF one, is the "Organisational patterns book by James Coplien, Neil Harrison" [1]. It contains some of the GoF *plus* all the non-technical ones, and they are bundled together - as software making is not just the coding.. i have the list of those patterns essences (patlets) extracted, here the link - https://www.svilendobrev.com/rabota/orgpat/OrgPatterns-patle...
edit: it's from ~2003-5 and images are missing. May need to scan them from the book. Closest i found is [2], at least to get some idea
[1] http://www.amazon.com/exec/obidos/tg/detail/-/0131467409/
[2] https://www.scrumbook.org/book-outline/history-of-the-patter...
Comment by DHRicoF 1 day ago
I have to touch some of the most unnerving modules in a legacy project and everything is a trap. Lot's of similar repeated code with ugly patterns and some big brain trying to hide the ugliness with layers and layers of indirections and inheritance, and calling it clean because there is a factory class. The biggest joke? each implementation have a different interface for key methods, so later you to check what instance got created.
I want to keel myself. Anyone could assist me in a seppuku?
Comment by sureglymop 19 hours ago
Comment by agumonkey 1 day ago
Comment by zelphirkalt 19 hours ago
We need to keep in mind, that the most composable concept in computer programming is the pure function (or maybe a mathematical "relation", if we want to abstract further). Not a mutating object. Not some constellation of objects that constitutes a pattern. Those are merely special cases.
I am currently developing a GUI application. Most of the classes in my code are classes, that are custom widgets. The GUI framework is OOP, so that is kind of infectious for the rest of the code. Still I try to keep some stuff separately as pure functions. Probably will outsource more stuff like that into completely self sufficient functions. The only pattern I have so far in the whole application, is a mediator, which I use as a way to have objects register themselves as listeners to specific events and for other objects to send these events to anyone who will listen. That way objects don't need to know, which other objects are interested in learning about some event. Could I have built in some factories and whatnot? Surely I could have, but there would have been very little, if any benefit. Even the mediator only exists, because the GUI framework does not have a way to send events that include data, so I need a way to do that. Otherwise I could even get rid of that pattern as well.
In this way pattern are useful for when you really need them, but these OOP pattern by themselves, without context, don't really have a value. No code becomes better by building in more patterns, unless the situation requires such a solution.
Comment by Jaxan 1 day ago
This is an instance of “use the right data structure for the job”. To me it has little to do with architectural design (where design patterns live), but it has to do with algorithmic design.
Comment by spopejoy 12 hours ago
Comment by zwnow 1 day ago
Comment by hyfgfh 1 day ago
Even some principles aren't known. I always recommend the book Head First: Design Patterns. It's in Java, but the lessons can be applied in every language.
Unfortunately, we are in a 'post-knowledge' era... I don't know how we can keep things up at this pace.
Comment by davidkunz 1 day ago
I can only discourage anyone from applying Java patterns all over the place. One example in JavaScript: There was a functionality that required some parameters with default values. The plain solution would have been:
function doStuff({ x = 9, y = 10 } = {}) { ... }
Instead, they created a class with private properties and used the builder pattern to set them. Totally unnecessary.Comment by Kwpolska 1 day ago
Design patterns cannot be applied in every language. While some patterns are applicable everywhere, many of them provide replacements for missing language features. For example, the Builder pattern is not very useful in languages with default parameters and named arguments.
Comment by microtherion 1 day ago
Builder is extremely useful to pair with a parser, e.g. SAX. The parser parses the input, and the builder then decides what to do with it.
Comment by Kwpolska 20 hours ago
Let’s remove the category argument and you get this:
Post post = new Post.Builder()
.title("Java Builder Pattern")
.text("Explaining how to implement the Builder Pattern in Java")
.build();
This builder is a more readable alternative to this: Post post = new Post("Java Builder Pattern", "Explaining how to implement the Builder Pattern in Java", null);
But if Java supported named arguments and default values (the default would be null), this could just be: Post post = new Post(title: "Java Builder Pattern", text: "Explaining how to implement the Builder Pattern in Java");Comment by vips7L 16 hours ago
Comment by prodigycorp 1 day ago
It definitely biases how people evaluate llms. Many cite Claude as their favorite llm for generating frontend code, but I suspect that many people prefer it because the output is prettier, rather than better composed.
Comment by signal11 1 day ago
In a world with only assembly language, for instance, it’s a bit like making a big deal about a “guarded repetition” pattern (aka a while loop).
Eg in Lisps, a lot of patterns become one-liners. At that point these patterns become a “can you write decent Lisp” question[1].
Comment by noveltyaccount 1 day ago
https://en.wikipedia.org/wiki/Ralph_Johnson_(computer_scient...
Comment by andybak 23 hours ago
https://wiki.c2.com/?AreDesignPatternsMissingLanguageFeature...
https://norvig.com/design-patterns/design-patterns.pdf
https://medium.com/@letsCodeDevelopers/your-design-patterns-...
Comment by crabmusket 1 day ago
In A Pattern Language, each pattern is hyperlinked to other patterns in a kind of hierarchy, where larger patterns (like "house cluster") are broken down into smaller constituent parts ("main entrance") all the way to quite granular details ("low doorway").
This is because you can't just take a pattern on its own; it forms part of a larger whole.
Tech pattern books often focus on small recurring structures (e.g. "command pattern" from this site), but not how they help create some larger pattern, or in the other direction, what are the smaller patterns that help create them.
This sounds like a lot of hard work of course, which is why people don't do it.* I would love to see this accomplished though. If only I had an extra 36 hours in each day.
One thing that A Pattern Language is also great at is motivating each pattern with a specific problem or symptom. This site seems to do a decent job at that, though some problems seem... kind of weakly motivated. For example, the above mentioned "command pattern" is motivated by "what if we need to rename a method?" which... is pretty weak tbh.
*EDIT: also because fitting patterns into a whole, maybe unavoidably, will promote a perspective, or a way of building a whole system. A pattern book for web applications written from an HTMX point of view would be a very different book to one written from a React slant. Maybe one pattern language can accommodate both sets of technologies, or maybe not.
Comment by spopejoy 12 hours ago
Comment by crabmusket 11 hours ago
Comment by crabmusket 1 day ago
---
Short Passages (132)
[Context, or pre-links]
The Flow Through Rooms (131) describes the generosity of light and movement in the way that rooms connect to one another and recommends against the use of passages. But when there has to be a passage in an office or a house and when it is too small to be a Building Thoroughfare (101), it must be treated very specially, as if it were itself a room. This pattern gives the character of these smallest passages, and so completes the circulation system laid down by Circulation Realms (98) and Building Thoroughfare (101) and The Flow Through Rooms (131).
[Problem statement]
Long, sterile corridors set the scene for everything bad about modern architecture. In fact, the ugly long repetitive corridors of the machine age have so far infected the word "corridor" that it is hard to imagine that a corridor could ever be a place of beauty, a moment in your passage from room to room, which means as much as all the moments you spend in the rooms themselves.
[Pattern contents here]
[Pattern summary]
Keep passages short. Make them as much like rooms as possible, with carpets or wood on the floor, furniture, bookshelves, beautiful windows. Make them generous in shape, and always give them plenty of light; the best corridors and passages of all are those which have windows along an entire wall.
[Elaboration, or post-links]
Put in windows, bookshelves, and furnishings to make them as much like actual rooms as possible, with alcoves, seats along the edge - Light on Two Sides of Every Room (159), Alcoves (179), Window Place (180), Thick Walls (197), Closets Between Rooms (198); open up the long side into the garden or out onto balconies - Outdoor Room (163), Gallery Surround (166), Low Sill (222). Make interior windows between the passage and the rooms which open off it - Interior Windows(194), Solid Doors With Glass(237). And finally, for the shape of the passages, in detail, start with The Shape of Indoor Space (191)
Comment by phplovesong 1 day ago
Comment by z3t4 1 day ago
Comment by oleggromov 1 day ago
Comment by FieryMechanic 1 day ago
Comment by android521 1 day ago
Module Pattern
Factory Pattern (factory functions)
Mediator / Middleware Pattern (as function pipelines)
Hooks Pattern (custom hooks, generalized)
Container / Presentational Pattern (implemented with function components + hooks)
Everything else is either neutral, UI-only, or fights POSD (Singleton, Mixin, etc.).
Patterns from that page you should treat skeptically for POSD
From Patterns.dev, for your POSD-style codebase I’d avoid or downplay:
Singleton Pattern → encourages global state and tight coupling. Patterns
Mixin Pattern → tends to increase interface surface and make dependencies opaque. Patterns
Observer Pattern → powerful, but event-based wiring can obscure data flow and increase “system complexity” (classic POSD warning). Patterns
Comment by neogodless 1 day ago
Comment by jakubmazanec 1 day ago
Comment by culi 1 day ago
Comment by fiddlerwoaroof 1 day ago
Comment by HumanOstrich 1 day ago
In spite of that, there are plenty of reasonable use cases for singletons in many languages, including JavaScript. For example, ES Modules are effectively singletons. If you import the same module in multiple places, it only gets evaluated once.
Let's not turn the singleton pattern into forbidden knowledge.
[1]: https://www.patterns.dev/vanilla/singleton-pattern/#tradeoff...
Comment by deaux 1 day ago
Comment by dkersten 1 day ago
Worse is that singletons enfurece a single instance which is almost always unnecessary. It’s trivial to only create as many instances as you need.
Comment by hokumguru 1 day ago
I think people just don’t like Singletons because they’ve been especially misused in the past but I guarantee the same argument stands for any other design pattern.
Comment by gm678 1 day ago
Comment by css_apologist 23 hours ago
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.
Comment by dominicrose 22 hours ago
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.
Comment by css_apologist 20 hours ago
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
Comment by css_apologist 23 hours ago
Comment by rswail 1 day ago
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.
Comment by pedrozieg 1 day ago
Anything that reliably shortens that loop is “good tech,” even if it’s ugly, uncool, or built on last decade’s stack.
Comment by HumanOstrich 1 day ago
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.
Comment by songodongo 1 day ago
Comment by KPGv2 1 day ago
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.
Comment by HumanOstrich 1 day ago
> 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.
Comment by seabass 1 day ago
Comment by seabass 1 day ago
Comment by verdverm 18 hours ago
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
Comment by wavemode 1 day ago
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.
Comment by lock1 1 day ago
Personally, I prefer to learn FP patterns, which tend to be backed with nice mathematical properties behind them.
Comment by bingemaker 1 day ago
Comment by css_apologist 23 hours ago
see the prototype, and observable pattern
they explain the basic concept, but in the only way you would never use it in real life
Comment by pajtai 1 day ago
Comment by dkersten 1 day ago
Singletons are just globals with extra steps, and have all the same problems globals have, just people (especially juniors) think they somehow are better.
In reality they’re worse because they conflate global access with enforced single instance. You almost never need to enforce a single instance. If you only want one of something, then create only one. Don’t enforce it unless it’s critical that there’s only one. Loggers are often given as an example of a “good” singleton and yet we often need multiple loggers for things like audit logs, or separating log types.
Instead of singletons, use dependency injection, use context objects, use service locators, or… just use globals and accept that they come with downsides instead of hiding behind the false sense of code quality that is a singleton.
Comment by tigrezno 21 hours ago
Comment by Simplita 1 day ago
Comment by bmiekre 22 hours ago
Comment by sh4rks 1 day ago
Comment by kaycey2022 22 hours ago
Comment by 1970-01-01 1 day ago
Comment by akst 1 day ago
I understand you can override modules in tests, and if you have a version of your app that runs in a different environment where you might replace a HTTP service with a different variant (like if an RPC service that normally performs HTTP requests, but in one case maybe you want to talk to specific process, worker or window using message passing).
I really really feel using constructor args is just a lot simpler in most cases. But I think there's a reason why people don't always do this:
1. Sometimes someone is using a framework that imposes a high level of inversion of control where you don't get to control how your dependencies are initialised.
2. (this was me when I was much younger) Someone dogmatically avoided using classes and thought they could get away with just data and functions, and then they realise there is some value in some shared instance of something and then they just undermine any functional purity. Don't get me wrong, functional purity is great, but there are parts of your apps that just aren't going to be functionally pure. And you don't need to go full OOP when you use classes.
----------------------------------------
Here are some examples of what I mean.
Here's one example, where I have an app defined in web components and I define the components for each part of the app before passing them into the skeleton. It's a more simple app and I avoid some shared state by different landmark components communicating by events.
https://github.com/AKST/analysis-notebook/blob/b3f082fc63c9b...
----------------------------------------
Here's another example, this app is built of multiple command line instructions that sometimes have their own version of services (singletons) with specific configuration, sometimes they are initialised in child processes.
https://github.com/AKST/Aus-Land-Data-ETL/blob/672280a8ded69...
Because this app is doing a lot of scrapeing and I wanted to also child worker processes to do their own HTTP I was going to make a variant of my HTTP service which talked to a daemon process that tracked state for open connections to specific domains to avoid opening too many simultaneously and getting blocked by that host.
Updating the code that uses HTTP will be effortless, because it will continue to conform to the same API. I know this because I've already done this multiple times with HTTP scrapping in the app.
https://github.com/AKST/Aus-Land-Data-ETL/blob/672280a8ded69...
Comment by vivzkestrel 1 day ago