Recently, design patterns are terribly popular, especially on job interviews, so let’s take a look at its Wikipedia entry:
In software engineering, a design pattern is a general reusable solution to a commonly occurring problem within a given context in software design.
A prerequisite for truly assimilating patterns is to have a prior background: having experience the problem in its context and, somehow solved or sidestepped it. Ideally, when you read about a pattern, you should recognize it as an acquaintance you have met before. However, you can get more or less amazed about how close your solution was to the canonical one.
From this point on, the newly acquired pattern will yield dividends. Not in the form of letting you solve a problem you couldn’t previously solve since you need that prior experience to really embrace the pattern. True dividends include faster problem identification, easier communication1 and being able to implement a less idiosyncratic solution.
Functors and monads are very common functional programming design patterns and they are waiting for you to carve them out of your code pretty much everywhere. Once you get familiar with FP and read about these design patterns2 you develop the same intuition about this that about when to use a singleton.
I want to illustrate this with a recent example from my day job.
First, imagine you have some piece of data
Foo that is obtained by a
fallible polling from a remote server and you should track if your cached data
is fresh or stale. It is reasonable to use a
Boolean for this purpose at
Later, you add another piece of information
Bar with similar
After this change, you realize that the design is taking a wrong course: you
have duplication and primitive booleans spreading to more and more
places3. So you replace the plain
Boolean with the richer type
To remove the duplication we could introduce a generic type
will allow you to annotate anything with freshness information:
Now your spider-sense goes off yelling like mad at you, “monad! monad!”. In
practical terms a monad can be seen as any container or context holding
information (i.e. with one generic parameter) that supports and implementation
flatMap4 that won’t surprise you.
If you add those methods to
Cached[T] then you can transform cached values
without losing the information about freshness.
And you can also combine cached values using the expressive comprehension syntax having guaranteed that the result will be fresh only if all the inputs are fresh.
You can take a look at the completed
No silver bullet
Design patterns, functional or OO, are not silver bullets that you can harness just by invoking their names. You need to invest time gaining context and studying them before getting your spider-sense tuned for helping you when to use them.
Software development is a social endeavor after all. ↩
If you approach this by reading a monad tutorial as the first step you are doomed. You need to get some field experience on FP and only then, chase the monad. ↩