Recently whenever I heard the phrase âmulti-paradigm programming languageâ I would sit there silently, nod and pull a confused face.
Itâs not something I had come across whilst teaching myself how to code. I just thought there was one way to programâŠ
But since Iâve started to expand my learning, Iâve come to realise that itâs important to know why we program in a certain way and why we use a certain type of programming.
Two types of programming paradigms Iâve been looking into are Object Oriented Programming (OOP) and Functional Programming (FP). They are the most popular and commonly used programming paradigms today. Weâre going to cover the key aspects of each, and compare them throughout to understand their similarities and differences.
Letâs begin with OOP.
Wikipedia defines Object Oriented Programming as:
a programming paradigm based on the concept of âobjectsâ, which can contain data, in the form of fields (often known as attributes or properties), and code, in the form of procedures (often known as methods).
To be considered an OO, there are 4 principles the programming language must demonstrate:
Encapsulation is a fundamental principle of OOP. It refers to bundling all the data and methods for a specific object into that object; essentially, making it self-contained. This is often referred to as a class in most OOP languages. The objectâs data is encapsulated which prevents other objects from accessing it directly.
Consider abstraction as an extension of encapsulation. Similar to encapsulation, abstraction âhidesâ certain details from a user, exposing only the relevant details which are needed.
Inheritance is the mechanism in which one class acquires the property of another class. Think of it like a physical trait passed from a parent to a child, like a parentsâs brown eyes passed to their child.
This is a powerful feature of OOP as we can reuse the data and methods of an existing class.
PolymorphismâŠ
Strange word, but it makes sense if you break the word down:
Poly = many
Morphism = takes different forms
In terms of programming, this is the ability to present the same interface for different forms (or data types). For example, consider a parent class called LogIn with a method in that class called handleClick. With polymorphism, any child classes of the parent class LogIn may use the handleClick method in different ways, like using it to manipulate numbers or using it to concatenate strings.
Wikipedia defines Functional Programming as:
a programming paradigm â a style of building the structure and elements of computer programsâ that treats computation as the evaluation of mathematical functions and avoids changing-state and mutable data.
Some of the key phases here are mathematical functions and avoids changing state and mutable data.
The principles of FP arenât as clear cut as those in OOP. But there are certain interconnected traits a language must have if it is be defined as functional:
Immutability is a key concept of FP. It refers to the inability to change state directly after it is created.
For example, imagine you have created an object with some data in it. With OOP, you can mutate that data - you can change its state. However, with FP you cannot directly change the data in that object. That objectâs data is immutable.
In FP side effects are avoided. A side effect is when there are any observable changes to state other than the functionâs return value.
For example, this function has no side effects as its output is contained to its return value only.
function add (x, y) {
return x + y;
}
Whereas this function has a side effect as it does more than just return a value. It has an action which something external to itself (in this case logging to the console).
function log (x, y) {
console.log(x + y);
}
In FP, there are no global variables. Instead, each function only receives its values through parameters.
The above examples are examples of a pure function and an impure function, respectively.
A pure function is one which:
The first example, the function âaddâ, is a pure function as passing in the same input will always result in the same output.
Even though this is also true for the second function, the function âlogâ is an impure function as it causes side effects outside of the scope of that function.
Pure functions are the foundation to FP.
So now that we have summarised each paradigm and looked at some of their key features, letâs compare them.
This isnât a âlets see which one is betterâ, because at the end of the day each paradigm serves its own purpose. And, as youâll see, it is possible that you could use either one to perform the same thing.
For example, consider filtering a list.
In OOP, you could do this:
const list = [1,2,3,4,5,6,7,7,8,9,9,10];
const filteredList = [];
for (let i = 0; i < list.length; i++) {
if (list[i] > 5)
filteredList.push(list[i]);
}
In FP, you could do this:
const list = [1,2,3,4,5,6,7,7,8,9,9,10];
const filteredList = list.filter(num => num > 5);
Both examples produce the same result, but just in different ways.
With OOP, the steps are explicitly defined one by one, in the order they are expected to be called. This is called imperative programming. The word imperative refers to commands. So itâs likened to having a set of commands for the computer to run.
With FP, things are done differently. In terms of how you write your code, itâs like the opposite of imperative programming. Instead of defining the steps one by one in the order they are computed, you describe the result without saying how you want to explicitly want to achieve it.
In the above example, the ES6 filter()
method is used to achieve the result of filtering through the list. This is functional programming as the code to do this returns the same output given the same output and produces no side effects (i.e. mutates list
array). Note: filter()
produces a new array, in this instance filteredList
.
One thing I love about programming is that rarely is there a time when there is just one answer to anything - it is a matter of judgement, experience and circumstance. This certainly applies to programming paradigms.
When it comes to OOP and FP, there are pros and cons to both. Some of them include:
â
Reusable code through inheritance
â
Easy to maintain through modularity
â
Flexibility through polymorphism
â Slower performance due to relative larger memory space required
â
Reduces bugs
â
Code more readable
â
Code more predictable
â Steep learning curve
â Lack readability
Well it depends on what youâre trying to solve.
FP excels in use cases where many operations are performed on fixed data. For example, in an app which you are using deep learning to determine patterns. Or maybe a CLI app which reads some input and produces some output which are consistent in their nature.
OOP on the other hand is more suited to applications that you can interact with like a GUI or API. These kind of apps often rely on mutable state and can grow to be very large and complex which is something OOP can manage well.
There are a number of OOP and FP languages:
And there are several languages which are capable of both and are therefore referred to as multi-paradigm; JavaScript and Python are examples of such.
Currently OOP is the most popular and well adopted programming paradigm, but it isnât without its flaws. FP shows promise, and there appears to be a growing view that it might be more widely adopted in the future. At the end of the day though, there is never any âperfectâ anything, and this certainly applies to programming paradigms.