Because it gets things done.
Like most people I am the kind of person that gets really bored when I have to do unnecessary avoidable things. As a side effect (fp ppl will get it) I work very hard to avoid being in a situation where I’m forced to do unnecessary things.
For example I don’t like waiting in lines or being stuck in traffic so I mostly work remotely and I don’t like spending unnecessary time trying to determine the correctness of code or to make it modular so I use functional programming. I have a Ying and Yang thing going on there. I need to mention that I operate mostly in the JVM area so at the moment it’s FP in Scala for me
Some might say.
- You don’t need FP to have correct code.
- FP “sux” because it’s slow, hard to learn,…
To them I answer: It depends (Isn’t this the universal answer on any question that has room for interpretation? Except for is JS bad because we all know the answer there.)
ZIO architect John De Goes claims FP is faster in the “large” while non-fp is faster in the “small”.
From my experience that claim is accurate.
What experience is that you might ask?
I’ve been developing software from 2007 and for the past at least 10 years I have designed and developed from scratch at least one medium sized project a year. I used OOP (as it’s understood in the wild), OOP (as it’s understood in the classroom), Actors (which is basically OOP on steroids) and FP (which is FP). I mainly used Java, Kotlin, Scala for backend and JS for frontend.
Why don’t I have any Github projects up?
MY DISCOVERIES ARE MINE, I’M NOT SHARING ANYTHING, I’LL LET THEM WRITE AWFUL CODE WHILE I WRITE THIS BEAUTIFUL AWESOME ONE ALL BY MYSELF MWAHAHAHAHAA. Just joking. Had I known that later on I will want to write an article and need that for credibility I would have. Joking again.
I did not do that because I was in a looking for answers phase.
Many paradigms show you the nice parts but don’t really know how to present the hidden costs very well. Most presentations and examples are on very simple and sterile scenarios. In real life you end up following “best practices” and see that the code is not all that it could be. The best practices of yesterday are avoided tomorrow. And nobody seems to notice the unnecessary effort being put in with diminishing returns or worse think that it’s normal. This is why sometimes rewrites happen. Because development puts the project in a corner with no way out and changes become more and more expensive, sometimes shortcuts are used that further aggravate the problem long term.
I know because on several occasions I was the guy that was brought in to do the rewrite and saw the mistakes that caused the need for rewrite.
Now did this happen because OOP is bad, or the programmers were bad? OOP projects are done and work fine every day and blaming the programmers is a cop out (they can’t all be bad, or maybe could it be that the tools they have make them deliver subpar software).
I think that the issue is the fragility of non modular/non composable software and that it’s harder(not impossible) to achieve modularity in OOP thus increasing the risk of failing for OOP projects.
I wrote OOP, I wrote more OOP than FP. I watched uncle bob’s videos (love them btw), I read the OOP books,…. With completely defined & detailed specifications the increased fragility I mentioned above is not that obvious.
But life is not all sunshine & completely defined & detailed specifications. You see priorities shift, people turnover, enhancements, long periods between looking at the same area of the code, changes in direction.
My experience tells me modular design is better at absorbing those “shocks” than non modular design and FP is better at modular design than OOP.
To the crowd that would say “you are just not doing it right”/“go away” I answer “maybe the doing it right in OOP is too expensive to be viable”/“you go away 😛”
You can achieve modularity easier with FP. You can prevent unsound states easier in Scala using FP design principles.
FP gives you back control in a dynamic world. (I said dynamic not chaotic, if your workplace is chaotic change it and thank me later). I love dynamic environments when using fp. Every new feature becomes a new cool problem with a principled solution and you get the good feeling that the user will get something done right. It’s just another piece in a lego.
Having developed at least a medium sized project from scratch every year for the past 10 years, many smaller projects and lead several teams of different size I picked up a few “heuristics” relevant to this point:
- The less modularity the more complexity. Complexity is bad is an understatement and is much higher in non modular code.
- The less modularity the more coupling. Coupling is the devil.
- The less modularity the higher the refactoring & evolution cost. Change is more expensive in non modular software.
- Productivity increases with modularity. Lower cognitive load, context switching, local reasoning — these all add up bigtime.
The downsides mentioned above increase non linearly with the size of the project and the number of people added to the project.
In closing I will tell you what I am using now with great success so far.
Scala + ZIO
I was using Kotlin+Arrow (which is a very good fp library for kotlin hope it grows and does well) prior to the release of Bifunctor by John De Goes. After that I made the switch to ZIO in my smaller personal projects and now I use it everywhere. There are so many things done right in ZIO that it’s a blast. I have yet to unlock all it has to offer but you can be very productive with it even if you only use the basic building blocks.
Have fun coding!