A pragmatic look at functional programming: The immutability orientation (Part 1/3)
Functional Programming has been getting more and more attention over the last few years. But what is it exactly? Is it just a bunch of new programming languages? Is it a different way of coding? Can it really make a difference to our business?
Three years ago we decided to upgrade the architecture of our Poker product, and we considered functional programming as an option to move forward. We needed to understand the reality behind all the hype, to determine whether it was the right move or not, both from a technical and from a business perspective.
There was plenty we liked about it, but we all agreed on four very significant aspects:
• Immutability orientation
• High level of abstraction
• Much easier parallelism
• Simpler and faster testing
In classic object oriented programming, instances are generally stateful and can be accessed and modified by concurrent threads. This is what is known as shared mutable state, which is widely regarded as the root of all evil. It can (and will) lead to unexpected state, unpredictable side effects, and unanticipated errors. Keeping shared mutable state under control is not easy; large applications tend to get more and more complex as they grow.
Functional programming is heavily oriented to immutability, which means that by default object instances cannot change and functions don’t have side effects — they simply calculate values (as opposed to OOP, where objects are normally mutable and methods almost always introduce side effects). Of course we need side effects for our software to be able to do something other than calculate values, but what tends to happen is that with FP, mutable state and side effects are well delimited and reduced to the bare minimum, and the rest are pure functions offering different views of your data.
Yes, you can have immutability and pure functions with OOP, particularly now that object oriented languages are quickly adopting functional principles. But it does not come naturally — you have to carefully (and repeatedly) enforce it, making your code complex and verbose. In the end, what typically happens is that in OOP projects you end up having plenty of mutable state and side effects, and maybe a few pure functions here and there. Functional languages are built with immutability in mind and this and other principles do not need to be artificially enforced.
In our next article we will take a closer look at abstraction, parallelism and testing.