
A design pattern is an artifact of a missing feature in your chosen language - bensummers
http://www.snell-pym.org.uk/archives/2008/12/29/design-patterns/
======
gruseom
One of the things that originally caught my attention in a PG essay is a point
he made about design patterns: if you're writing the same code over and over
again, you're being a human compiler. I distinctly remember the shock of
reading that; it was like someone poured a bucket of ice water over my head.
It wasn't just that I recognized it as true. I recognized it as indicating the
existence of an alternate programming universe that I knew nothing about.

~~~
wwalker3
The "human compiler" bit never made sense to me. When I start to write
something for the second time, I stop and make it a function (or a class,
interface, library, or whatever's appropriate). "Don't repeat yourself" is
good advice in any programming universe.

~~~
randomwalker
That was the point of the article. A design pattern is a sign that your
programming language lacks an abstraction that makes it impossible not to
repeat yourself.

~~~
wwalker3
Could you give me a concrete example? Say, a pattern that can't be abstracted
away in assembly language, but can be abstracted away in C++?

Serious question, not a troll -- I've always felt like I'm missing some key
point here.

~~~
jules
For example the "there aren't enough registers so I put some data on the
stack"-pattern. You just don't have that in C++.

Or getting the result of an expression into another expression, like

    
    
        (a+b)*c
    

You have to write that as

    
    
        x = a+b
        y = x*c
    

In C# people regularly play the human compiler when defining getters&setters
(or maybe their IDE does it, but you still have the noise code on your
screen). Or when mentioning types everywhere when the compiler could infer it
(although it's better now with the var keyword).

~~~
rbanffy
During college I designed a processor that could do that. It would read like
this (assuming A, B and C were constants representing memory addresses
pointing to integers):

$300: $(A) $(B) ADD $(C) MUL

And the result would be at the top of the stack.

Not all assembly languages are created equal. ;-)

~~~
klipt
That has more in common with Forth than most assembly languages though.

~~~
rbanffy
That's what I liked about the machine. When I realised that, if I designed a
microcoded stack machine, I could make it run something very close to Forth in
the 4 months I had to finish it, I knew I had to do it that way instead of a
more conventional design (I took some implementation ideas and the assembly
syntax from the 6502).

In the end, I wrote an incomplete Forth compiler for it, but I don't know
where the floppies I wrote them to ended up.

------
iron_ball
I despise the constant knee-jerk reaction to "design patterns" as "scripture."
There is a sizeable contingent who cannot accept design patterns at all, in
the belief that design patterns are used only by -- in some nearly literal
sense of the term -- religious zealots.

These people will eventually code an Adapter, but presumably they will not
call it that.

~~~
alaricsp
I think it's a knee-jerk reaction to how the more zealotous members of the
design patterns community have had knee-jerk reactions to people questioning
the scripture status of the Design Patterns book.

Once a bunch of people get religious, another bunch of people will crop up to
get religious against them in turn.

I think design patterns are useful and valid; but I think they should be
evaluated individually within the context of a given programming language, not
necessarily considered global.

------
andreyf
_because one of their fundamental tenets is that patterns cannot be
represented in [the] code [of a particular language]_

There. Fixes everything. Patterns are great, because they tell a language
which way to evolve. They're even better, because they give those stuck in the
"programmers program"/"language designers design languages" state of mind a
chance to jump into the "I make computers do things" state.

------
tnovelli
I tend to agree with Alaric here, but reading this inspired me to take a look
at design patterns, ironically.

I've never studied design patterns per se in my two decades of programming
(mostly lone hacking) and I think it's about time I took a brief tour of 25+
patterns I'm likely to stumble upon or reinvent anyway, and learn _names_ for
them. Then I'll question everything and use my own judgement, as usual. (Is
there a good non-dogmatic book on the subject, or does
[http://en.wikipedia.org/wiki/Design_pattern_(computer_scienc...](http://en.wikipedia.org/wiki/Design_pattern_\(computer_science\))
do it justice?)

------
lsd5you
He could make a stronger case, by posting an example. Even then he would be
trying to prove a negative - i.e. that there is no design pattern that isn't
overcoming a language flaw.

What about the much maligned factory pattern. It boils down to a method that
provides an implementation, and can be considered (when not misused) a single
point of configuration in an application. (e.g. switch the factory to use html
instead of pdf).

My view was always that people could learn patterns much the same way that
they can learn a 2nd language. That is end up with a high level of knowledge
about the grammar/patterns but not be able to use them fluently.

~~~
andreyf
_What about the much maligned factory pattern_

If classes are first-class variables (as in Python, and now even Java (I
think)), this is replaced with a constructor which takes a class as an
argument.

~~~
mhansen
Then you aren't gaining anything over simply calling 'new' on that class,
negating the point of the factory pattern, right?

~~~
orangecat
The point of the factory pattern is that you don't always want a new instance,
and you don't always want a specific type. "new Foo()" necessarily does both,
while Foo.new() can potentially do neither.

------
10ren
He makes a thought-provoking point about a _GOSUB or CALL_ being a design
pattern, that _explicitly saves the calling location somewhere and then jumps,
and a RETURN_ , but I disagree with this specific example.

In Z-80 assembly, the return address is implicitly saved on the stack. Sure,
it's not structured, meaning that you can call into code at any point (not
just at the start of a procedure). One big difference is that the language
construct doesn't pass arguments (and I don't think it saves save registers on
the stack either - but my memory is fuzzy on this point).

~~~
spc476
In assembly, a design code would be (and here I'm using the Intel 8086 as an
example) pass pointers to structures in BX, pointers to strings (or arrays) in
SI, CX will contain sizes or limits, DI will point to destinations (say,
copying something, or accepting input) with AX and DX used for anything else.
Returning data---carry flag clear means success, if set, AX will contain an
error code. Other registers may be updated depending upon the function.

That's a design code in Assembly. Move to a Motorola 68000, and well, it
changes somewhat---pointers are passed in A0-A5, other data in D0-D7. You can
still use the carry flag and say, D0 for error codes.

Move up to C, and the details about passing parameters to a function go away
(unless you are mixing Assembly with C, and even then it can be isolated). I
just give the parameters to the function and it's up to the compiler to stuff
them into proper registers or on the stack or how ever it's done on a
particular architecture.

Now, object oriented programming in C---another design pattern. Declare a
structure with pointers to functions, and always pass the pointer to the
structure to functions called via the function pointers. Again, the programmer
is aware of the details. IN C++, the compiler handles those details.

------
mikeryan
Where did this title come from? I read that and got all up in arms but then
read the article and that wasn't really what it was saying.

------
dnaquin
One of the things I'm really liking about ruby during my python to ruby
conversion is that it handles the visitor pattern for me.

Half the Java code I ever wrote was probably visitor pattern cruft. Ruby
largely just handles it all for me.

~~~
blasdel
What are you doing in ruby that you weren't in python?

~~~
dnaquin
I can write methods that take blocks.

Sure I can do the same thing in python, but I either have to write a lambda
that limits me to a single line or write a one-off named method. The latter
being much less clear than do ... end.

~~~
swolchok
"visit_foo" as a nested function definition, immediately before it's used in a
function call, is not particularly unclear.

------
wglb
So I am wondering how we got to the opinion of "because one of their
fundamental tenets is that patterns cannot be represented in code". Seems
quite odd.

------
mbenjaminsmith
Exactly, I was recently considering writing a @tryandfailsilent. Would save a
bit of time and space.

------
spooneybarger
really only skims the surface of the idea which is too bad. there are a number
of similar pieces out there that tackle the subject in depth. i'd link to
them, but i'm feeling lazy and don't want to go tracking them down.

~~~
alaricsp
Nowt wrong with skimming a surface, sometimes you can get more impact with a
one-page summary than a long essay :-)

~~~
arakyd
In this case your better off just reading Norvig's original presentation.

------
lucifer
My take on this:

1 - Patterns address (and are formulated using) the semantics of intent. They
can not address domain semantics; that is addressed in the specific
realization of a given pattern (which some would consider "redundant code" but
that is not strictly speaking, correct).

2 - In a meta-reflective language (type i) (such as LISP) patterns are
expressed as (reusable) macros. In languages that lack the ability to extend
the compiler (type ii), patterns are expressed as specifications. So
regardless of the expressive power of a type-ii language, there will always
remain the possibility that a pattern can be identified that would require an
extension to that language's expressive power.

~~~
reeses
In re (2), not always. For example, the Visitor pattern is one that is
specifically eliminated by basic functionality in languages that support
multiple-dispatch. No developer extension of compiler or language needed.

