“Elements of Reusable Object-Oriented Software” is a book that I am sure all self respecting software developers have read. The infamous Gang of Four book seems to shape everything we do in modern object oriented software development and by applying the principles contained within generally results in a quality software product.
One common (but slightly controversial) view on design patterns is that generally they only exist to patch up any shortcomings of the language. If a language can solve a problem in a trivial way then it may well have no need for a design pattern at all. This can be demonstrated by developments within the .NET Framework, for example the “Iterator” design pattern is embedded within the language through the IEnumerable interface, reducing the need to implement the pattern yourself.
Microsoft F#, due to ship with Visual Studio 2010, is primarily a functional programming language and supports all the features you would expect, such as functions as first-class values, currying and immutable values. As F# is fully integrated into the .NET framework it can also be used in an imperative or object oriented way.
So in a multi-paradigm language is there a need for software design patterns? Do we need to worry about design patterns in F#, and if so how do we apply them.
Some articles I have read recently have gone so far as to suggest that the design of functional languages eliminates the need for design patterns completely. This is however only partially correct.
There are some design patterns that are rendered obsolete by functional languages, take the Command pattern as an example. The Command pattern as documented by the Gang of Four enables you to:
“encapsulate a request as an object, letting you parameterize clients with different requests”.
This is simply an approximation of a first-class function. In F# you would simply pass a function as the argument to another function.
In an object oriented language, you have to wrap up the function in a class, which you then instantiate and pass the resulting object to the other function. The effect is the same, but in the object oriented world it's called a design pattern.
The same can be said about the Abstract Factory pattern. The Abstract Factory enables you to:
“Provide an interface for creating families of related or dependent objects without specifying their concrete classes”.
In F# this is known as currying. Currying is the process of transforming a function that takes multiple arguments into a function that takes just a single argument and returns another function if any arguments are still needed.
It is clear therefore that several design patterns are rendered redundant in F# because the language provides more powerful, succinct alternatives. There are however still design problems that are not solved within F#. There is no F# equivalent for the Singleton pattern for instance.
Interestingly it works the other way too. Functional languages have their own design patterns; you just tend not to think of them that way. You may have come across “Monads”, which are a kind of abstract data type and often used for handling global state within functional languages. This is a problem that is so simple to solve in object oriented languages that there is no equivalent design pattern.
So while it is true that some object oriented design patterns become redundant in functional code, many, such as MVC do not.
So if you’re working with F#, don’t forget about design patterns, you never know you may even come across some new ones.