Why Functional Programming?

Peter Harrison - May 29 '22 - - Dev Community

I'm late to the functional party. I tend to learn technologies which I feel help me deliver value. It isn't the first time I've been skeptical about a new technology. I'm a Java developers, so naturally this colors my experience, so keep this in mind.

Why go Functional?

The below is not an exhaustive list, but rather the advantages I've understood from the sources I've explored to date.

Safe Parallelism

The functional approach encourages safe parallelism, meaning the ability to run jobs in separate threads without getting nasty threading conflicts and modification collisions. The reason is that unlike the object approach you don't share an object with which state can be changed while you are processing. There are inputs and outputs, and the input doesn't change under you. In Java even if you use 'threadsafe' objects you can't guarantee they will be the same values throughout your method call. In the below example we see how a loop that processes items one at a time can be parallel processed with ease with a lambda function inside a stream.

for( String item : items ) {
   process(item);
}
Enter fullscreen mode Exit fullscreen mode

becomes

items.parallelStream().forEach( item -> process(item) );
Enter fullscreen mode Exit fullscreen mode

Fast Input/Output

Functional programming is supporting an approach different from threading. What this means is that we no longer have separate threads waiting for responses to I/O such as database calls. This way we maximize CPU use and throughput. For high performance applications this is clearly an advantage.

This is implemented with the idea that a call to a function can return a Future, which isn't the actual result of the call, but rather a promise to return the result at some point in the future. At some point in the future the return value is obtained which triggers the function. This means CPU threads are not waiting around for databases or REST calls to complete, and can get on with something else.

Powerful Expression

Software developers love the ability to express complex ideas in elegant ways. Functional programming allows developers to express some quite complex ideas in ways which are terse. Common constructs like for loops can instead be replaced with streams that abstract the common operations for loops are used for. There is no doubt that the addition of Lambda functions and Streams to Java have expanded its ability to express ideas not possible previously.

Why not go functional?

Just to reiterate the above points, there are benefits to functional coding, so this article is not trying to generalize this case to say you shouldn't be doing functional programming. My point is you should be doing it with a clear understanding of why and understand some of the potential pitfalls.

Difficult to intuit

When writing code are you trying to communicate with the computer? Well in a trivial way yes. But if communicating with a computer is what is important why not write in machine code? No no, computer languages are all about ways of allowing human programmers to create expressions which are comprehensible to other programmers.

As software grows larger and more complex we need strategies to manage the complexity. We achieve this through abstractions and information hiding. The class you use in Java to send an email is quite complex, but the interface to this class is simple. It hides away the detailed implementation, only exposing the control surfaces.

Features of the language such as braces and brackets communicate structure, such as conditionals and looping. Only now we are moving looping, or more correctly recursion, and conditions into functions. And so this:

for( String item : items ) {
    System.out.println(item);
}
Enter fullscreen mode Exit fullscreen mode

becomes:

items.foreach( item -> System.out.println(item) );
Enter fullscreen mode Exit fullscreen mode

The stream and lambda approach is certainly shorter. You are able to express the same functionality with less code. The issue is that we are now hiding the actual behavior inside methods which we must know. Loops in Java use keywords. Lambda functions on the other hand can implement various forms of recursion with only the name as a clue that this occurs. For example, it is perfectly possible to have this:

boo.fooble( item -> System.out.println(item) );
Enter fullscreen mode Exit fullscreen mode

The point here is that you can no longer just read the code to understand the structure. This makes trying to follow execution flow more difficult.

Another feature is function chaining, where the output of a function is the input of the next without intermediate variable assignment.

boolean result = boo
    .fooble( /*some code*/ )
    .bobble( /*some code*/)
    .goober( /*some code*/);
Enter fullscreen mode Exit fullscreen mode

For the author of this code it may make perfect sense because they potentially wrote each function and know what it does. For someone new to the code however they may know nothing about the parameters, process or return values of each function. But if you write the same in something which assigns types you get:

Car car = boo.fooble( /*some parameters*/);
Tyre tyre = car.bobble( /*some parameters*/);
int pressure = tyre.goober( /*some parameters*/);
Enter fullscreen mode Exit fullscreen mode

This is perhaps not an ideal analogy as parameters and anonymous functions are not the same, but the message here is that a long run on sentence with unknown results and parameters are difficult to read without diving in deeper to understand what the functions below are doing.

And so it is possible that functional programming is at the same time powerfully expressive in surprisingly short segments of code, yet intractable to understand for people new to the software.

The point of classes and interfaces is related to data hiding, to create reusable chunks of code which don't require the developer to understand or potentially even see the implementation to be able to use them. They exist in order for developers to be able to work with large complex systems without experiencing neural lock. They are a convenient way of organizing code related to specific entities to make life easier for developers.

I guess I'm not seeing how functional programming helps you structure large complex projects. Maybe I'm just an idiot, but then I'm about to discuss the danger of over investment in ego.

To impress others with your skillz

The last thing we need is software developers so insecure about their skills that they need to prove themselves by writing impenetrable code. As a senior developer and mentor I'm not impressed by software developers who try to write 'clever' code, by which I mean is an exercise in demonstrating how amazing they are. This doesn't just apply to functional programming of course; the same kind of thing can happen in any style of programming. But I have noted a certain intellectual conceit coming from functional programming advocates.

Bottom line is that software developers don't exist in a vacuum. That 'clever' code will need to be maintained, and if it is difficult to understand it will be difficult to read, difficult to change, difficult to debug. When running teams we have people at all levels, and so the smart thing to do is write code in ways which are easily understood. This is why we have comprehensible long variable names, why we limit the length of methods. Clever can cost. And then it isn't quite so clever.

Functional programming appears to use the same arguments around terse powerful expression that Perl did years ago. The Perl advocates were proud about how expressive it was, how they could write programs that would be very powerful in only a few lines of code. Which was all true. The problem was being able to understand them. Is functional programming falling into the same kind of trap?

Because it's the new hotness

There is always the latest hot new technology or paradigm. New technologies, languages and approaches occur all the time. We should be challenging ourselves and evaluating new technologies all the time. Being a software developer is all about advancing technology.

But as software developers we need to evaluate which technologies are needed to deliver value. Learning a hot new technology just because it's hot isn't smart use of your learning time. This isn't saying you shouldn't learn functional programming, but rather you should evaluate the pros and cons for the kind of application you are writing. Will using a fully functional programming language limit the resource pool of developers? Will it be around in the long terms or leave you on a technology island? With Java at least I know it is now in the core language.

Because it's the one true way

Many times before I seen developers promote a particular approach as being the one true way. But as a friend once said to me, horses for courses. There are different tools for different jobs. I'm using Python and PyTorch for AI. There is often many options for tools and technologies, each having benefits and weaknesses.

There are good reasons to consider functional programming for services which need massive scalability and will benefit from the parallelism safety offered by this approach. But you need to be aware of the costs and potential risks.

Years ago I had a similar experience with Dependency Injection, and how Spring was the One True Way. When I asked advocates about what benefits it brought the answers were not clearly articulated. I'm seeing a similar thing with some functional programming advocates, who appear to be on some kind of religious campaign rather than a dispassionate evaluation of the technology.

It turns out dependency injection was a great idea by the way, and I'm now able to clearly identify the benefits. Similarly I think my concerns around functional programming are related to how it is used rather than whether it is a useful and valid approach.

Conclusion

The point of this article is more general than whether functional programming specifically is something you should be doing. The real question is how you evaluate any new technology or approach. Is it easy for other developers to pick up? Is it going to restrict your pool of developers? Will it be easy to read and maintain? Will it be around in future? Will it help you deliver software? What technical issues does it help solve?

Importantly, don't allow ego to cloud your judgement. Software development isn't about proving your intellectual capabilities, your leet credentials. It is about delivering value in the real world. If functional programming helps you deliver then use it.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .