Applying Functional Programming Ideas to OOP

Functional programming in OOPThe 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.

What Are Some Core Tenants of Functional Programming?

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.

  1. Pure Functions – This concept states that functions should receive some input, work on only that input and return output… the same output for the same given inputs. This harkens back to mathematics where a function. Let’s say we have the function f(x) = y. This takes an input x and returns y. This is what makes it pure. In this sense a pure function is more of a transformative feature that transforms one value to the other and nothing more. It doesn’t write to a file or database, it doesn’t log anything, it doesn’t print to a console or modify variables outside the scope of the function. All of these extra tasks are often referred to as “side effects”. It also states that given the same value of x you will ALWAYS get the same value for y. Not sometimes y and sometimes z depending on some external factor.
  2. First Class Functions – This simply states that functions should be able to be passed around and called on like any other variable. That functions can then be passed to other functions to form what is known as higher order functions. Think of things like callbacks or closures. Many languages support this and you have probably already seen it.
  3. Variables Immutability – Once a variable has been declared and assigned a value, it is not to be changed. Think of things like constants. If I assigned the value 4 to the variable wheels_on_car you should not be able to change it later to 5. You can copy the value to a new variable and operate on it, but not on the original input.
  4. Referential Transparency – A fancy way to say that wherever you call a function, you should be able to replace that function call with the function’s result and the code won’t break. Given our example in the previous point, if we have a function getNumberOfCarWheels() that returns 4, we should be able to replace all function calls to this function with the value 4 and it won’t break. I find that if you observe purity and avoid relying on any values outside of the function, you should be pretty close to having referential transparency.

What Ideas Can We Glean From Functional Programming to Use in OOP?

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.

How Might We Use These Ideas Anyways

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.

  • Strive for purity. Think about the values a method takes in and the values it returns. Keep them free of side effects as much as possible. We all know that side effects are inevitable, but maybe regulate side effect use to a few key methods only. If we think of the inputs to our methods as constant and that we limit our use of state, we can get pretty close to creating pure functions/methods. This also means that we don’t reuse our input variables (copy them if need be and assign to new variables). Look to avoid using state defined variables by first defining them locally and only promote them to class level if needed by multiple methods. You might be surprised how easy a method may become if you keep state out of it and you define the method’s goal well. Lots of code bloat comes from dealing with external entities just because of error checking alone.
  • Strive for first class function/method use. Look for method synergies that allow you to compose methods that are made up of other methods/functions being passed to it. This might work better in the realm of private class method helpers, but anywhere you can compose a higher order method, you should try to do it rather than calling methods directly. But before you flame the idea, I will say that it really depends on design and if you think possibly a function defined outside of the class could be passed into the method too. If you think it makes sense in that regard, then higher order methods could be an idea that works great.
  • Strive for immutability. Look to possibly have class variables set as constants. If they can’t be constant, strictly control the access to that state using setter methods that regulate the set of values that a class variable could implement. You should look to have the possible value set as small as possible. While not truly functional programming immutability, at least having a small value set of well-defined values can be thought of as not changing frequently or limiting their mutability. Obviously using data types that are also immutable by nature (like tuples) will also help enforce this.
  • Strive for cutting out side effects. Limit state, limit calling on anything outside of what a function is given and this will all certainly help. One great way to know if this is a problem is to go back to the idea that if given a certain value as input, can anything you are doing possibly result in the output not being the same? If the answer is yes, you probably have a side effect. For instance if you give a method the value 4 and depending on what you read from a database the returned value can be 8 or 12, then you know you have a side effect.

Conclusion

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! 🙂

About The Author

Martyr2 is the founder of the Coders Lexicon and author of the new ebooks "The Programmers Idea Book" and "Diagnosing the Problem" . He has been a programmer for over 25 years. He works for a hot application development company in Vancouver Canada which service some of the biggest tech companies in the world. He has won numerous awards for his mentoring in software development and contributes regularly to several communities around the web. He is an expert in numerous languages including .NET, PHP, C/C++, Java and more.