Reconciling Functional and Object Oriented Programming
The Functional and Object Oriented Programming paradigms have different philosophies on how to write software. Like any ideology, they have to be applied in a concrete way to be useful. A programming language implementation has to be made, and the designers have to choose how to embody either or both of those paradigms in the syntax and semantics of the language. Some languages try to stay true to the ideal paradigm. Most mainstream languages, which make up most of the codebases out there, land somewhere in the middle. When you choose a language for a project, you often do not want to choose purely on programming paradigm - the language runtime, ecosystem, deployment options, and performance are critical considerations. Even if you favor one paradigm or the other, you often find yourself in languages that support both, working with people from both camps, and the codebase ends up being somewhere in the middle between the two.
There is plenty of content on how to write code the functional way, or how to write code the object oriented way. There is less content on how to navigate the murky area in the middle, where you will likely do both. Which things should be more functional and which should be more object oriented? Why? "Because that's the functional way" or "Because that's how we write object oriented code" are not good ways to decide. The goal of programming is to make useful, fast, correct, and maintainable software. We need to understand how each approach helps us do that, and how that fits to the situation at hand, to make informed, practical decisions about how to write code. I'm going to dive into some of the fundamental differences between the two paradigms, and see if we can gain that understanding.
Building Blocks - Functional Programming
In functional programming, the basic building block of programs is the Pure Function. A pure function is a function which satisfies these conditions:
-
Always return the same value for a given set of inputs.
-
Have no side effects.
A side effect is anything that changes the state of the system. Some examples are...
-
Changing the state of heap memory by adding or removing from the heap
-
Writing to a file or database
-
Calling an API
Functional programs are composed of Pure Functions. Function a calls, b and c. Function c calls d and e. The program will reflect the properties of its component parts - it will itself be a Pure Function. Visualizing that would look something like this:

Building Blocks - Object Oriented Programming
In Object Oriented Programming, the basic building block of programs is the Object. An Object is a self-contained entity that encapsulates state and behavior.
Object Oriented Programs are composed of Objects. Objects can communicate with other objects. In some languages and platforms that communication is via direct method calls, in others it is through message passing. Object A interacts with B and C. Object C interacts with D and E. Visualizing:

Building Blocks - The Fundamental Difference
We can already see a key difference in these two building blocks, which will end up having far reaching implications for how systems are built in each paradigm.
An Object has state, a Pure Function does not.
Software systems are all about state and behaviors. The data that we have, and the operations we can perform on that data. Some systems can be useful without storing state, but most interesting systems that we build must store state to satisfy user needs. Our ultimate goals for any software system we build are that it...
-
Has the data we need
-
Stores the data efficiently
-
Has the operations we need on that data
-
Runs the operations efficiently
Or in other words, satisfies the user needs, at the cheapest cost of memory and CPU. When two approaches to programming differ at their core about how to handle one of the key components of any software system, it is not surprising that this leads to division and conflict when folks who favor different approaches have to build these systems together. But the whole issue boils down to a more general question:
Where do we store state?
And the answer is the same answer that an experienced software gives to any question of the flavor "What should we do..."
It depends.
It depends on the particular requirements of the particular system we are building. It does not depend on the dogma of whichever programming paradigm we want to ascribe to. That leads to sub-optimal outcomes. There are times when functional programming principles help us get more efficient systems, and there are times when object oriented principles help us get more efficient systems. If your goal is to build the best system you can, then neither can be applied blindly everywhere.
Perhaps more importantly, when you reframe the question of "Should I use Object Oriented Programming or Functional Programming?" into "Where do I store state?", you change your focus from thinking about how to write code to how to build systems. A program is not a software system. It is one part. State storage transcends individual programs, and encompasses databases, file systems, networks of services - the whole system that is built to satisfy user needs. You can start thinking about how state storage choices impact the user experience. The whole purpose of programming is to build useful systems for people, and the more your thinking centers around that, the more value you can deliver.
Time to Reconcile
This series of articles is not about promoting one approach or the other. It is about how to reconcile their differences. It is about how to put them together. When to use one or the other, and what the boundaries between them are.
Now that we have an idea of the difference, and a better context for thinking about that difference, we can start to explore the practical implications on programs built with either paradigm. We will see how different approaches to state management impact the structure of our programs, and we will see how the two paradigms can be combined together to get the best outcomes for our systems.