My Journey from OOP to Functional Programming

When I first started coding, I was firmly rooted in object-oriented programming (OOP). Like many novice developers, I believed that functional programming was simply about using functions instead of objects and methods—a relic of the past, overshadowed by the dominance of OOP in modern frameworks. After all, everywhere I looked, it seemed like OOP was the gold standard, with most frameworks heavily relying on its principles.

But then came React.

As I delved into React, I noticed a significant shift. React, a framework I initially approached through an OOP lens, was moving away from its OOP roots and embracing functional programming. This shift piqued my curiosity. If functional programming was outdated, why was one of the most popular frameworks in the world adopting it?

This question led me down the rabbit hole of functional programming, and what I discovered completely transformed my approach to coding. To fully grasp the philosophy and power of functional programming, I turned to Grokking Simplicity by Eric Normand. This book was my guide, breaking down complex concepts into practical, understandable insights.

I quickly realized that functional programming wasn’t just about writing functions. It was about writing code that is cleaner, more predictable, and easier to maintain—traits that are increasingly essential in today’s fast-paced development environment.

If you’re curious about functional programming or ready to challenge your own assumptions, I highly recommend Grokking Simplicity. It’s not just a book; it’s a mindset shift that can fundamentally change the way you write code.

What is Functional Programming?

Functional Programming (FP) is a programming paradigm that treats computation as the evaluation of mathematical functions. It emphasizes immutability and avoids changing state and mutable data, aiming to produce predictable and reliable code.

Key Goals of Functional Programming

  • Immutability: Avoid changing data once it is created.
  • Predictability: Ensure that functions produce the same result given the same input.
  • Side Effect Elimination: Minimize or eliminate actions that alter the program’s state or interact with external systems in unpredictable ways.

In FP, a side effect is any operation that depends on or changes external state and can produce different results when executed multiple times. Functions that cause side effects are known as impure functions.

Examples of Side Effects

  • Modifying a Global Variable
  • Writing to a File
  • Modifying a mutable Data Structure
  • Printing to the Console
  • Changing the State of an Object
  • Network Requests

But Aren’t Side Effects Essential?

While functional programming strives to minimize side effects, it’s important to recognize that side effects are often necessary to achieve real-world functionality. Programs are created to perform useful tasks, and many of these tasks involve interacting with external systems, like reading files or handling user input.

The Goal of FP: The aim isn’t to eliminate all side effects but to manage them carefully and limit their impact on the predictability and reliability of the code. By isolating side effects within controlled areas of the code, FP helps ensure that the core logic remains clean, testable, and robust.

Why is React’s useEffect Named That Way?

The name useEffect highlights its role in managing side effects. It helps keep them under control and ensures they’re handled in a way that maintains the predictability and reliability of your components. Essentially, it’s about ensuring that effects are used wisely and don’t disrupt your app’s core functionality.

“In functional programming, the idea is to express your problem as a combination of simple, stateless functions that are easier to understand, test, and maintain.” — Grokking Simplicity

The Core Ideas of Functional Programming

1. Pure Functions:

A pure function is a function where the output is determined only by its input values, without observable side effects.

Example: A function that adds two numbers is pure because its output is always the same for the same inputs and does not modify any external state.

function add(a, b) {
  return a + b;
}

“A pure function is like a vending machine that gives you the same candy every time you press the button.” — Grokking Simplicity

2. Immutability:

Immutability means that once a data structure is created, it cannot be changed. This leads to safer code as it prevents accidental mutations that can cause bugs.

Example: Instead of modifying an array, you create a new one with the desired changes.

“Immutability is the idea that once you create a value, you can’t change it. It’s like writing in ink instead of pencil.” — Grokking Simplicity

const numbers = [1, 2, 3];
const newNumbers = [...numbers, 4]; // [1, 2, 3, 4]

3. First-Class Functions:

Functions in FP are first-class citizens, meaning they can be passed as arguments, returned from other functions, and assigned to variables.

“Treating functions as first-class means we can build abstractions, making our code more flexible and reusable.” — Grokking Simplicity

Example: Passing a function as an argument.

function greet(name) {
  return `Hello, ${name}!`;
}

function processGreeting(func, name) {
  return func(name);
}

console.log(processGreeting(greet, "Alice")); // Hello, Alice!

4. Higher-Order Functions:

A higher-order function is a function that takes one or more functions as arguments or returns a function as its result.

“Higher-order functions allow us to create powerful abstractions and compose complex behaviors from simpler ones.” — Grokking Simplicity

Example: A function that returns another function.

function multiplier(factor) {
  return function(x) {
    return x * factor;
  };
}

const double = multiplier(2);
console.log(double(5)); // 10

Further Reading

For those interested in diving deeper into functional programming and related concepts, here are some valuable resources: