Hacker News new | past | comments | ask | show | jobs | submit login
“Design Patterns” Aren't (2002) (plover.com)
310 points by Tomte on Nov 1, 2016 | hide | past | favorite | 122 comments



I remember reading this when it was new.

foreach only works on a list. I can bless a list of lists into a rose tree, but i can't traverse that in a uniform way. There's just no hook to say, when the thing isn't a list, get the next element like this. Now days i'd point at haskell's traversable as the gold standard.

On large java projects it seems like composite/facade for days. Those splits seemed to let teams work together and not end up with piles of rubble.

A lot of my understanding of programmer fashion back then was pretty fuzzy. It was easy to ask any team if they were doing extreme programming and they'd all respond, well, kinda. Ask any team if they were using a pattern language, and they'd mumble about UML. Sort of the equivalent of well, kinda.

When you have to write a large project like a compiler or a web browser or something, it's handy to have around. All to often I stare at the empty text window in my ide and question my life choices. I wonder why i didn't learn to weld and why i'm a failure at everything i try. The existential dread fills my soul and i want to just crawl under my desk and cry. In that case, i'll flip through the GoF. Then i tell that endless abyss "I'm going to use the Command Pattern!" The abyss slinks back into the corner quietly murmuring until i feed it a couple beers at the end of the day.

On the other hand, i did quite a bit of perl programming around 2000, so i'm probably weird.


From the postscript of this slide deck:

It appears to me that almost everyone who has read this has completely missed the point, even though I said it twice in big letters. People keep sending me mail that says things like this:

> I just read through you article "Design Patterns" Aren't. I'm afraid you got it all backwards. At least the iterator example is totally flawed.

Or people spend a lot of time arguing about how foreach is not analogous to an iterator pattern, or how it doesn't do the same thing, or how even if it does, I'm still wrong, because Perl has no analogous replacement for a model-view-controller pattern, blah blah blah. None of this has anything to do what the point of my talk. I really wish I'd left out the thing about the iterator pattern.

Why do people focus on pages 4, 5, and 6 of a 13-page talk, and forget all about slides 8, 9, 10, 11, 12, and 13, where I make the real point? I have a few theories. One theory is that most of these people are technical experts. They're equipped to consider technical issues, but not much else. When all you have is a hammer, all you can see are the nails. That's what happened to the guy above who said I "got it all backwards." What? The point of my talk was that we need to take a fresh look at Chrsitopher Alexander; if I got it backwards does that mean he thinks we should avoid taking a fresh look at Christopher Alexander? Or does he think that Alexander should be looking at us instead? No, he just forgot about everything after slide 7.


It appears to me that almost everyone who commented on my comment completely missed the point, even though i made it three different ways.

Why do people focus on paragraph 2, when paragraph 5 is where i make the real point? Facing a big coding challenge is hard, and having an abstract language for describing how to structure a solution is valuable to the point of protecting sanity. I have a few theories. One theory is that most of these people are technical experts. They're equipped to consider technical issues, but not much else. When all you have is a hammer, all you can see are the nails.


fyi i don't understand why you're getting downvoted, and touché.


To be fair, it was pretty snarky. It was meant to be silly not hurtful.

In my experience, people pick and choose what they need at the time. I don't think it's unreasonable to say conversations like this happen all the time.

Dev1: Hey, i need to test my control flow, but i need the register allocator.

Dev2: Oh yeah, I put together a facade for register allocation that just does LRU and injects the push/pop pairs to do the right thing. I couldn't get away with a simple interface because there's some weird shared state. The graph coloring allocator is hard, and will take me some time to get ready.

Facade is kind of code for a leaky abstraction. It communicates a lot about how the api really works. Most of the stuff in GoF got picked over and teams took what they needed. Are you doing design patterns? well, kinda. In that sense, i think it did a lot in the Christopher Alexander spirit.

The original author wasn't wrong, just look at FactoryFactoryBuilderFactoryMadness from java's crazy times. But i don't think that's a fair characterization of the entire field of programming.


The problem is you buried your point in the 5th sentence in the 5th paragraph of basically a rant.

And it's wrong. No modern programmer does that any more.

When I first came here 9 years ago people would refer to patterns all the time. But this is the first time I've seen the GoF even mentioned in a year or so. People stopped caring about design patterns years ago because they stopped being relevant.

And good riddance, the whole thing was a farce that spawned factoryFactoryFactories and newbies constantly asking how to implement a singleton because actually they wanted glorified global variables because they can't program properly.

Where the GoF completely failed, javascript, ironically, saved us (with Crockford doing the nudging). It forced functional paradigms, lambda expressions, anonymous types, function objects, etc. into the mainstream languages where lisp had failed and almost overnight made design patterns obsolete. It fundamentally changed how we programmed so that the problems the patterns aimed to solve weren't problems any more.


Design patterns aren't obsoleted by JavaScript; they've just been given trendy new names like reducers and sagas.


Precisely. Each language and domain of programming gets its own set of patterns. Some patterns are obsoleted (by virtue of being unneeded, or baked into the language), some new ones are created. Some are amalgams of old ones.

This is the way of the world, design patterns are intended to offer a language, and languages evolve. The uniqueness of design patterns to certain domains/languages can be seen as equivalent to the jargon between different technical fields. It doesn't mean that one set of jargon is obsoleted, it just means it's inappropriate. The failure, if any, in our world (programming) is to recognize and emphasize that different levels of programming, different languages, different operating systems, require different jargon and patterns and approaches.


> And good riddance, the whole thing was a farce that spawned factoryFactoryFactories and newbies constantly asking how to implement a singleton because actually they wanted glorified global variables because they can't program properly.

Number one on HN at the moment for me is "Async/Await support landed in Firefox Nightly". With Async/Await, instead of explicitly queuing callbacks in the main event loop and then returning control to the main event loop (ala Reactor Pattern), I create a queue of callbacks that are scheduled to run one after the other when each one terminates. This is different from a Continuation, where I queue my current state, schedule a callback to be run and then restore my state.

I often use Rails (not usually by choice ;-) ). Data is mapped from relational tables into objects using a pattern known as Active Record. In this scheme you generally have one model object per table and the model object itself is responsible for writing data to the database. There are other schemes for mapping relational data to model objects. Active Record is very convenient for simple data models, but is not great for more complex systems.

The opinion you express (that modern programmers need know nothing of patterns) is one of the reasons why programmers don't understand the tradeoffs between Reactor, Async/Await, and Continuations. It is one of the reasons I have to pull out my hair dealing with domain object models that mirror relational layout exactly.

I haven't mentioned a single pattern from GoF, but it's all the same. These are design techniques that are appropriate in some situations, but not in others. Even the very, very simple design pattern in GoF are unknown by a large proportion of programmers out there. Things like Flyweight pattern should be basics for any programmer, but most people haven't got a clue. And if I had a nickle for every time I've seen Composite Pattern where one of the terminating objects is not a subclass of the container (with obvious hilarity ensuing), I'd be a rich man.

How many times have I seen people deriding OOP and espousing the advantages of pattern matching? We can write functions that are polymorphic to their parameters so that we can group all the functions doing a particular thing in one place, regardless of type! The same people will chop my hands off if I mention Visitor pattern.

The paradigms you espouse are patterns. They even have names. And they have situations where they are appropriate and where they are not. If you get it into your head that the language designer will tell you how to do it, so that you don't have to know, it will limit your growth as a programmer dramatically. If you think that your programming culture will somehow allow you to escape the need to think about and discuss techniques -- using names, and describing situations where the techniques are beneficial and when they are unwanted -- then you will never understand what you are doing.

I don't for a minute believe that you intend to stay so ignorant, but the words that you type have been used to keep many from improving their abilities beyond basic repetition.


Just some comments to your response.

`The opinion you express (that modern programmers need know nothing of patterns) is one of the reasons why programmers don't understand the tradeoffs between Reactor, Async/Await, and Continuations. It is one of the reasons I have to pull out my hair dealing with domain object models that mirror relational layout exactly.`

I actually rather a domain model that mirrors the relational layout exactly, as this reduces my time spent in some god unknown framework who is over-engineering with `design patterns`.

`These are design techniques that are appropriate in some situations, but not in others`

Like what? Seriously? Do you have any evidence to backup the assertion of design techniques that are appropriate for some situations but not others? Otherwise you're just kidding yourself.


'Like what? Seriously? Do you have any evidence to backup the assertion of design techniques that are appropriate for some situations but not others? Otherwise you're just kidding yourself.'

Really? This requires proof? I would have thought it was self evident. Take the Flyweight pattern mentioned previously - appropriate when you have thousands (millions, billions...) of entities and memory is constrained.


How can it be self evident? You made a statement saying `Some are appropriate for some situation but not others`

You've listed one example of Flyweight, but without any sources to backup the claim it's appropriate when memory is constrained.


The whole premise of the GoF book is to offer patterns that are helpful in certain situations. They describe when a certain pattern will help and when it will not in detail. They also take care to tell you that you should think carefully before using a pattern and consider all the alternatives to be sure you're using the right tool for the job (or maybe a pattern that isn't in the book would work too of course)

To use the building architecture analogy FTFA, the "door" design pattern is good for some circumstances and the "window" pattern for others. This is the same thing. Not sure what proof you're after?

It's a great collection of patterns that you can pick and choose from, not the be all end all, and totally worth reading even if you only get 1 idea for how to solve a problem from it


I'm not sure if you're seriously questioning, or if you're trying to win an argument.

i'm going to go with the notion that you're genuinely curious.

I worked on a project with grids, an editable table like an excel sheet. Each grid, row, column, and cell could be styled. Font as Arial, Comic Sans ...; Color as rgb; padding top, left...; background color as rgb; Alignment as left, right or justified; format as freeform string, integer, float money or regex; decimal separator as . or , ; thousands separator as . or ,; and a whole bunch more.

The first cut just naively associated a style struct as part of each cell's data. Several customers complained that grids were very slow to start up, a few complained that they were running out of memory. They were using very large datasets for the grid, and the naive implementation wasted a lot of time on initialization, and a lot of memory on duplicate representation of style.

In retrospect it was a stupid mistake to make. We'd only tested against small amounts of data on relatively fast machines. Customers were using millions of rows.

The solution we went with was the aforementioned pattern. it saved a ton of memory and a ton of time avoiding all of that initialization. There were a few rounds dealing with smart lookup of style based on cell, row, column, and overall table.

My c++ is rusty, but i'm a little baffled by your confusion. Iterating over data structures in a uniform was was kind of a big deal back in the day. IIRC, implementing preorder, inorder and postorder iterators for a binary tree was homework. Have iterators fallen out of fashion?

I don't have a peer reviewed paper paper indicating flyweight is helpful. I don't have a peer reviewed paper saying multiplication is better than looping over adding m to itself n times. It's just better.

Some of them are mostly stupid, ala singleton. Of course even stupid singleton is a nice place to stick environment variables, because they are globals. I never thought decorator was all that great. I really like composite, but i like tree representations that i can recurse over.

If i had a scale, where you could place code on one side, and a design pattern on the other side, and it would balance if adding the design pattern was worth it, i would give it to you. To my knowledge, no such thing exists.

If you have questions, i'll try to answer. here or jfoutz at gmail.


It says so in GoF. The example in the book is having an object represent each character on the screen. You don't want to pay the overhead of an object for each byte in a file, so you use flyweight to share all the instances of each character.


> Like what? Seriously? Do you have any evidence to backup the assertion of design techniques that are appropriate for some situations but not others?

It's hard to say what you mean by this. I have difficulty believing that you think that a technique used in one situation is always going to be the best technique to use.

As someone has already graciously described situations where Flyweight can be used, perhaps something simpler than that like the Singleton can be illustrative.

The OP opined that the Singleton is only useful to people who don't know how to use a global variable. If that were the case, it would not be useful at all. In fact, it's usually something to stay away from. However, it absolutely shines when you want to make sure that an entity's constructor is only called exactly once.

There are many situations where you need to do this -- often when interacting with hardware, this kind of thing is crucial. As the OP suggested, though, it's easy to misuse this pattern.


Spoken like a true perl programmer


> Why do people focus on pages 4, 5, and 6 of a 13-page talk, and forget all about slides 8, 9, 10, 11, 12, and 13

From a sample of one i.e. me it might be that they aren't forgetting slides 8+, it could be they just didn't bother getting that far.

I got as far as the Iterator example where he, effectively, says that there's no such thing as an iterator pattern because perl has a list iterator built in. Having read that, I didn't feel a huge drive to continue reading the rest.

I appreciate that's probably a failing on my part, it is unlikely to have been a huge drain on my life and I might have learnt something. But that was the path I took. I have a funny feeling others may have done the same.

EDIT: I have felt sufficiently guilty that I have read the rest. If I understood correctly, the author doesn't think that GOF design patterns are the same as Christopher Alexander's design patterns. He thinks that Alexander's patterns are important and applicable to software. He doesn't really say why.

It wasn't a huge drain. It wasn't particularly informative. The Iterator pattern is definitely a thing. Don't feel a pressing need to read Alexander's book again.


The takeaway I got was that in software as in building architecture, the design should result from a conversation between the architect and the users. Christopher Alexander's book presented a shared vocabulary that allows the eventual users to specify at a high level what they want ("entryway transition", "varying ceiling heights", etc) for the architect to synthesize into a coherent whole.

Christopher Alexander patterns are about the conversation between the maker and the user; GoF patterns are about the conversation between the maker and their tools.

If we drop out of the conversation about design patterns altogether and look at that kernel of the argument, I think there's a very valuable point there: makers need a way to effectively communicate with their users at the correct level of abstraction. This generally necessitates a design language that is useful to both parties.

Users don't care if their data is being stored in a relational database, or document store, or flat files; they just care that it's persisted. Linus Torvalds didn't build git because he wanted a content-addressable tree of objects, he wanted fast, distributed source code management with protection against data corruption.

Talking to our users is one of the hard problems in software architecture.


I mean, lots of people can't read for crap, but at some point, some of the failure to communicate has to fall on the one doing the talking.


Actually. It's always the sender's responsibility, not the receiver. Or, as it's been said: It's not what you say, it's what they hear.


That saying was before the internet, though. There are plenty of people who read something to say what they want it to say, and no amount of planning will ever change that.


Trivially, this is as impossible as not offending anybody.


You're absolutely right.

But I also think the author's getting at something slightly different - it sort of goes back to that popular barb that design patterns are just a way to make up for a language's shortcomings.

At the time this was written, doing something like foreach in most languages was a horrible PITA. And if you had a language like foreach, and you were watching people use the iterator pattern (which, I realize, is more powerful, but mostly it would get used for stuff that foreach could handle), you'd definitely shake your head sadly to see all the sweating it would take to express simple concepts, and you'd think, "Geez, why are most programming languages so awful?"

A lot of languages stayed awful for a long time. Java only recently got better, I think partially in response to pressure from .NET. Nowadays, though, even C++ is a wildly different beast, so the point the article was trying to make has lost a lot of its poignance.


I'm a 40-something programmer learning to weld. It's really fun! You can do it too.


Same here. Totally agree. Check out the new weldment and pipe features in OnShape, just noticed this last night.


> When you have to write a large project like a compiler or a web browser or something, it's handy to have around. All to often I stare at the empty text window in my ide and question my life choices.

You absolutely nailed that feeling. And yes, it is indeed useful to have a repository (he) of patterns, just so you can start throwing them at the problem until you find something that sticks.


Your second to last paragraph is brilliant. Forget welding - you should write a novel!


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.


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.


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.


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


Design is a kind of Constraints Satisfaction Problem (CSP).

https://en.m.wikipedia.org/wiki/Constraint_satisfaction_prob...


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.


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


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.


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


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


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.


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.


I loved the GoF book back in the days. I recall it as very well written and very much directed at solving practical problems. Those properties alone set it apart from most books that I encountered during my time at the university.

Being new to Java at that time, the GoF patterns were also a very useful crutch to me when trying to learn to "walk" in the bright and futuristic world of class based OO. And it provided me with a common vocabulary that would ease communication with coworkers.

These days I find the GoF patterns to be a bit dated. A lot of it had to do with patching the shortcomings with the popular languages of the day; mostly C++ but Java had the same kinds of issues. A good deal of them could be paraphrased as "alas, functions are not 1st class citizens but as a workaround let's wrap them in an object" or "alas, our language does not readily support the common need to do X, so here is how to implement X ourselves". Someone once noted that design patterns are really language smells and I think that hit the nail on the head. The GoF patterns are really a catalog of the pain points of C++ (and similar strongly typed, class based OO languages).

In recent years I've had the pleasure of working in Javascript. Does GoF apply to Javascript? Not really. Does Javascript have design patterns? I'd say yes but there are fewer of them. Promises are really a design pattern to ease the pain of working with callbacks. Using function scope to hide private variables is a design pattern to deal with the lack of having private sections of the code. The module systems such as CommonJS deal with the lack of language level packages, and also provides a solution to isolating code in a well defined way.

Bottom line is that design patterns are not universal in any way; they are very specific to the type of language that they deal with. Also: Language designers better pay attention to the design patterns which evolve over time since each one points to a potential improvement of the language itself.


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.


Thanks for the e-mail!


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?


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


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


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.


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.


My further thoughts on this, from 2006, are in this blog article, “Design Patterns of 1972” http://blog.plover.com/prog/design-patterns.html


Two years after this was published, Domain Driven Design was released, which among other things talked about using a ubiquitous language to ensure all members of a team creating some software were on the same page. So it seems disingenuous to imply the software design community were completely oblivious of these nuances in Alexander's work.

More widely, addressing the slightly snidey remarks about C++, which form the basis of most attacks on design patterns - this idea that design patterns are snippets of code certainly did take root, and persists to this day. Even with DDD, people missed many of the more interesting 'soft' factors addressed, and walked away from the book thinking all they needed to do was rename their data access objects 'repository'.

But it's utterly useless to say that iterators as a concept are pointless because foreach exists (and whether or not the author wants to believe people are missing the point, this is the foot they launch off from). Languages with first class functions are popular today, and I still hear that you don't need the strategy pattern because of this. And yet I look at Python's urllib (literally today), and its retry mechanism is configured by supplying a value telling it what to do. It's doesn't expose an interface to make the decision yourself. Design patterns in software (whatever the ancestry of the phrase) give you a better granularity to discuss, think about and plan software design. Sure, we have more retrospective patterns, but that's as much to do with the fact that we make a ton more software than architects make buildings.

I certainly agree that we haven't, as a community, got full value out of even our own interpretation of design patterns. But I don't think it's because of any of the issues described in this talk, and I certainly don't think it's because of the limitations of our programming languages.


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?


I'm somewhat familiar with the GoF book and Alexander's A Pattern Language book and I must say, I don't really understand this post.

I wish I had the latter in my hands now for reference (it's at home), but from what I can recall, the book goes into great detail about how to solve specific problems using generalizable solutions. For example, to establish a connection between the space inside of a building with the space outside of the building, consider adding awnings with open archways to the perimeter.

The Design Patterns book, though wildly specific (possibly only because it can be), also deals with solving specific problems with generalizable solutions. For example, creating and ensuring only one instance of an object exists (Singleton - p. 127). The book outlines the motivation for this (e.g. the problem), and defines an abstract for the solution.

Also, the fact that more modern languages can more easily solve some the problems discussed in Design Patterns is, while true, seems like a bit of a red herring. Undoubtedly the patterns themselves have a lifetime of usefulness, and will evolve as we discover new ways of solving new (and old) 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 ...


Also from Norvig, same basic idea, minus the Alexander appreciation:

http://norvig.com/design-patterns/


I agree with the author's main point (software engineers should take another look at how Alexander frames the patterns in "A Pattern Language"). Obviously we should all look for common patterns and problems in our work and build up a shared "vocabulary" of approaches to those situations.

But these pattern catalogs present a risk of seeming complete. To believe that you're near completion on a list of patterns in any field is utter hubris. Alexander's own hubris at having discovered objectively "correct" architectural styles led him down a path towards obsolescence while the rest of the architectural discipline moved on. The hand wavy "scientific" surveys Alexander conducted wouldn't pass a basic social science methods review these days. Pseudoscientific methods of assembling anecdotes or interviews from small samples that don't control for sampling bias will always result in some interesting insights that can't be reliably generalized beyond the narrow scope from which they were gathered. That's what both of these pattern languages are. At best they are a handful of neat ideas that other practitioners can reuse. But these are not some sort of reliable canon. We're all going to have to do more rigorous research if that's what we want.

There might be another parallel in here about the fetishization of anachronisms. Alexander, who is an architect not a carpenter, goes out of his way to glorify hand-crafting things (literally avoiding power tools). Unless you're a carpenter who specializes in make "artisanal" works of art for wealthy patrons, I guarantee you'll enjoy the productivity gains of a pneumatic nail gun. So if you ever find yourself insisting that some old "pattern" is more pure at the expense of everyone else's productivity, double check whether your dogma is worth it.

TL;DR. Don't take patterns too seriously. Always look for new ones.


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


We need a way to explore the design space of the design space.


Design patterns are good practices that emerge when a language is used by a lot of people. That's it. Nothing less, nothing more.

There are two kinds of languages: languages that have design patterns and languages that don't have a lot of users.


So Haskell and Lisp are just lacking users? It has nothing to do with language design?


Those languages have a ton of patterns. Heck, not only they have patterns, but some of the patterns are studied to the point of having an entire branch of mathematics dedicated to them and have countless properties that can be proven about them. They even predate the language (Category Theory)


Macros that have names starting with "with-" and allocate some non-managed resource for the dynamic scope of their body are one obvious design pattern in Lisp.


"functional pearls" == "design patterns" without the architectural garbage.


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.


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


Ugh! I read the joke without realizing it was a joke.


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?


I have to agree with the OP that Alexander and the Gang of Four (GoF) approached design from very different angles. It looks to me that the two groups never shared a common vision at all.

Alexander is talking about 'spaces' in buildings, how they take shape, how they interact, and how they serve the greater style and purpose intended by the master architect to serve the lifestyle of the resident. Here design focuses on the end product and how it will function for the user. These design patterns have nothing to do with how the building was constructed or the experience of the tradesmen who built it.

In contrast, the GoF book did not talk at all about the final software end product, but only the process of building it. The emphasis is entirely on the tools of the tradesmen and encouraging their proper use and re-use. Such design patterns do not reflect the user requirements or even the architect's high level design of the software product, much less serving the user experience in a consistent purposeful way.

However it seems to me that Alexander's approach to patterns could have been adopted in the software domain, but I think that would have looked a lot more like Jef Raskin's style guide at Apple which encouraged developers to adopt a common holistic yet systematic approach to Mac software so that the user experience was served. I think Raskin wanted apps to fit together the way that rooms in a well designed house flow from one to the next -- something Alexander would endorse, I think.

Another variant on design patterns in the software that might have worked well, at a level that might have bridged Raskin to the GoF, could have been Alan Kay's model for objects. The higher level conventions for components and behaviors that Kay espoused might have made for an interesting basis for patterns like those of the GoF. But without Kay, much less Raskin, the very modest ambitions of today's notion of software design patterns led nowhere but software reuse -- an inauspicious end to Alexander's vision, IMHO.


It's been a while since I read the GoF but my recollection is that it was fairly language agnostic and also quite focussed on problems that arise when building the UI monoliths of the time. While it was an attempt to capture something fundamental it ended up, in many cases, capturing something that is more reflective of the period, including things that have to do with languages of the period, the types of applications, and the prevalence of OO. In contrast, Pattern Language, which I've also read a long time ago, naturally benefits from a broader perspective because while humans have been building software at scale for something like 30 years, we've been building buildings at scale for thousands of years.

I feel like GoF was pretty useful in a moment in time where a lot of people were facing similar problems and could benefit from canned solutions to those problems. For the most part are not the problems that I'm trying to solve today aren't really related to those monolith UI application and the tools that I use have some patterns already built into them that I tend to follow. So seems it's something that's useful to study, in the right context, learn something from, but not necessarily copy/paste patterns from.


> The problem Alexander is trying to solve 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 pattern language does not tell you how to design anything

> It helps you decide what should be designed

> You get to make up whatever patterns you think will lead to good designs

I'm not sure I completely agree with this. I agree Alexander was trying to establish a vocabulary for communicating common ideas, and I agree that his collection of patterns wasn't meant to be the one true canonical list of architecture patterns, but I do think a lot of his patterns do specifically tell you how to design things. Also much of what he wrote isn't specific to large construction projects with many stakeholders ("The Oregon Experiment", which I haven't read, is an account of the process of designing the University of Oregon campus. However, "A Pattern Language" would also be of use to a person designing their own house by themself.)

What makes A Pattern Language more interesting and intellectually honest than just a list of design rules is that he gives justifications for each pattern and tells you what problem they solve and why he believes them to be an optimal solution. Anyone else can come along and propose a better pattern that solves that problem (or a more general one) in a better way, or can provide some argument that the problem isn't really a problem in certain circumstances. There's no appeal to authority or tradition; patterns are judged solely on their merits (to the extent that we can understand what those are; architecture is strongly tied to psychology, which isn't entirely understood).

(I really wish that someone would write a book similar to A Pattern Language, but about music theory.)


In the last year I've learned a little bit about expert performance from the book "Peak" and also the Coursera course "Learning how to learn".

Experts learn to think and act more efficiently by forming "chunks" - associations between different concepts that are recalled together and can be handled as a larger unit (which reduces the amount a person needs to keep in working memory).

I think this really has a lot in common with "design patterns", which are basically "chunks" of design expertise that have been written down and can be recalled by name and shared between people.

(Also, if you haven't looked through "The timeless way of building", do it! It's a beautiful book about architecture and the role of individuals as a part of society and how our environment shapes our lives. When I open it I feel transported to 1970s Berkeley.)


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.


So, to summarize:

1) Iterators are pointless because perl has foreach. (Which entirely misses the point of why you'd want to abstract the concept of iteration from the container. (Hint: try using foreach on a tree.))

2) A bunch of trash talking about other languages type systems. (Incidentally, even when this was written, those criticisms were untrue.)

However..

3) According to the postscript, we should ignore the bogus parts I just mentioned above and just focus on the parts that are right. I'm guessing this is the "throw spaghetti against the wall and see what parts stick" school of persuasion, where you can just say a bunch of shit that's obviously wrong and then tell people to ignore those bits.

So basically, the point of this talk is "go read Christopher Alexander's book"


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.


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


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.


In a similar vein, I found Alex Martinelli's talk on design patterns very level-headed and instructive: https://youtu.be/0vJJlVBVTFg


I personally like to implement design patterns when I'm learning a new language. Last year when I decided to learn Swift I did just that. I took on ten different made up problem and solved it using one or more popular design patterns. I wrote up a blog posts and uploaded a final repo for each solution.

If you like to check it out, you can find it here: https://shirazian.wordpress.com/2016/04/11/design-patterns-i...


> 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


Fortunately C++ is finally out of the coma and now the Concepts part is being looked into. This should finally make it possible to make many patterns truly generic without excessive amounts of template voodoo. (or Boost, which is a library of voodoo) One iterator for everything that is a RandomAccessSequence, etc.

Concepts are supposed to be the Design Patterns in the sense mentioned in the slides. But they could use more user friendly names. (no, I do not mean developer friendly)


I was at that talk. YAPC in St. Louis. (WUSTL?) At the time, I didn't know much about the Gang of Four and I had never heard of Christopher Alexander. Even many many years later, this talk has stuck with my and I spent time looking up Christopher Alexander and reading about some of his ideas. Also, I told everyone I knew about him :D


I think he just means "Design principles" in the as foundational ideas that keep many decisions clustered together. E.g. "Always have a default option; if more settings are needed, make them available but hide them away from the 'main path'".


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.


  > but you got no language support as with __iter__, other than using tie callbacks.
What are tie callbacks, if not (creaky) language support?

Also the perl way would be to implement infinite streams, ala MJD's HOP[0].

[0]: http://hop.perl.plover.com/book/pdf/06InfiniteStreams.pdf


I didn't think you were supposed to copy the code out of the book. GOF was trying to define the vocabulary, and the code was just examples.


From the description, it sound like Domain Driven Design is a better fit for "a pattern language" than software patterns are.


Very interesting, a lot a truth, many design patterns have become useless in some languages as the language itself solves the problems.


Ancient cruft from an arcane language and other neat thoughts about scripting languages from 2002.


"The pattern language does not tell you how to design anything. It helps you decide what should be designed. You get to make up whatever patterns you think will lead to good designs."

Impressive insight.


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


"But the C++ macro system blows goat dick" teehee


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.


yikes.


Ubiquitous language.


title += ' (2002)'


I wholeheartedly concur with this ethos, and agree with the principle statement that it is the Language which matters, more than the patterns themselves.

Computer software is a form of literature. The most important thing is how well the language of this corpus persists. That only happens through usage.

Thus, by slide 6, I was prepared for a "because: Lisp" argument, and .. there it was.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: