Functional principles for object oriented development
I came across a great talk from Jessica Kerr titled “Functional principles for object oriented development” or something along those lines. There are a few variants of the talk. The ones I’ve watched are delivered at a good pace and I think would really benefit anyone looking to learn about functional programming. You can find one here and another one here. There are more. You could also take a look at her blog or follow her on Twitter. This is an attempt to illustrate the concepts she put forward as I understood them using C#. This post only scratches the surface of the talk so I’d highly recommend watching/listening to it.
- Data in, data out
The idea here is that most of our programs should be composed of functions whose output is entirely based on their inputs. These functions are generally easier to test as there is little mocking required and no hidden dependencies. They tend to be easier to understand as the signature tells you the prerequisites and the outcomes. They also provide referential transparency. This basically means that you can substitute a value for the function call.
You can see that the output of “GetMilesPerGallon” is entirely dependent on the inputs. If the answer today is 42 for a given set of inputs, it will be 42 anytime you call it with the same input. For something more computationally expensive you could actually perform the calculation in advance and cache the result.
2. Verbs are people too
With this we want to recognize functions as “first class citizens” in our programming model. This means that you can pass them as parameters and they can stored in variables (i.e. generally appear on the left hand side of an assignment operation). This is a given in pure functional languages and since .NET 3.5 has been possible in C#. Hopefully, the example below illustrates this.
3. Specific typing
This is about making the code more expressive (business critical code in particular). This is akin to the concept of coding in the language of the domain. In a compiled language like C# this gives us the possibility of catching more errors at compile time.
4. Declarative style
This is about writing code that states what needs to be done and leaving the underlying implementation to determine how to do it. This makes the code more readable. It also encourages us to code in smaller chunks.
The premise here is that functions should not alter the state of their inputs. They should instead yield the result of some operation applied to the input. Use of immutable variables aids comprehension. It offers a guarantee that the value will remain the same no matter how many times it is reference, how deep in the call stack it occurs or even when it is accessed. This means that it can be accessed concurrently without the need to employ locks or alternative synchronisation mechanisms. The code below shows once constructed an instance of the class cannot be mutated. If one needs an instance with a different value then a new instance must be created.
6. Lazy evaluation
The aim is to delay execution until the last possible moment. Basically, it shouldn’t matter when the function executes. This means we can specify what to do separately from when to do it. In the example below “numberIsOdd” is only execute as “sequence” is enumerated. In addition, it is only evaluated for the first 10 numbers in the original sequence even though there are 100 elements in it.
That about wraps it up. As stated early this is a quick overview using trivial examples in C#. It is more of a note to self. If it helps anybody else, even better. The actual talk has a lot more depth and more realistic examples.