Background
Functional Programming has become a hot topic. Either developers talk about testable codes, modularization, lazy loading, or multi-threading / parallelization, functional programming often becomes a topic into the discussions. What is actually functional programming?
What is Functional Programming
Functional Programming (FP) is a programming paradigm, mindset, or style of building code in IT world which treats computation or programs as mathematical functions, the so called Pure Functions in computer science.
A pure function itself is a function where the output only depends on the input. Shortly explain: we treat a code or a program as a function f(x). The input is “x”, “f” is the function or how the code behaves, and “y = f(x)” is the output. The result / output “y” only depends on “x” and not anything else. Whenever the function is executed with same input “x”, it always produces the same output “y”, it does not matter how many times we execute it, does not matter when we execute it.
By the implication of that principle, it should avoid mutability and side effects, e.g. global or shared states, or mutable input since those could change the result “y” although we have the same initial input “x” by running the function “f”.
That’s basically one of the most basic principle of functional programming. There are still a lot of other concepts influence the evolvement of functional programming paradigm. In this article I’ll try to focus not at all but on that principle and see the benefit of it if we consider it and adopt the concept to our development.
Procedural Programming is NOT Functional Programming
Procedural programming also encapsulates codes to the so called procedures which is also often called functions, methods, or routines. However a function as a procedure is not always the same pure function introduced by functional programming since an encapsulations of codes to a function (procedure which is introduced by procedural programming) still can contain side-effect and mutability.
Benefits of Functional Programming
Testable Code (Code Which is Designed for Test Automation)
As a mathematical axiom, we can treat a capsulated program as a function:
So for a complete requirement of that program, we can treat the requirement as a list of tupels Input and Output, mathematically:
Since in functional programming we treat a program as a function where its output “O” only depends on input “I”, we can create test cases by listing down the tupels (I, O) of test cases. Of course the test completeness will still depends on the testability hierarchy of the program but since any input “I” can be passed as the input parameters of the function, we can have the best completeness of the test to have the best code coverage.
This is not always possible if we have side effects which comes from external entities or other layer, since in that case we often do not have controls to modify those side-effects value.
By having it passed through input parameter instead of side effects as a pure function, we could easily mock the parameter, even to mock behaviors as parameters, by the so called high order functions (using functions as a parameter).
By encapsulating code as a pure function (or a function which behaves like a pure function) we can have a best collection set of Input Output Tupels to have an automated test suite which have best test coverage
Modularization and Black-Box (Code with Short Methods and Classes)
Since functional programming uses the concept of pure functions, the function / the part of the code which is encapsulated as a pure function can be easily moved to other place as a black box for re-usability or for the purpose of code readability without any huge effort of refactoring like in case we use a lot of side effects in the codes.
There are several ways to do pure function in OOP (Object Oriented Programming). An example of it is by using the static method concept to mimic pure function concept. In that approach, we extract method easily to other class, keep classes always short and do what it has to do.
Do you want to have short classes for your whole codes? Have a look to adoption of functional programming in OOP to encapsulate codes as black-boxes.
Lazy loading
The concept of functional programming is by letting us pass anything as input parameter. We pass each input parameter which causes any effects of the outputs. It includes to pass behavior as parameter, in other words it let us pass a function as an input parameter of the main function (high-order function).
The function as an input parameter itself can be run freely inside the main function which take it as parameter. And this is actually the concept of lazy loading, by running or invoking the consumed function when we need it.
Multi-Threading / Parallelization
Since functional programming minimize side-effects, avoid shared variables, and mutability in its concept which make the implementation thread-safe based on the purity of the function’s implementation, it becomes more natural for functional programming for parallelization, multi-threading, or multi-core processing.
Functional Programming Features in Programming Languages
Functional Programming is a concept and paradigm, we can adopt it to any programming language. However how far or how complete we can adopt, it depends on the functional programming support for the particular programming language.
Here is a list of some most used interesting features we could check, if we want to start doing functional programming paradigm into the particular programming language.
- Immutability of variablesIt is good to check how mutability and immutability are implemented for language implementation. For example in Java and C#, primitive variables are immutable and Object are by default mutable.
- Higher order function (first class function of programming language)
Important support for functional programming in programming language is the higher order function. A language which support this by its prioritization is called first class function of programming language, to have possibilities to pass function as parameters, to return function as the output, or to have data value as a function. - Anonymous Function and Lambda expression
Higher order function are often implemented in programming languages as Lambda expression to pass an anonymous function as parameter. Checking that feature might be useful. - Generic and dynamic typed
For language which is weakly typed (not strongly typed) like JavaScript. Passing parameters to function is easier since every kind of types including function type can be done without additional effort. For language which is strongly typed like C# or Java or even TypeScript, another approach is to be taken. In C# or TypeScript dynamic type modifier is used to make it weakly typed (“dynamic” in C# or “any” in TypeScript). Or we could also use Generic Programming, to make the parameterization still strongly typed whenever we pass a function contract as a parameter. - Interface functionality for OOP
Sending a function as parameter also could be done by using interface concept as work around in case we do not have the feature to send a function directly as a parameter, e.g. working with Java 7 or prior version. Basically the function contract will be encapsulated within an interface. The input parameter contract will contain only the interface, and the real value to pass is the implementation class of that particular interface.
Adopting Functional Programming Paradigm
Besides the pure function concept the functional programming paradigm as I mentioned before has a lot of introduced other concepts to support the pureness.
The functional programming paradigm itself has been evolving from the declarative programming paradigm which uses the concept of declarations / expressions over the statements concept introduced by imperative programming. It puts more focus in structures instead of the execution orders. Not like in the imperative programming, the functional programming prefers to use recursion structures over iteration loops.
There are several levels how we could adopt functional programming in the development. The extreme one might be the purely functional programming where it tries to adopt the full concept of functional programming and avoid side effects and mutability completely.
However, not all of the concepts are really 100%-ly dependent one to each other that avoids us to adopt one and try not to adopt the others. Also there are always benefits and drawbacks of each concept introduced by the functional programming. Putting everything together and try to do everything without knowing the reason behind it is not always useful, moreover it could even cause problems. Instead we should take what necessary based on what to solve, understand the concept well, and start simple.
For instance, even of the elegance of recursions implementation, implement everything as recursions does not always make sense since recursions could also cause memory problems. That’s why people in many cases should even go for the iterations.
Implementing immutable parameters completely is also not always useful. For example, if your application is single threading and require high performance processing of large amount of data, putting effort to implement pure immutability by replacing mutable data structure which has O(1) algorithm complexity for its operations with the immutable one which has at least O(log n) algorithm complexity does not make sense.
However it might be useful to implement them as a set of functions which have clear definition of inputs and outputs without uncontrolled side-effects, so we would have them behaving as pure functions, and the codes would be more testable also support well for test automations.
However in another scenario in case if you are working for multi-core application. You might need to consider a lot about immutability and how you pass input parameters. And once we could ensure them, it becomes natural that our code fits well for that situation.
By understanding the concept of side-effects we try to maintain them not to have dirty unpredictable side-effects and use it whenever necessary.
Conclusion
As a conclusion, I would say that functional programming concept and paradigm bring a lot of benefit in code development. Use it wisely to know where and when to adopt for each concept.
Functional programming helps us to build testable codes. If you are a fan of code with short classes and methods, you should not miss the functional programming. Combining functional programming (FP) with object oriented programming (OOP) paradigm makes your methods encapsulation more maintainable and much more easier for refactoring later.
I personally love functional programming a lot. Functional programming imposes disciplines which help us to create clean and modularized codes, to create testable codes for the support of test automations. I love to combine OOP and FP together embrace their powers and strengths together in code development.
– By Efelti