132 comments

[ 2.8 ms ] story [ 194 ms ] thread
The core points of this talk, as noted in the Addendum [0], is that "we need to take a fresh look at Christopher Alexander".

Since that point has been established, it would make a phenomenal follow-up talk to take Alexander's book, which is from the 1970s, and begin a discourse on how his ideas can be applied to modern software engineering and architecture. While the reader takes away from the slides that Alexander has some unique ideas that are probably useful, he/she doesn't come away with a good understanding of what they might be. (though if anyone knows of talks that discuss Pattern Languages, I'd love to see them!)

[0]: http://perl.plover.com/yak/design/samples/note.html

(comment deleted)
After reading the presentation, I'm imagining the presenter has an obnoxious loudmouth voice and totally misses the point.

He goes on and on to put down C++ and the four book authors as if he holds a personal grudge against both. He makes it seem as if C++ programs were written by code monkeys pasting examples from books in order to make it work while other programming languages are god's word. It does not occur to me why he thinks that in C++ there should be a general solution for an iterator over any kind of collection^1. Yet C++ allows to implement data structures on the lowest level and only the programmer may know how to iterate over a certain multiply linked structure (if possible at all). The Perl counterexample looks like a straw-man to me.

I agree with you, the core of the talk comes after the talk and is not presented properly.

1: For standard collections in C++ there are iterators predefined and you can iterate over the collection easily.

Or, indeed, to look at Alexander's work since this book, which has gone in a direction very similar to the programming world. In "The Nature of Order", Alexander shows how the idea of "good design" is actually best analyzed as just the output of "good process": design is about how a thing unfolds over time and becomes more itself through gradual refinements and responding to its environment.

The bigger complaint about software patterns is that, unlike Alexander's original patterns, they are merely tools useful to build any kind of program. Alexander's patterns were meant to only be useful in building humane places with humane processes. You literally could not build a mass prison with the construction methods he describes, because they aren't amenable to mass production, design from afar, or economies of scale.

Exactly the opposite is true of our usual application of "software patterns". They are often used to produce software that is inherently immoral. Alexander's patterns describe an environment of decentralization of decision-making about both architecture and the community it inhabits. Meanwhile, our "software patterns" embed a centralized power structure both in the code (architect->team lead->junior programmer) and in the world now increasingly controlled by the whims of Silicon Valley founders.

I wonder what it would look like to describe low-level primitives of computation, similar to Alexander's new low-level architectural methods, which actually made decentralization of power a reality and resisted economies of scale. They certainly wouldn't look like the Gang of Four patterns.

> Meanwhile, our "software patterns" embed a centralized power structure both in the code (architect->team lead->junior programmer) and in the world now increasingly controlled by the whims of Silicon Valley founders.

None of these things is obvious to me. In fact, this whole paragraph veers in the direction of a conspiracy theory. The rest of your post is quite interesting and I agree that the design of our software should tend towards the human and humane.

> Exactly the opposite is true of our usual application of "software patterns". They are often used to produce software that is inherently immoral. Alexander's patterns describe an environment of decentralization of decision-making about both architecture and the community it inhabits.

You should expand on this.

I certainly don't mean to imply a conspiracy theory, any more than Alexander would say that the past century of poor architecture is deliberately brought about by a conspiracy of architects. It's simply a case of the environment bringing about bad results naturally.

His critique of architecture is this: the quality of a building comes from a process which has to unfold over time and take into account very minute preferences of the kinds of people who will actually inhabit it. A good house design can't be measured by the plans, but only by living in it and seeing what kind of life occurs to the people who are there. Therefore, if you build it by one person's design, or because the renderings look nice as a 2d composition or as a 3d model, or to reduce costs by repeating the exact same things over and over, you will necessarily end up with a bad building. It won't be bad on purpose, but the power structure of the process that built it will have made it bad. (Maybe an architect wanted to win an award, or a developer wanted to sell the properties quickly without worrying about the owners' long-term experience, etc.) And if you want a better building, instead of arguing about design, you should just find a process where more of the decision-making is made by the kind of people who will inhabit the house.

The same is true of software. I do not think most people set out to make bad software. But Conway's law tells us that the result will reflect the organization and process by which it was created. If the process of creating the software is embedded in a large corporate structure where VPs are fighting, that politics is necessarily felt by developers and even embedded into the system. If the process of creating the software is embedded into a VC unicorn and its only chance of growth is to destroy local communities or mistreat workers on a large scale, that will happen.

This is even true just for the people building the software. I've worked at companies where the design team had the power, where the engineering team had the power, or where the project management tool had the power. The same people might work with the same goals, but in these three environments they will produce three very difference pieces of software. And I've worked at companies that had the power to trick money out of customers, which soon replaced the desire to actually provide customers any benefit, and produced its own unique form of engineering environment.

Alexander's critique is aimed at the very idea of "scalability": any one person or process who can determine the way architecture (or software) behaves for thousands of people will get it wrong. Not because the person is bad or the decision is inherently wrong. But because no one decision could possibly be right for all of those people.

The bigger problem often is...

We don't often understand what we are building most of the time.

Software is a communication tool most of the time. You are communicating between machine and user or user to machine to network of data and so on.

Most of the code is really a translation from input to some kind of command or process and outputting the result.

The more layers you add to that, the further you are from the truth and the more confusing the world truly is. For all the patterns, abstractions, and so on that we lean on, we miss out on the most important one...

input -> processing -> output

We need a way to explore the design space of the design space.
> We don't often understand what we are building most of the time.

Indeed. Programming is a process of constant discovery and reframing of the problems ahead.

> Most of the code is really a translation from input to some kind of command or process and outputting the result.

I disagree. This may be true in a general form, but a general form like this is of little utility. There are many types of programs for which the focus is state manipulation, and what you care about is that state - whether in its final form (e.g. 3D modelling software) or in its evolution (video games). The classical output here is just a snapshot of state. I don't think trying to squeeze everything into a "dataflow" paradigm of input -> processing -> output is a good idea.

Also, in context of design patterns - the problem is that even if we take "input -> processing -> output" assumption, the space of possible outputs is huge, and the criterion for acceptable outputs is very complex. It is this complexity that makes our code complicated, and the reason we have to build layers of abstraction is because our minds are pretty limited and we can't handle much complexity directly.

This guy clearly doesn't understand the iterator pattern!

J/K'ing. But he consciously chose to give the talk a "click bait" title, and the goat thing was a bit of hyperbole. Totally reasonable things to do, but know that you have to live with the backlash from that.

All of that said, I agree with this core point that "we need to take a fresh look at Christopher Alexander". I plan to go out and get a copy of the pattern language book and read it sometime soon, to get a better perspective on "real" Alexanderian patterns. This was a handy reminder to do that.

Ugh! I read the joke without realizing it was a joke.
It's worth mentioning that "A Pattern Language" is just that, it's a language of about 250 patterns that can be applied to urban design, building layout, and construction. If you want to know more about design patterns and how and why Alexander came up with the patterns described in "A Pattern Language" in the first place (which is helpful if you want to create a pattern language of your own to address the needs of a different field), you might be interested in "A Timeless Way of Building".

(I would recommend reading or skimming through "A Pattern Language" first, to get a good idea of what Alexander's idea of a well-formed pattern is. It's also a really interesting book in its own right, especially if you have any interest in architecture.)

My impression was that design patterns are just shared vocabulary, not something to aspire to use (other than realizing there was an existing "word" that would succinctly describe your jumbled spaghetti sentence and using that instead).

Edit: I've been wanting to read A Pattern Language for a while, but this snippet from Amazon made me chuckle. If I didn't know better, I would have given it a 50/50 shot of being from APL or GoF!

>The elements of this language are entities called patterns. Each pattern describes a problem which occurs over and over again in our environment, and then describes the core of the solution to that problem, in such a way that you can use this solution a million times over, without ever doing it the same way twice.

This.

Design Patters are simply tools at a higher level of abstraction than the code itself.

They are 'approaches to modelling information'.

That's it.

Use them, hack them, or not.

I've found them handy enough, though never implemented anything precisely. They make sense when communicating ideas as well.

I don't see why there is a need for debate.

Right, if you do the same handful of things over and over again, you eventually realize that it helps to have a way to talk about those things at a higher level. It's nothing too serious.
I'd completely agree that, at their core, design patterns are simply words or phrases that can loosely define what a program can do without getting as specific as even pseudocode.

I believe there is some element to aspiring to use them though. Once something becomes common enough to be called a design pattern that 2+ independent developers might recognize, that's the signal of a common problem that might have better solutions than the first couple you come up with in planning.

If a design pattern becomes really common, perhaps enough developers get together and add a feature to a language (or make a new one) to encompass what was once a common bit of spaghetti code.

I've heard the quote about design patterns making up for the lack of features in a language. I've always been a little confused by it. Can you give me a good example of a language feature that removes the need for a design pattern?
In Java, you'll sometimes see people handing around instances of nearly (or entirely) empty classes with a single method, for use as callbacks. In languages with first-class functions, you can just hand around function pointers directly, you don't need to dress them up with classes.

In C, you'll sometimes see people make a struct containing only a collection of function pointers, and different parts of the code will produce instances of the struct with the function pointers populated differently. In languages with built-in polymorphism, this isn't necessary.

A language-level match feature replaces many use cases of the visitor pattern.

Typeclasses often remove the need for facades.

First-class constructors (e.g. static virtual methods) remove the need for factories.

I think that's what they are in the industry right now. We all use the same vocabulary, and it makes sense to share a lot, since we're mostly doing the same thing.

The slides' point seems to be that there's this other concept, which is that each project should develop a language for speaking of the project, perhaps more specific to the project. But also not just a list of "things people use currently". Your new projects could include completely new design patterns.

So the idea when starting a project is :

when designing, define concepts that you will use a lot. For example, you might be using a lot of iterators. But for the designers of Angular, you're working with promises, with controllers, with scopes. Use this language when trying to frame problems, and people will build off the same base.

When people start coding, everyone starts off the same foundation. But that foundation doesn't need to just be "the design patterns from all over". You can have your own design patterns, more specific for your project. Have your best developers choose the right design patterns for the project, and even the most junior developers will be guided by this when working on the details.

The last portion of your comment reminds me of the themes from Mythical Man Month by Fred Brooks.
MJD says Alexander's central question is "How can you distribute responsibility for design through all levels of a large hierarchy, while still maintaining consistency and harmony of overall design?"

The only "solution" to this question in software that I'm aware of is, "hire a charismatic architect and let them do all the design" which is terrible.

Thinking about my team, I'd say probably a third of them are interested in architecture at all, and of that third, at least one has a punishingly minimalist aesthetic that the rest of us loathe. The rest of us are fairly scared of being wrong, scared enough to avoid making bold decisions.

GoF may be insufficient, but it's really the only pattern language we have. I don't even know how to think about this idea properly, which I consider a symptom of the author being onto something.

Good architecture is leadership based on transparent principles.

The hardest thing for a lot of people to hear is, "you're not wrong, but the thing you're thinking about isn't the essential one." Architecture is about finding the principles and axioms that apply to the situation. It also requires an ability to "let go," in that if your design is good enough, you are no longer personally necessary because the rest has been made obvious, and anyone can implement it.

Elegant thinking can seem obvious, and transmits a great deal of understanding simply. The purpose of architecture is to formulate something that benefits in scale to the efforts of multiple cheaper, less experienced people.

I think what makes that even harder is that I've never even thought of saying that, and it's exactly right.

Thanks for elaborating on this.

Would you mind sharing what you mean by "a punishingly minimal aesthetic"? Is it overly concise to the point of not being reasonably comprehendible?
I'm not going to, for two reasons. One, it wouldn't be appropriate for me to make it possible for the world to identify the developer in question (and I doubt I could elaborate without making it possible) and two, it opens up a discussion about code aesthetics that is not likely to be productive.

I will email you privately about it.

"The Gang-of-Four idea is to discover existing patterns of software development. Then program people to implement them habitually"

Citation needed.

GoF's intention was to give people a tool for thinking about architecture and sharing their experiences with others. If people are "programmed to implement them habitually", that's some manager's fantasy and neither in the letter or spirit of Design Patterns.

It's be like seeing a programmer blindly use jQuery without understanding JavaScript, and blaming it on jQuery instead of the programmer. A tool that can be used badly, even one that lends itself to being used badly by a certain population, doesn't automatically mean the tool itself is rotten.

(comment deleted)
I don't have the book handy, but I seem to remember somewhere early on they say something to the effect of "We find ourselves writing similar code in response to similar situations, so we've collected those strategies and put them in this book." I don't remember anything that sounded like "This is how you OO."

As others have pointed out, the book is nice because it gave rise to a common language for describing patterns, and it's much easier to understand code someone else wrote if you can divine intentions from variable and class names.

> that's some manager's fantasy

The issue is that in a lot of shops design patterns have turned into a religion and not just a tool to help thinking. I've seen managers like that.

If you didn't implement 15 different design patterns in this or that code base that was "bad design", even if it unnecessarily made the code more complex.

I've seen iterators classes written when a simple for loop would have done the trick. I've seen chains of responsibility implemented when a basic switch statement would have been enough. Of course the code wasn't meant to be refactored in anyways. In fact complexity led to inability to refactor anything as nobody had a clue what went where ... and of course to manage all that bullshit we had to write tons of factories, because instantiating a single useful object now took 30 lines of code ...

(comment deleted)
Agree, that's a real issue, just like managers who treat agile as a religion and sadly give a fundamentally good thing a bad name.

Good programmers know the importance of YAGNI and the root of all evil that is premature optimisation. They should be well equipped to avoid over-engineering while still getting the learning benefits of patterns.

Chain of responsibility, for example, is a pattern I learned via GoF, have found it to be useful on several occasions. I quite possibly never would have known about it otherwise. At best, it would be left to chance for me to stumble on it or refactor into it enough times to recognise the pattern.

Via the curry-howard-lambek(-...) correspondence, Category Theory is a pattern language for programming. It has a very rigorous criterion that justifies calling a logical/mathematical/programmatic construct a pattern: a pattern is a universal construction. Bear with me if you would like. I'm doing this off the cuff and I doubt I'm good enough to communicate what I want in a single Internet comment :)

A universal construction, at the vaguest level is the most general way of solving a particular problem. For example: What is the universal way to construct a program that produces two values?

Via curry-howard: A program is an arrow from f : A -> B. We call A and B types, they are like specifications of the environment a program takes and the environment it produces. e.g. (+1) : Int -> Int is the program that takes an Int and produces another Int, by incrementing. We also have a way of composing programs, (.), which to young mathematicians is function composition, to older mathematicians morphism composition, and to nixy programmers the pipe operator (in reverse). (+1) . (x2) : Int -> Int is the program that first multiplies by 2, and then adds 1.

We want a solution that produces two values from the same environment. Such a solution looks like f : W -> A, g : W -> B. That is, we have two programs that take the same environment and each produce their own value.

Let's say our language has product types. That is, given a context A, and a context B, we also have the context A x B. This is a very natural thing to have. A language with pairs/tuples has such a type. What makes product types special is that they come with functions proj_1 : A x B -> A and proj_2 : A x B -> B which do the "obvious thing". That is, the first one just gives you the first element of the pair while the second just gives you the second element of the pair. I claim that this type and its projections are the universal solution to the problem of constructing a program that produces two values.

What do I mean by that? I haven't defined at all what universal means. See, I don't want to give the rigorous definition because it is very abstract and I think it takes a lot of pondering to really understand it. Instead, let me wave my hands some more and give references at the end: A universal construction is something that solves a problem in such a way that any other solution to the problem can be transformed into an instance of this construction.

The functions proj_1 and proj_2 are not the only feature of product types. They have another feature, and it is that, given a solution f : W -> A, g : W -> B, there is a unique way to produce a function W -> A x B, that is, there is a program that converts our solution into a product type. This is usually denoted < f, g > : W -> A x B. Furthermore we have that proj_1 . < f , g > = f and proj_2 . < f , g > = g.

This might either be complete nonsense, a triviality, or something you already understand. This definition of product, when made rigorous and with all its details written in, transfers from programming languages, to logics, to set theory, to algebra, to topology, to geometry and beyond. It is a pattern, and you can use this pattern wherever you find it. And where you don't find it, usually there's significant reasons why it can't exist.

https://en.wikipedia.org/wiki/Universal_property

And nobody cares because it is easier to just use a word Set. Or Program. (in Church-Turing sense, and not awkward Curry-Howard isomorphism)

A true Program is not really an Arrow, as it deals with mutable unknown state that cannot be reduced to a known set of inputs completely. (Where functional and monadic programming gets awkward or impure.) There may also be multiple outputs and inputs at any stage in the process, an Arrow limits you to one output and input vector making actual programming awkward. Forces the kinds of composition you can describe.

I've always seen design patterns principally as a way of communicating what you are doing to other programmers who come later.

For instance, MVC is a very popular design pattern. When you read code built according this pattern, even if you are not familiar with the language or framework, you know what kind of thing to expect to find in different parts of the program.

They can also be useful in a context where not everyone in the team is used to writing code in a disciplined way - like coding standards and ideas like YAGNI, they can give an objective set of standards at code review. Adopting a few of these strategies in a code base provides a standard people can refer to about what goes where. Where the question is whether James should have stuck this database code in the class that renders the web page, being able to point to a well documented strategy and say "that code doesn't go there because we're doing that" can be better than excessive conflict.

The author is right that if you have a common problem, you should probably be solving it with a library (preferably someone else's). However, often these libraries and frameworks are implementing the generic bits of the design pattern, and understanding that pattern gives you a shortcut to knowing how to use them well.

That's exactly right. The GoF patterns were identified from experience and then formalized, not created from whole cloth. Programmers that don't know anything about design patterns use many of them, often without realizing they are doing it.

The GoF patterns give everyone a common vocabulary to reason about the patterns.

> For instance, MVC is a very popular design pattern. When you read code built according this pattern, even if you are not familiar with the language or framework, you know what kind of thing to expect to find in different parts of the program.

The problem with MVC is that it lost any accurate meaning.If you tell me "my app is MVC", I vaguely understand it has a view, a controller and a model but it doesn't tell me if the controller sits between the view and the model or the view directly observes changes in the model.

If you take a pattern like the Chain of Responsibility, or the Command pattern, the goals are clear because they are usually made of a single or at most 2 collaborators. MVC is sometimes a mix between the strategy and the observer, sometimes it isn't yet people still call that MVC.

The major problem for me with MVC, is that people build complex applications on an MVC framework and then try to shoehorn various things that are definitely not views, models, or controllers, into the pattern.

I've seen applications that control hardware where a class called 'model' twiddles bits on an interface port and then blocks until it sees some bits twiddled in response. Or where the 'controller' actually goes off for an hour to do heavy data processing (using the web servers thread pool as a job queuing system).

In both these cases, those things should have been in descriptively named classes that accurately described what they did. In the latter case, trying to adhere to a pattern gave the application a strange architecture that could have unforeseen problems.

I'm not sure if MVC is even the right pattern for a lot of modern web applications with a thick client or that describe a workflow. Often it feels like you are shoehorning there.

However, I'd say these are cases of 'doing it wrong' that don't prove the overall approach bad. I picked MVC because everyone has heard of it.

This is why I disagree with the shared language interpretation of design patterns. Once you slap "MVC" or any other name on some code, you'll constantly be second-guessing whether new code is violating the pattern. The goal is to produce working, efficient, secure, maintainable software, not to implement patterns.

I think design pattern books would be more helpful if they deleted all the pattern names and just called the book "A collection of a-ha! moments in C++" or whatever. Readers could skim through the chapters every couple of months until they stop having a-ha! moments. The "patterns" may or may not emerge in the reader's code, depending on what works best for a specific project.

>I've always seen design patterns principally as a way of communicating what you are doing to other programmers who come later.

I've seen a big project with heavy emphasis on patterns, and it was a hell for new programmers. Take a month debugging 50 levels of method calls trough the facades and the framework, just to find code that does the business logic.

Every tool it can be misused. Doesn't mean it doesn't have value.
what the fuck is this place ? please somebody explain
The key slide is http://perl.plover.com/yak/design/samples/slide011.html

My understanding is that Alexander's patterns applied to software would be the typical components of a software system (DB, queue, API, etc). The GoF patterns are about how to build those components. They are lower level.

We need both, but don't we already have both?

> Alexander's central question is "How can you distribute responsibility for design through all levels of a large hierarchy, while still maintaining consistency and harmony of overall design?"

To the degree I understand Alexander's central answer, it is "Put the needs and wants of humans who are the users of the design at the center of all design, planning, and building (and heve them do the design, planning and building, where possible.)" If that's close to true, then making things that are programmable is more important than 'getting it right the first time'. One can always take a chainsaw or an editor to a bad decision.

I remember reading this some time after reading "Notes on the Synthesis of Form". He's absolutely right.
Christopher Alexander's books:

    https://archive.org/details/TheTimelessWayOfBuilding
    https://archive.org/details/APatternLanguage
It's also worth reading Patterns of Software by Richard Gabriel:

    http://www.dreamsongs.com/Files/PatternsOfSoftware.pdf
who draws heavily on Alexander's work.
Thanks very much for the links. And Richard Gabriel is an interesting find.
Patterns of Software is worth it just for the Forward.
I couldn't find "Forward" in that book, what exactly is it?
Very interesting, a lot a truth, many design patterns have become useless in some languages as the language itself solves the problems.
hey man can u explain to me what is this place (website)
Very interesting, a lot a truth, many design patterns have become useless in some languages as the language itself solves the problems.
Design patterns are just a way to convey an idea. If I name something a factory, everybody knows its purpose. If I name something a prototype then people who are familiar with patterns know it will have some "clone" method. So it's a bit like UML redux. But one only need iterators if the language one uses doesn't allow you to naturally express custom iteration without requiring you to write a class or some other boilerplate.

The article demonstrates that fact pretty well.

It's also a good way to judge how practical a language is. I don't need to write iterators in a language that has generators for instance. I don't need to write factories in a language that supports closures... But then people selling all these expensive modelling tools would be out of business ...

I like his point about Alexander going after delegation of design decisions, though I don't necessarily think that's the only point he was driving at. From "The Timeless Way of Building" I got that he's also driving at this:

1. Modern (not necessarily just modernist) architects are generally terrible at achieving what Alexander refers to as "living space" because they're solving for the wrong things.

2. Small-scale patterns and large-scale patterns can constructively or destructively interfere with each other from urban planning right down to construction details of a room.

3. If you've really mastered design, you can leave behind the pattern language and cookie-cutter implementations: your solutions will organically develop with these large-scale/small-scale synergies.

I'd suggest that GoF is a little closer to Alexander in these respects than the presenter gives credit for, particularly for point #3. The book studiously makes the point that its implementation of these patterns is not meant to be the only way to implement them. It also makes no attempt to be an exhaustive catalog. The fact that some of these patterns have standard and different implementations in other languages (e.g. iterator method hooks and generators in Python) doesn't necessarily mean that the pattern itself is useless outside of its OOP niche.

I'm glad WikiWikiWeb is back up so we can debate all of this on the one true forum for debating design patterns. :-)

The thing very few people seem to get about Design Patterns (in the gang-of-four sense): they are not a Good Thing, desirable and worthy of study in and of themselves. They are a necessary evil to compensate for fundamental deficiencies in C-like programming languages.
The patterns still exist, just many of them are already implemented in the language itself.
Especially object oriented languages.
Especially functional languages.

I remember this whole talk now. I actually have an acknowledgement credit... holy crap. That was a long time ago.

Here's how I see GoF: it was a brand new idea to programmers. GoF was trying to open some eyes to the idea that there were already all these patterns in a lot of software. They called out a few of them. Some are really classic. Some were total misses (how many of you have implemented State?)

GoF was also coming from the Smalltalk world and trying to preach what they'd learned so C programmers could understand it.

So in 2002 when MJ Dominus wrote this, a lot of us were feeling a lot of stress about the rise of Java and C#. A lot of the appeal of these languages was the promise of never having a memory leak. A side benefit was that Java especially didn't enable some of the really risky C++ practices (MI, overloading short circuit operators... basically most of Scott Meyers' "Effective C++" books). But if you were any good at C++, you gave up a lot. Generics were the big pain but I remember at the time really missing the STL <algorithm> library.

MJ was (is?) a Perl / dynamic languages guy. There was vigorous discussion in the "blogosphere" (gag) over the static/dynamic language debate. MJ was basically saying to think bigger than these trivial little patterns. GoF is to software architecture is like nails & drywall are to an architect.

> The "Design Patterns" solution is to turn the programmer into a fancy macro processor

To be fair, it is far from the only source of motivation to see programmers as (or turn them into) a fancy macro processor. Maybe that's one reason why shops where discussion orients heavily on design patterns often also seem to be places where Management Theory X [0] is on display.

[0]: https://en.wikipedia.org/wiki/Theory_X_and_Theory_Y

This is what strongly-typed functional programming languages have been teaching and preaching and practising for years.
Can you provide more detail, this is very intriguing. Do you mean that the types are the patterns?
Not the OP but let's take a tree. In F# it's trivial to describe what a tree structure is with the type system. In Java, you'll need to use the Composite pattern and write classes (tree + leaf) to create a tree like structure. Thus the Composite pattern is made irrelevant in F# since an algebraic type system allows you to describe an intent without writing imperative code.

https://en.wikipedia.org/wiki/Composite_pattern

https://en.wikipedia.org/wiki/Algebraic_data_type

Good type systems are a trade-off between complexity and expressiveness, but it's something that is hard to get right. Obviously Java's type system is simpler thus in theory easier to learn. But in practice F#'s is easier to use if understood and might lead to smaller thus more maintainable code bases.

It's not really a property of a functional or strongly typed language. Trees are trivial to define and iterate over in e.g. Prolog or Erlang as well. The essential thing here is the first class support for structured/abstract data types.
Design patterns are mostly cultural. They're about getting people to speak the same language about designing a system. In languages like C++ and Java, the culture is needed to overcome the paltry capability of those languages to re/compose well. Other language communities don't need this.

If you read Alexander's interviews in Stuart Brand's How Buildings Learn you'll see he's mostly concerned with how to connect people directly with the problems his buildings and urban planning are trying to solve. It's highly cultural. He rails against what he calls "magazine architecture" where buildings are designed mostly to photograph well, their inhabitants's problems with the buildings are an afterthought. Sounds familiar?

Well, design patterns are an abstraction.

You can build an abstraction where a car as a particle for a thought experiment or where a car is 3d vehicle with a deformable chassis for crash simulation. Both can represent a vehicle to certain level of detail. The correctness of using each level of detail is very context sensitive.

To model a problem after a design pattern can have a lot of overhead, but it can objectively produce a working solution.

Now, if the design pattern is really a way to solve a problem in terms of constraints imposed by a type system or a language, once you add, change or remove those constraints the problem solving approach might stop making sense or being optimal.

I'm a bit young for perl, but I've had rather extensive experience with python at my last job, and it's my understanding that perl has a similar "global" solution with

    for elem in collection:
and the `__iter__()` function. Correct?
no. perl5 can deal natively only with finite lists, not general iterators over infinite (lazy) lists. of course you can design an iterator over lazy lists, but you got no language support as with __iter__, other than using tie callbacks.

only perl6 supports lazy lists and coroutines and yield.

but iteration is only a trivial part of a design pattern. as the name says, a pattern is matching certain conditions, like number of arguments, types of arguments, context, ... and applies a specific solution to this pattern. perl5 and perl6 are not functional enough to provide this kind of pattern matching and functional dispatch. python and ruby neither. perl6 has multi-methods, but no proper matcher.

Norvig explains a bit in http://norvig.com/design-patterns/design-patterns.pdf, but in essence any strongly typed FP deals with that.