

Ask HN: GoF Design Patterns and Dynamic Languages - Floopsy

Hello -
Excuse me if this question is elementary, but it is something that I would like to get a better understanding about in order to be able to code more properly/etc.<p>If I understand correctly, the GoF Design Patterns were originally created to address some limitations with the object oriented approach used by Java at the time (Please correct me if I am mistaken).<p>Is it true that dynamic languages address this limitation to some extent and thereby reduce or eliminate the need for the use of some of these patterns?<p>Specifically, my questions are:
* In a language like Ruby for example, do you find yourself using GoF patterns or does the fact that the language has functional aspects/duck-typing/etc. reduce/eliminate the need to use these patterns?
* If the above is true, are there new patterns that you find yourself using?
* If one is starting with dynamic languages today, is learning/mastering these GoF patterns still a requirement?<p>My intention of course is not at all to create an argument about this topic, but rather to learn how to best approach learning programming now in 2012, specifically with dynamic languages in mind (Such as Ruby and CoffeeScript, for example).<p>Furthermore, I am not a CS student and have been teaching myself programming over the years (Started out with scripting for system admin purposes but gradually became interested in programming/development itself).  Being self-taught has its virtues and limitations.  One such limitation perhaps is the fact that I may have missed out on some of the important teachings such as these GoF patterns in a classroom setting/etc.<p>Thank you for your time.
======
tptacek
This is a good question, but the specific answer to it is unfortunately very
short: if you're writing Ruby, using GoF patterns is non-idiomatic.

In parts this is because, as Norvig points out†, many GoF patterns are
obviated by basic features of the language, like first-class class variables.

In parts this is because those features and others change the way you design
programs in Ruby. It's less common to build complex pipelines of carefully
layered objects in Ruby than it is to implement (for instance) DSL's.

And finally, in parts its because the "GoF patterns" are themselves a
misconception about pattern-oriented programming. Often when we talk about
"idioms" in a particular language, we're often just talking about patterns-
by- another- name. When the Github guys write Unicorn to do concurrency and
process management "the Unix way", they're dealing in patterns that Schmidt
and the OOPSLA/distributed systems people hammered out 10-15 years ago.
There's a lot of work that's fallen out of fashion that we're inevitably going
to rediscover.

† <http://norvig.com/design-patterns/>

------
gruseom
I'll take a shot at answering, but you should know that people disagree about
this.

The GoF patterns predate Java. They came out of a "software patterns"
movement, inspired by Christopher Alexander's beautiful _A Pattern Language_
about how to make great buildings, to capture various problems that come up
frequently in software design and formulate standard solutions to them. The
hope was that this would lead to a body of engineering knowledge that people
could learn software design from, instead of everyone having to figure this
stuff out on their own or (at best) from oral tradition. Also, the idea was to
provide a standard vocabulary for common constructs, so for example instead of
me saying "wrap" and you saying "delegate to" we would both say "decorate".

But it didn't work. Software patterns turned out to be at just the wrong level
of abstraction: too generic to be applied directly to real problems and too
specific to be good as principles. They confuse inexperienced programmers who
are told that good code makes use of patterns and so try to find ways to
organize their programs around them. That is disastrous: you get a bunch of
abstractions in your code that are not there because of the problem you're
trying to solve, but because of preconceived ideas about what good code looks
like. What's particularly bad is that the patterns are seductive: they seem to
make sense when you read them, but as soon as you get to your concrete
problem, it's hard to see how to apply them. If you're inexperienced, you
blame yourself and think you're doing it wrong, when what you ought to do is
reject the abstraction as not fitting.

People who like software patterns will say that of course you're supposed to
apply the patterns appropriately, not mechanically. But this leaves you
trapped in a circle. If learning the patterns themselves doesn't teach you how
to make good code with them, what's the point of learning them, and how _do_
you get good at software design?

People who dislike software patterns add that in many cases, the patterns
amount to mere code repetition, caused by the fact that a given programming
language isn't powerful enough to get rid of the repetition, and that the
solution is not (in PG's memorable phrase) to be a human compiler but rather
to just use a more powerful language.

In my opinion, you'd be much better off just writing real programs to solve
interesting problems. No one has a good general theory of programming. What
you want is practice. Learning patterns will fill your head with a lot of
abstract gobbledygook without telling you which bits are useful in specific
cases. Don't start with a solution or a set of solutions in mind; always start
from and return to the problem itself. It will tell you what to do, or at
least what to try. Your job is to try those things and see which ones fit -
they are the ones that solve part of the problem without adding extrinsic
complexity.

Learn your language well. Learn more than one language. Read other people's
code, especially by anyone you think is particularly good. Finally, when you
write a program, think hard about whether you could do it more simply: that,
over time, is the royal road to good software design.

And if you want to get stronger in CS, avoid software patterns and software
process and most of what's called software engineering, and just learn more
about the classics, like algorithms, data structures, operating systems,
compilers.

~~~
tptacek
This is all true, but if you haven't read Schmidt's patterns of
distributed/concurrent systems, and you keep an open mind, you might find the
approach has more value; "Abstract Factory" did more harm than good, but "Half
Sync/Half Async" is pretty good stuff.

~~~
gruseom
That may well be true. My concerns are primarily pedagogical.

I took a quick look at the work you mentioned and most of it seems to be
considerably higher-level than the GoF patterns. Somewhat counterintuitively,
that makes it less abstract. (Example chosen at random:
<http://www.cs.wustl.edu/~schmidt/PDF/lf.pdf>) That's a good thing. It means
there's more meat on the bones. The kind of patterns I'm critiquing are the
one-level-up-from-language-constructs kind, which (I guess we agree) are
different.

There seem to be some good papers in that collection. I might even forgive
them the UML!

