Functional Programming
School of Tought
Object Oriented Programming (OOP) is a school of tought. Done right is not a bad one. Functional programming is another school of tought. Also, if done right, it can be good. Any engine engineer can code in any language. However, to take advantage of it, you must go deeper to fully understand the school of thought and how to properly operationalize it in production. Which sometimes, in fact, is one of the barriers to new languages.
Functional programming has two main branches: Lisp and Haskell. Clojure comes from the Lisp school, and Scala comes from the Haskell school. Both are functional programming languages, but they have very different approaches. For instance, Clojure is very into dynamic programming, like you would with OOP languages like Ruby. Scala, which takes the Haskell approach, is the opposite; it is all about leveraging type systems, complex type manipulations via higher-order functions, higher kinded types, monads, and other generics patterns, but all boiling into the compiler.
IMHO, There is no better school than Tought. I like both; it's all about the teams and people you have and your passion for learning new things. Good engineers will continuously learn new languages and ways of tought, even if they don't use production that POC in V or Idris will pay off in the long run.
State Misinterpretation
The state is something people often get wrong in functional programming. Functional programming favors immutability, yes. Even if you are doing OOP you should favor immutability. Having a state is not bad; now, having an indiscipline state that's where it can be pretty bad. Shared state is a problem even outside of functional programming; let me give you a list of bad examples of shared state:
- Shared Database: The most obvious and yet form of indisciplined state, which leads to distributed monoliths. Pretty bad and the source of many problems at scale. Resource contention, Scalability issues, Availability issues, Ownership issues, and many other problems.
- Aspect-Oriented Programming: IF you create a central aspect to enforce rules and behavior across all your classes, you have code that is not obvious and can be hard to test and maintain.
- Global Chained State by Reference: Create a global variable and pass it by reference to 3-5 methods, and you already have very difficult code to understand and refactor.
Functional Patterns
OOP, we have design patterns, but FP is not different. There is a combination of some types of classes plus functions you need to implement. But we can summarize the functions you need to implement. So, functional programming patterns are all about functions. Here is a simple summary:
For the sake of comparison, if we trace a parallel with OOP. Let's say you have to have a value that doesn't change, and when consumers read that value, it should always be the same; we would create a Singleton, which in FP could be ReaderMonad. IF you are using Scala, you have both schools of tought at your disposal and can even combine the patterns.Complexity and Performance
The more abstractions you get, the more impact on performance you will have. Do not think abstractions are for free. Build time and execution time in production can be a problem. Always check the generated assembly and perform performance tests and benchmarks to ensure your abstractions are not killing the performance.
Complexity is another very interesting tradeoff. If everybody knows Haskell, having monads might be fine; otherwise, you can have a simple and grounded abstraction that people can understand and wrap their heads around. Either way, there will be a cost for people to understand and get used to it.
Influence on Modern Engineering
No matter if you are into functional programming or not, no matter if the language is a functional programming language or not, we see and tend to continue to see lots of influence from functional programming in new languages like Kotlin, Typescript, Rust, and many others.
Cheers,
Diego Pacheco