The ideas of functional programming have been around for a long time. This paradigm has several key principles that, while not exactly compatible with the Object-Oriented Programming (OOP) paradigm, do have credibility and advantages in their own right. Is functional programming better than OOP? In some ways yes, but in some ways no. It really depends on the problem you are trying to solve and the best way to think about the problem. In this article I will outline why I think applying some of the basic ideas of functional programming can only strengthen your OOP code if done correctly. These are just some general ideas and are open to your own design spin. I want to also say that OOP is not weaker than functional programming, it is just a different way to look at problems.
If you have been working with functional programming and OOP, you already know that the two paradigms don’t really jive together nicely. Mainly due to the fact that OOP deals with state and that state really causes problems with function purity and immutability. Before we talk about ways to get some ideas working together, let’s first talk about a few key functional programming concepts. We will then go into why these don’t exactly fit in OOP but how we might glean some ideas from them to make OOP work better.
Well, we know that we won’t necessarily have pure functions in an OOP class because that function will likely operate on class variables… aka class state. These values can be manipulated outside of the current method by other methods in the class (or in the case of public class variables, maybe even another part of the system). However, we can glean the idea that if we strictly control access to class variables, and possibly look to not even using them, then we can strive for purity. We can do this by first defining the function to work locally and only when other methods in the class ABSOLUTELY need to share a state, then promote the appropriate variables to the class as state. This is in contrast to putting in class variables from the start, even if only one method uses that state.
What about functions as first-class citizens and composing higher order functions? Well, I don’t see much of a problem here in OOP. In theory you could pass a reference to one method to another method and call that method as a callback or a standalone function. You could even define some other function outside of a class and pass it to a class method which takes a function as a parameter. Now would you do this with methods defined in the same class instead of calling them directly? Possibly. The idea is that if the method was generic enough, that method could take any function (defined in the class or not) and it should still work. If it is a private helper method, it might make more sense that it receives another private helper method and works with it than calling the other helper method directly. The goal here is reusability and building up these higher order functions where the low-level functions can be used in other projects.
As for variables being immutable, again state is often meant to be changed by more than one method. State is all about change. Again, if we reduce our reliance on state variables we have half the problem solved. The other thought is that if we can apply strict rules on when state can be changed and what values that state can have at any given time, we can almost treat state as immutable. For instance, if we say that cars can only have 4 wheels, anything that violates that rule should not be allowed. Then we treat that variable as if it was immutable. Or that it is mutable but only with a finite set of known states. This could be maintained by strict setter methods of a class that evaluates the state change and absolutely forbids any changes that violate the set of rules for a given variable. Setting wheel count to 5? Nope! Not going to do it.
Lastly, what about referential transparency? I think this is perfectly doable. However, if you are working with state in a method, and even if that state has a finite number of values due to strict control, referential transparency would still be violated as the same input may lead to different outputs and thus you can’t replace calls to a method with a known result in all situations. But you could still strive for this, especially for static methods. However, to truly do it you would need to keep state (and any side effects) out of the method… period.
I already mentioned above a few tactics and trains of thought we could use to help integrate some of the ideas of functional programming into our OOP world. Here I would like to help solidify some of the thoughts around some general themes. Even if we can’t implement these 100%, I believe that incorporating as much as possible of the idea into our OOP can only help strengthen our code.
We talked about some of the basic ideas behind functional programming and how the ideas behind some of them might be used to strengthen OOP code. We talked about pure functions and immutability and how we can look to avoid elements in OOP that might violate these rules… primarily class state. By knowing some of these concepts and looking to get as close as possible to implementing some of these ideas we will find that our OOP code will take on a functional programming flavor that should lead to stronger methods and overall stronger classes. Encapsulating our class state and then putting severe restrictions on how state is managed (looking to avoid state if possible) can lead to methods that exhibit functional programming strengths that may prove useful even in a class context.
I hope you found this article interesting and help improve your code in the future. I enjoy some of these ideas and look forward to implementing many of these concepts in my future coding projects. Thanks for reading! 🙂