It's very common for people to repeat that claim that Peter Norvig gave in that presentation that design patterns are work arounds for language shortcoming. This is only true for some patterns. MVC, Facade, Composite and others are obviously applicable in most paradigms. Moreover, some patterns are obviated by library improvements, such as Singleton.
The truth is that modern OOP (even in Java) doesn't many of the patterns in the GoF book any longer. That's not much of a surprise though: GoF is 18 years old. Approaches to problems have changed and the patterns used are a bit different.
Idiomatic Haskell is full of design patterns. Here's a few of the popular ones: monads, composition (of functions, not objects), maybe. When I stopped use Haskell actively, they were just getting a handle on the overuse of monads. Pattern overuse had occurred, just as in Java. It seems that pattern popularity follows the Hype Cycle (http://en.wikipedia.org/wiki/Hype_cycle)
Composite is often a work around for poor support for delegation in the language; so too is Facade to some extent. The language feature that will make MVC obsolete is less obvious, but I have confidence that one will arise.
>The truth is that modern OOP (even in Java) doesn't many of the patterns in the GoF book any longer.
Oh how I wish I shared your optimism. You still need Visitors and Factories and Singletons in Java, because the language still doesn't provide the features that replace them. At least with java 8 we'll finally be getting lambda.
Well, a Facade is very much about hiding away something that you have no control over. Even in an FP environment, you need to communicate with third parties, and they generally to a crap job of their api's.
It is, but most patterns are like that to a certain extent. I'm not thinking of a language that eliminates MVC so much as one where MVC is so easy and natural that it's not even a concept that needs a name. (Just like passing a function as a parameter doesn't really replace the Command pattern, it just means it's so normal and obvious that you don't think of it as a pattern).
I'm not sure this discussion applies to MVC as easily as you're making out. It's a design pattern, not a code pattern. Let's make it more general, though. How would a language that "gets rid" of the problem of modular code look like? That is, a language that makes it natural to organize your code based on high-level functionality, responsibility, and/or dependency? It seems to me that such a language would have to bring in arbitrary limits and introduce a lot more problems than it would solve, assuming it's feasible at all. I'm not saying this is something I've given a lot of thought to, it just has a "concept smell" to me.
There are cross-cutting concerns in software development that don't have an obvious technical solution. Modular code is one of them. There's no logical reason for us to organize code in such a roundabout way, it's only to help us measly humans reason about it more efficiently during the process of software development. So, there's unlikely to be a way to unproblematically translate that process into something logical.
A lot of the reason for MVC is to avoid mixing business logic and data. So maybe one route to making it redundant is to have the language make more of a distinction between data objects and logic objects. Scala's case classes give you a slight nudge in this direction - after a while you become uneasy at seeing a complex function on a case class, or a non-case class with lots of data members - but it's quite subtle; maybe a future language could make it harder to do these two things.
I think there's this constant tension in language design between giving you the power to do really cool things (python) and the constraints to stop you screwing up (java). But I think that more modern languages are getting further down the funnel, combining the advantages of both.
Rails scaffolding provides a language (the rails comma done apps) that sets up MVC. Rails itself has code that follows the pattern. The code you write in your app doesn't follow the pattern, it fits into it.
I don't think you can refer to function composition as a design pattern. The syntax for function composition in Haskell is so light that most of the time it's more effort to write in all the arguments explicitly than it is to use composition. Consider
lineLengths = map (length . words) . lines
as compared to
lineLengths text = map length (map words (lines text))
I don't think that monads are a design pattern either (in this I agree with Tony Morris [1]). Monads are a unified method of doing contextual computations. They are far too general to be a design pattern in themselves (how many design patterns do you know that encompass failure, error handling, nondeterminism, probabilistic computation, logging, backtracking search, mutable state, asynchronous computation, continuations, I/O...)
Monads should be more accurately thought of as an interface that is implemented by many types (in Haskell terminology, a class that many types are instances of).
I am not saying that there aren't any design patterns in Haskell - just that function composition and monads are not examples of design patterns. Instead, common design patterns include
* Writing tail-recursive, accumulating helper functions where you'd use a for loop in an imperative language:
sum xs = go 0 xs
where
go result [] = result
go result (x:xs) = go (result + x) xs
* Using strict left folds to accumulate values
sum = foldl' (+) 0
* Using runStateT and its cousins to tame stateful computations
sum xs = execStateT (go xs) 0
where
go [] = return ()
go (x:xs) = modify (+x) >> go xs
* Using a record of functions to encapsulate related functions that might be given different implementations (like a lightweight version of classes)
data Lens a b = Lens { get :: a -> b, set :: a -> b -> a }
* Using libraries like Conduit or Pipes to structure your program as a flow of data through componentized parts.
Then there are 'large scale' design patterns, like
* Structuring your code in three parts: (i) data type declarations, (ii) pure functions operating on the data, (iii) a thin I/O wrapper to glue the pure functions together.
* Using the MonadIO, MonadState, MonadWriter etc classes to keep your code implementation agnostic.
To re-iterate: I agree with you that functional languages (like Haskell) still have design patterns. But I don't think that monads or function composition are good examples of functional design patterns.
>Here's a few of the popular ones: monads, composition (of functions, not objects), maybe
None of those are design patterns in haskell. They may well be design patterns in other functional languages (probably only monads really), but in haskell they are very basic, fundamental features of the language. That is like saying classes and variables are design patterns.
No, it's a lot like saying that composition of objects (using a basic feature called "properties") is a design pattern - which it is: GoF call it Composite. The idea that design patterns have to be large and possibly overwrought elements is untrue. Composing functions _is_ a design pattern. Consider how it makes parsec different to bison.
You are just deliberately misrepresenting what they called the composite pattern to make it sound simpler than it is. Nobody said anything about things being large or overwrought, that is you bringing your bias to the discussion. Just proclaiming "function composition is a design pattern" is useless, support your claim. Parsec being different from yacc doesn't in any way provide support for the notion that function composition is a design pattern. In a language where function composition is possible, but isn't available directly in the language, then function composition could be a design pattern. And the pattern would be describing how to implement the composition operator. Given that I do not need to implement it, it is clearly not a design pattern.
> Given that I do not need to implement it, it is clearly not a design pattern.
We have a definitional disagreement: this is a bad definition. Here's what I think, straight off page 3 of GoF:
> A design pattern names, abstracts and identifies the key aspects of a common design structure that make it useful for creating a reusable [object-oriented] design.
Composite is a great counter example to your definition of a design pattern, because it is an example of an important pattern (IMO the most important in GoF) in which no special implementation is required.
PS. Calm down and stop accusing people on the internet of bad faith
The definition you quoted matches the one I gave. And as I already said, composite does require an actual design pattern. It isn't just "use properties", I think you might want to re-read the book.
P.S. If you want people to think you are making a good faith attempt at discussion, making passive aggressive douche notes like this is counter productive.
The truth is that modern OOP (even in Java) doesn't many of the patterns in the GoF book any longer. That's not much of a surprise though: GoF is 18 years old. Approaches to problems have changed and the patterns used are a bit different.
Idiomatic Haskell is full of design patterns. Here's a few of the popular ones: monads, composition (of functions, not objects), maybe. When I stopped use Haskell actively, they were just getting a handle on the overuse of monads. Pattern overuse had occurred, just as in Java. It seems that pattern popularity follows the Hype Cycle (http://en.wikipedia.org/wiki/Hype_cycle)