Top
Best
New

Posted by handfuloflight 3 days ago

Patterns.dev(www.patterns.dev)
621 points | 150 comments
emaro 3 days ago|
Design patterns can be really helpful. In my previous job I worked on enterprise .NET applications. It made sense to use common patterns, because most applications were big and the patterns made it easier to understand unfamiliar code, within an application but also across different teams and applications. New projects looked familiar, because the same style and the same patterns were used.

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).

layer8 3 days ago||
I would put it slightly differently: Patterns (including anti-patterns) happen whether you call them such or not. Any developer will sooner or later come up with patterns like Adapter or Builder or Composite or Iterator. In that sense, patterns are not invented, but discovered. The benefit of design patterns is to be able to communicate these discovered patterns, and to define agreed names for them, so that you don't have to describe the pattern each time you talk to another developer, but can refer to it by a well-understood name. (Or when not yet well-understood, can refer to the corresponding pattern description.) It extends the language we use to talk about software design.

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.

zeroq 3 days ago|||
I would go even further.

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.

naasking 3 days ago|||
Yes and no. Some patterns exist because the language isn't expressive enough. This is one reason why the patterns made sense in the OP's .NET programs, but made less sense in JS. JS simply doesn't require as much ceremony for some things because it's dynamically typed and reflection kind of comes for free.
moron4hire 3 days ago||
I would say that reflection in JS is terrible compared to .NET. You can only just barely figure out what is in an object, but it's a hell of a time figuring out what any of those things can do. I wouldn't so much as call what JS does "reflection" any more than "making objects out of poorly implemented hashmaps."
no_wizard 3 days ago|||
>You can only just barely figure out what is in an object

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...

moron4hire 3 days ago||
In JavaScript, one can tell if an object has a method by iterating over the object keys and seeing if the value is `instanceof Function`.

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.

matheusmoreira 2 days ago||
Isn't this just a fundamental limitation of dynamic typing?
moron4hire 2 days ago||
Most of it is not. Most of the data necessary to support reflection should be available to the runtime or else it wouldn't be able to operate. The runtime is parsing the syntax of the function, it should be able to tell if all exit conditions have a return of any kind. It should be able to tell me at least the names of the parameters. It should know if a function is bound to a "this", or of it's a constructor. It just doesn't give any way to tell me.
naasking 2 days ago||||
> I wouldn't so much as call what JS does "reflection" any more than "making objects out of poorly implemented hashmaps."

I used "reflection" because that's how it's abstracted in popular statically typed languages. My point was that JS has abstractions and idioms that eliminate some of the need for design patterns like, factory, decorator, strategy, etc., and some of the reasons are because JS's core objects are basically just fancy hashmaps.

actionfromafar 3 days ago|||
"Javascript" === "Chaotic neutral lisp"
moron4hire 3 days ago|||
Yeah, I don't like the comparisons of JS to Lisp, because I think they mostly center on the existance of the map and filter methods of Array. To me, that's just not what Lisp is about. C# has map/filter/etc, and we don't say C# is-a Lisp.

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.

actionfromafar 3 days ago||
Well put.
socalgal2 3 days ago|||
lisp to me is (1) the language itself is a lists of lists (2) defmacro lets you manipulate those lists of list at compile time. JS doesn't this do either of these at all AFAICT and so is absolutely nothing like lisp.

Most lisp programs are about writing DSLs using defmacro.

What's the similarity to lisp except that both are programming languages?

actionfromafar 3 days ago||
Let me ask you instead, do you consider there to exist any Lisp which has no compiler?
skydhash 3 days ago|||
A lot of patterns only make sense in languages like C# or Java, which are inflexible by design. You have two hierarchical trees (inheritance and namespaces) that you have to work around. With something simpler like C, Go, JavaScript, you don’t have those obstacles and a solution can be way simpler to implement.
ssrc 3 days ago|||
Some patterns in the GoF book only apply to C++/Java as they were in 1994, but I don't see any reason why other languages would have no useful patterns. The Linux kernel (C) is full of patterns for example.

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.

liampulles 2 days ago||||
I went from Java to Go for my last job. I think there is a reduction in pattern stuff but there are still many (at least in my project).

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.

mrsmrtss 3 days ago||||
How do optional inheritance and namespaces (which you can ignore to use a single global namespace) make a language inflexible? If anything, these traits make your language more powerful, not less.
richardlblair 3 days ago|||
Somewhat true - I usually find that in these languages the patterns are there they are just less obvious.
jonkoops 3 days ago|||
This is a common thing I see when developers that come from an OOP enterprise environment familiar with Java, C#, etc. do JavaScript, they try to use all the same patterns, default to classes for everything. It just doesn't fit the language.
threetonesun 3 days ago||
It was fascinating to me to see JavaScript add the class keyword, have it be widely adopted thanks to React, then just a few years later seeing `class` in JavaScript code is, as you said, a clear sign a Java/C# dev was here.
arscan 3 days ago||
I haven’t done JavaScript in a long while, is using ‘class’ not a favored way of writing JS these days? I wrote JS heavily pre-class, and never really got comfortable using it before switching my focus to other languages.
gcau 3 days ago||
The poster you're replying to is plain wrong, using "class" is ubiquitously common in the javascript/typescript world, it's the idiomatic way to create classes, and it has better semantics than trying to use prototypes. You might compile away the class keyword for compatibility, though.
kbolino 3 days ago|||
But you don't have to do either of those things. There's a third way, with functions and bare objects. I'm not sure that's what GP meant, but a lot of the JS I've written (which tends to be for the browser, mostly vanilla, and quick-and-dirty, to be fair) never touches classes or prototypes. The JSON data being produced/consumed is just a bag of fields, the operations on the document are just top-level functions, events get handled in callback closures, responses to HTTP requests get handled with promises, etc. Sprinkle in some JSDoc comments and you even get fairly workable autocomplete suggestions. Of course, the web APIs are built on prototypes/classes, so it's not like they're totally absent. But with things like data attributes, querySelector, and HTML templates, the usual needs for my own code to be OOP (or even structs-with-methods a la Go/Rust) just don't emerge that much.
arscan 2 days ago||
Yeah, I would do a lot with plain objects, and using closures and iifes to do encapsulation and what-not. It was ugly and a bit of a pain, but once you learned how it all worked it made sense and was doable. I felt that classes were a bit of a bolt-on that violated my own internal understanding of how JavaScript worked, but by that point I was moving on to other stuff so never really got used to it.
threetonesun 3 days ago||||
I'm not denying the existence of class in JavaScript, but at least from what I've seen when React went to functions so did most of the JavaScript community that had moved to class based syntax, except for those who worked with Java/C# as well.
thunderfork 2 days ago|||
I think the real sign of this is a class where all the members are static, or pure data classes - ie, classes as a default rather than classes for things where classes make sense
ozim 3 days ago|||
I see a lot of comments about how patterns are useless from people writing toy apps or at least ones that never had to deal with really enterprise scale stuff. So for me they are like people building a shed screaming at people building sky scrapers that no one ever needs to pour so much concrete to form a foundation.

Parent comment is not like that.

daxfohl 3 days ago|||
Yeah, I've seen (okay, and been responsible for) a lot of "the road to hell is paved with good intentions" due to jumping to some pattern or other because, well, it feels like the right thing to do. It makes the code cleaner at delivery time, and is usually very intuitive when the design is fresh in your mind. But IME it doesn't take long before that freshness goes away, and the next time you look at it (let alone anyone else) you find it hard to follow the logic anymore. Usually "constructing" the pattern and "executing" the pattern are in different places in the code, and there's not a straightforward way to mentally step through one without continually cross-referencing the other. At some point you wish you'd just written one long switch block that you could step through.

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.

khannn 3 days ago|||
People were shifted from Java to Javascript and kept the Java patterns and maybe the organization had standards requiring their use.
baq 3 days ago||
design patterns are a language, it's just that the programming language they're being implemented in doesn't support them natively.

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.

nl 3 days ago||
Does anyone remember the Yahoo design patterns library? It was mostly for UX pattern (eg: ways to "Rate an object") and it was really good.

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.

culi 3 days ago||
Not quite the same thing, but there's this incredible (open source) project called The Component Gallery that is basically just a repository of UI components across 93 (currently) different design systems. It's an incredible resource if you're building a component from scratch and either want some design inspo or technical advice. Many of the design systems have thorough guidelines for a11y/ARIA best practices that I've learned a ton from

https://component.gallery/

paulirish 3 days ago|||
Amen! The terms "accordion" and "carousel" were really codified by the pattern library. Establishing a common vernacular definitely accelerates things.
101008 3 days ago|||
Oh, the second link is amazing. I love the old web, and that brought a lot of nostalgia.
no_wizard 3 days ago|||
YUI was ahead of its time as well
cachius 3 days ago|||
And it spawned ExtJS. Which could have been React, but they messed up. Literally they built a faster Facebook app 'Fastbook' in 2012.

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.

dahcryn 3 days ago|||
we often forget how great Yahoo engineering was back in the day, sad it was destroyed by bad management and horrible business cases prioritization
dimaor 3 days ago||
for some reason I remember him being related to YUI, but I learned JS from Douglas Crockford, one of the best lectures from the old days of JS.
8cvor6j844qw_d6 3 days ago||
Looks great, time to add it to my bookmarks.

Anyone has other sites like these to share?

- Domain-driven design, design patterns, and antipatterns

https://deviq.com/

- Refactoring and Design Patterns

https://refactoring.guru/

- Standard Patterns in Choice-Based Games

https://heterogenoustasks.wordpress.com/2015/01/26/standard-...

culi 3 days ago||
I posted this elsewhere in this thread:

https://component.gallery/

Great meta resource for building UI components.

lelandfe 3 days ago||
Design patterns and component libraries are a bit related but they're pretty different concerns ultimately.
culi 3 days ago||
It's more of a meta resource. Many of these design guidelines go in depth on accessibility best practices and UI patterns
sdovan1 3 days ago|||
- Java Design Patterns

https://java-design-patterns.com/

vips7L 3 days ago||
Love how you were downvoted for mentioning Java.
mdhb 3 days ago||
The JS community is so freaking strange sometimes.
elktown 3 days ago|||
Here be dragons. People trying to pattern-match their problems to design patterns can waste a lot of time and effort over many years. Use responsibly.
gopher_space 3 days ago||
To your point, everything we do is context-sensitive and patterns are revealed by abstracting context.
crabmusket 3 days ago|||
Microsoft's cloud design patterns are quite well-written IMO, if you're into that kind of thing

https://learn.microsoft.com/en-us/azure/architecture/pattern...

esfandia 3 days ago|||
The OG site for patterns is of course the Portland Pattern Repository. I believe Ward Cunningham invented wiki for this purpose initially!

https://c2.com/ppr/

bbminner 3 days ago|||
I think it is difficult to oversell the bob nystrom game patterns book

https://gameprogrammingpatterns.com/contents.html

rambleraptor 3 days ago|||
I’ll make a plug for aep.dev, which is a collection of API design best practices and assorted tooling
JimDabell 3 days ago||
Google has something similar:

https://google.aip.dev

rambleraptor 3 days ago||
AEP began its life as a fork of AIP! We’ve got a bunch of ex-Google folks on the project, including the former API Lead at Google.
culi 3 days ago|||
Oh here's a resource for common "idioms" across programming languages

https://programming-idioms.org/

slig 3 days ago|||
https://www.deceptive.design/
endymion-light 3 days ago|||
+1 for refactoring.guru, find it really useful whenever i want to refactor some pre-existing code. Only wish they had a physical book!
begueradj 3 days ago||
Useful links. Thank you.
socketcluster 3 days ago||
I find that the more senior you become, the less you rely on software design patterns.

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.

palata 3 days ago||
I see it as a common vocabulary to talk about tools. It's simpler to say "I made a singleton" than to describe it.

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.

Yokohiii 3 days ago||
You point out the cultural issue that this creates and sweep it under the rug, violently.

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".

palata 3 days ago|||
I did not mean "everybody has to learn the vocabulary". I meant the opposite, actually: it's fine not to know the word for the tool (I don't enjoy reading about patterns just to learn about patterns, it's not my thing at all).

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.

berkes 3 days ago||
The other thing that design patterns allow, is to learn pitfalls, applications and other attributes about them.

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.

palata 3 days ago||
I totally agree with that!

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 :-).

Yokohiii 3 days ago||
I have mixed feelings about this.

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)

palata 3 days ago||
I feel like we're talking past each other. I tend to agree with you, I don't like having a "bible" and "celebration of design patterns as a catalogue of general wisdom".

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".

Yokohiii 2 days ago||
Well I guess I am not clear enough. Naming stuff is a normal human habit, maybe even why we have language? So we can agree on that, it's helpful. But you say it yourself, a thing is called different in another language, so the thing is bigger then the word. But everyone can handle it better in his own head and in communication with a word for it. I guess my usual grief is that any kind of excessive celebration and ceremony comes down to some kind of brainwash. Which mostly affects newbies and cultists. The article for example isn't overtly critical on singletons, while past design pattern writings often heavily disregarded the use of it. So we don't just always reiterate the good, but also the bad.
palata 2 days ago||
I don't mind the celebration and ceremony as long as they don't bother me personally. I wouldn't fight against the existance of a PatternConf, I just wouldn't go :-).

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.

Yokohiii 2 days ago||
The silly thing is that I've been the same when I started. A high energy kid playing around and celebrating everything fresh and new, with a big ego.

Probably a bad habit trying to stop them, they need to learn walking before they can sprint. The question is always how to put limits on them? I say it's overengineered, they say it's modern code and I am old. So what do you do if they send you a PR that is just plain wrong? I mean it seems like you delay the conflict from upfront design/planning to pull requests.

palata 2 days ago||
I have been in two different situations:

* Functional teams (established companies): enough seniors are here to tell the juniors when they are wrong, and the juniors naturally accept the criticism because it's expected in that environment.

* Dysfunctional teams (startups): most devs are juniors anyway, there is no clear hierarchy, managers are still at their first job so they have never seen a functioning team or had a competent manager themselves.

In the second case, there was absolutely no way I could win an argument: the "high energy kids with big egos" never believed me, I was the "old guy" as you mention. I remember an example where the "kid" failed and gave up with their "right" way after 3 months and I solved it in 3 days, exactly how I had suggested they did it in the first place. Next discussion, nothing had changed, they still knew better.

I can't really blame them, because the whole environment was like this. Everybody was always right, knew better, etc, even though it was their first job.

What I've learned is to protect myself and move away from that. Either by changing job, or by changing project. In startups I have been pretty successful at saying "I can help with this project if we do it this way, but if we do it that way, I can't help and I will work on something else". Of course it meant that I could not work on the most exciting project, but they made a mess out of them, so all in all I feel it was better working on my boring, stable, maintainable components.

rglynn 1 day ago|||
> 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 think once you have spent enough time in a software space, nothing is really new under the sun. That's why I think the GoF has aged well (controversial opinion I know!).

Izkata 3 days ago|||
> 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.

This is a "hash join" in relational databases. You can see it in the query planner output of at least postgres.

viraptor 3 days ago|||
I wouldn't say it's cringe. A factory is a factory. Calling it that in the code may not be the best idea, but having the shared vocabulary is nice. Basically, patterns work well when they're descriptive rather than prescriptive.

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.

microtherion 3 days ago|||
> A factory is a factory.

Yes, but what about factory factories? https://factoryfactoryfactory.net

zelphirkalt 3 days ago|||
The visitor pattern is my go to example for patterns, that you don't really need, when you have a language that has first class functions, which implies among other things, that you can pass functions as arguments, like you can pass anything else.

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.

vips7L 3 days ago||
I've always seen the visitor pattern as a poor-mans pattern matching. How do you solve the same thing with callbacks?
zelphirkalt 2 days ago||
Instead of defining a Visitor interface and then making objects to implement the interface and then passing those objects to whatever traverses a graph or iterates through something, you pass the function, that will be called, by whatever traverses a graph or iterates through something.
vips7L 2 days ago||
Kind of like how sum types and matching are implemented in library code? Example from D here:

    Fahrenheit toFahrenheit(Temperature t)
    {
        return Fahrenheit(
            t.match!(
                (Fahrenheit f) => f.degrees,
                (Celsius c) => c.degrees * 9.0/5 + 32,
                (Kelvin k) => k.degrees * 9.0/5 - 459.4
            )
        );
    }
TINJ 3 days ago|||
> 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.

Isn't this called 'dynamic programming'? It's actually a habit people should pick up when grinding leetcode.

viraptor 3 days ago|||
No, dynamic programming is when you split your bigger problem into a smaller one + 1 step to get to your bigger size. Then apply that recursively until you solve the trivial problem at the end and get back the answer for your original problem size.
salutis 2 days ago||
No, that is plain old recursion. Dynamic programming is recursive programming with a twist. The twist is that identical sub-problems are short-circuited with memoization.
arethuza 3 days ago|||
If you already have Sets handy - why not use the Set Intersection? (Assuming the Set implementation has that capability).
zelphirkalt 3 days ago||
Putting both contents (lists, arrays, whatever you have) into sets, and then calculating the intersection might be more expensive than building the intersected set right away sourcing both non-set contents, I imagine. Though it would probably be easier to read and understand. But that can be solved by naming of functions that process the 2 non-set things.
rglynn 1 day ago|||
I agree with the first half as it echoes my experience, but the second half hasn't been my exp.

To talk about design patterns as not as useful, only to then mention big O notation seems strange to me unless you are in a context where performance is critical?

Worrying about O(n) IME is far less important than choosing the right architectural pattern. O(n) issues are usually observable via metrics or QA and are typically straightforward to fix. By contrast, recognising that your pattern choice is wrong is harder (since it manifests during dev rather than in prod) and takes more effort to rectify.

I also disagree that patterns don't deserve a name. I have found it very useful when discussing with both seniors and juniors to have a common name for a pattern being described. Seniors known instantly and it can be helpful to have a resource to point juniors to if they aren't familiar. I have also found it useful when English isn't the first language.

I do agree that seniors don't typically try to fit standard patterns to their problem in a way that a junior might, that's a fair point.

svilen_dobrev 3 days ago|||
the actual software design patterns, unbiased by language/particular-usage, are subtle. i would go as far as say that there are also "design-patterns"-usage patterns.. and those might be even more subtle. e.g. what is/constitutes "interpreter", and when to use one, and when/if one is being used behind-the-scenes. Sometimes it is a single piece that is easily pinpointable. Sometimes a whole (sub)system behaves like one (e.g. event-sourcing stuff) but it's not easily cut into this is this, that is that.

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...

DHRicoF 3 days ago|||
For your example, if both lists are small enough, the constant factor on the cost of creating the hashmap eliminates any advantage you could have. Anyway, it's not like most places were I've seen a nested loop used for search the developer had cared. Today I am in a bad mood.

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?

sureglymop 3 days ago||
Don't kill yourself. Stop and leave. Every day you will build up a tiny bit more resentment and then first you will become more cynical but eventually you will burn out. Be proactive and leave this behind, move on with life.
agumonkey 3 days ago|||
What about the social / communication aspect ? Having a common vocabulary of pattern may help reduce cognitive load when reading others code. Just a soft opinion because I assume it's the reason frameworks and conventions help teamwork. Less per-context custom solutions.
zelphirkalt 3 days ago||
It really depends. If under the guise of "best practices" and "patterns" a team creates an unmaintainable, not easily extensible mess, then all this community aspect was good for exactly nothing but shoulder patting. If instead pattern are used sparingly, where they actually make sense, then sure, it can help.

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.

Jaxan 3 days ago|||
> Very useful pattern but I don't believe it has a name.

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.

spopejoy 2 days ago||
This is the thrust of much of the excellent "Algorithm Design Manual" by Skiena -- choosing the right data structure to model your problem can take you 95% of the way toward the best solution.
zwnow 3 days ago|||
For webdev especially everything I do is basically singletons... For UI state management its just perfect and that's about the hardest thing in web dev. Also easy to recover state with, in a SPA if a user refreshes the site. Or control whether a modal is open or not. Easy to centralize logic too... Never looked into any other patterns as a lot of them seem like bloat.
hyfgfh 3 days ago||
Agreed! The problem is that some 'seniors' never cared to learn patterns in the first place. That’s a huge problem for frontend, where we have increasingly complex architectures and people with very little experience with design.

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.

davidkunz 3 days ago|||
> It's in Java, but the lessons can be applied in every language.

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.
Kwpolska 3 days ago||||
I've read that book, and it felt very childish and condescending.

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.

microtherion 3 days ago||
I'm not sure what Builder would have to do with default parameters and named arguments.

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.

Kwpolska 3 days ago||
Here is an example of the Builder pattern that illustrates my point: https://www.baeldung.com/java-builder-pattern#bd-classic-bui...

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");
vips7L 3 days ago||
Funny part is that Java does have named parameters, but only for annotations!
prodigycorp 3 days ago||||
What's interesting about frontend is that there are two ways to evaluate it: by how it looks and how it's written.

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.

signal11 3 days ago|||
Design patterns are language independent, but a lot of the ones many Java devs focus on are a bit meh.

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].

[1] https://mishadoff.com/blog/clojure-design-patterns/

noveltyaccount 3 days ago||
In my senior year of college two decades ago, I needed one or two credit hours to finish up, and I signed up for a once per week software patents (as in, intellectual property, I thought) course. It turned out to be a patterns course taught by none other than Ralph Johnson and the text was his famous Gang of Four Design Patterns book. Happy accident, it turned out to be among the most professionally useful courses I ever took.

https://en.wikipedia.org/wiki/Ralph_Johnson_(computer_scient...

andybak 3 days ago||
"Design Patterns are a sign of missing language features".

https://wiki.c2.com/?AreDesignPatternsMissingLanguageFeature...

https://norvig.com/design-patterns/design-patterns.pdf

https://medium.com/@letsCodeDevelopers/your-design-patterns-...

crabmusket 3 days ago||
This is a nicely laid out collection of tutorials, but I'm sad that collections like this have drifted away from the very deliberate structure that A Pattern Language introduced. While patterns weren't invented by Alexander and co, they did inspire a lot of what we see in tech these days, inherited via design patterns etc.

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.

spopejoy 2 days ago||
If you're trying to connect Alexander to software patterns like GOF, it's important to include Gabriel's "Patterns of Software" [1] as the first genuine attempt to apply Alexandrian patterns to software. It also introduces the first and probably the best takedown of OO inheritance as not reuse but instead a form of _compression_ that is in many ways worse than just copy-and-paste.

1 - https://www.dreamsongs.com/Files/PatternsOfSoftware.pdf

crabmusket 2 days ago||
This looks great! I am diving right into the yak of producing a HTML version of this.
crabmusket 3 days ago||
Here's an excerpt from APL showing what I mean about the connections to the other patterns. This isn't the whole pattern, there's a lot between the problem statement and summary. Annotations in brackets are mine.

---

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)

phplovesong 3 days ago||
When overused these kind of "patterns" always lead to slow and hard to grasp code that is a nightmare to maintain.
z3t4 3 days ago||
My experience is that they are best discovered independently as a way to abstract code, and let them come naturally to solve a problem. So for most things in Dev, if you do something prematurely you might end up with a good solution for a non existing problem.
oleggromov 3 days ago||
Or, even more likely, a bad solution for a non-existent problem.
FieryMechanic 3 days ago||
Like many things they shine when use appropriately.
android521 3 days ago||
The ones that actually match POSD (deep modules, small interfaces, lower complexity) and work great with plain functions are:

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

neogodless 3 days ago|
What does POSD stand for?
jakubmazanec 3 days ago|||
I'm assuming John Ousterhout's book A Philosophy of Software Design [1], which I would recommend reading before reading about design patterns, because it's more fundamental.

[1] https://news.ycombinator.com/item?id=37975558

culi 3 days ago|||
I'm assuming Philosophy of Software Design but I've never seen anyone blatantly presume it's an implicit initialism
fiddlerwoaroof 3 days ago|
I wish people would stop promoting the singleton pattern: in almost every case I’ve seen, singletons are unnecessary tech debt and solve a problem that’s better solved with some form of dependency injection (and I don’t mean the XML/YAML monstrosities various frameworks force on you but rather constructor arguments or factory functions)
HumanOstrich 3 days ago||
The site is not "promoting" the singleton pattern. In fact, there is a "Tradeoffs"[1] section that calls it an anti-pattern in JavaScript.

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...

deaux 3 days ago|||
Why pose DI as replacing singletons when they're used together all the time? Injecting dependencies to create a singleton repository or service class, which is shared across requests.
dkersten 3 days ago|||
Singletons are globals and should be treated the same as every other global (that is, used sparingly and with care).

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.

hokumguru 3 days ago|||
Off the top of my head, rails (currentattributes), Laravel (facades) especially, and most iOS apps use singletons quite well. It’s all in moderation and depends highly on how it’s used, much like every other design pattern.

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.

gm678 3 days ago||
Yes, I have to admit my interest was piqued by the banner, and I then scrolled down, saw the first example was singletons, and closed the tab.
More comments...