# Object-oriented vs Functional programming

***

## Functional Programming: A Visual Guide

Functional programming is a programming paradigm that treats computation as the evaluation of mathematical functions. Let me break down its core concepts:

### Pure Functions

A pure function is like a reliable machine - same input always produces same output, with no side effects.

```
Pure Function Box
┌─────────────────┐
│   Input: 5      │
│      ↓          │
│   [double]      │
│      ↓          │
│  Output: 10     │
└─────────────────┘

Always: 5 → 10
        5 → 10
        5 → 10
```

**Characteristics:**

* **Deterministic**: Same input → Same output
* **No side effects**: Doesn't modify external state. It means intermediate results are **local** and don't affect anything outside the function.

**What "No External State Modification" Actually Means**

```
EXTERNAL STATE (what pure functions DON'T touch):
┌─────────────────────────────────┐
│  Global Variables               │
│  Database Records               │
│  File System                    │
│  Network State                  │
│  Object Properties (outside)    │
│  Console/Screen Output          │
└─────────────────────────────────┘

INTERNAL/LOCAL (what pure functions CAN use):
┌─────────────────────────────────┐
│  Local Variables                │
│  Parameters                     │
│  Intermediate Calculations      │
│  Temporary Data Structures      │
└─────────────────────────────────┘
```

* **No hidden dependencies**: Only uses its parameters

```
Impure vs Pure

IMPURE:                    PURE:
┌──────────────┐          ┌──────────────┐
│ counter = 0  │          │              │
│              │          │ add(a, b)    │
│ increment()  │          │   return     │
│   counter++  │          │   a + b      │
│   return     │          │              │
│   counter    │          └──────────────┘
└──────────────┘          
   ↓ (modifies           
   external state)
```

### Immutability

Data never changes - instead, you create new versions.

```
Mutable Approach:
list = [1, 2, 3]
list.append(4)      ← modifies original
list = [1, 2, 3, 4]

Immutable Approach:
list1 = [1, 2, 3]
list2 = concat(list1, [4])  ← creates new
list1 = [1, 2, 3]           ← unchanged
list2 = [1, 2, 3, 4]        ← new version
```

### First-Class Functions

Functions are treated as values - can be passed around like data.

```
┌─────────────────────────────┐
│  Functions as Values        │
├─────────────────────────────┤
│                             │
│  f = multiply(x, y)         │
│  g = add(x, y)              │
│                             │
│  operations = [f, g]        │
│                             │
│  apply(operation, 5, 3)     │
│         ↓                   │
│    operation(5, 3)          │
└─────────────────────────────┘
```

### Higher-Order Functions

Functions that take functions as parameters or return functions.

```
Map Example:
numbers = [1, 2, 3, 4]
           ↓
    map(double, numbers)
           ↓
    [double(1), double(2), double(3), double(4)]
           ↓
    [2, 4, 6, 8]

Filter Example:
numbers = [1, 2, 3, 4, 5, 6]
           ↓
    filter(isEven, numbers)
           ↓
    [2, 4, 6]

Reduce Example:
numbers = [1, 2, 3, 4]
           ↓
    reduce(add, 0, numbers)
           ↓
    0 + 1 = 1
    1 + 2 = 3
    3 + 3 = 6
    6 + 4 = 10
```

### Function Composition

Combining simple functions to build complex ones.

```
f(x) = x * 2
g(x) = x + 3

Composition: h(x) = g(f(x))

Input: 5
  ↓
  f: 5 * 2 = 10
  ↓
  g: 10 + 3 = 13
  ↓
Output: 13

Visualized as pipes:
5 → [double] → [add3] → 13
```

### Recursion

Functions calling themselves instead of loops.

```
Factorial (iterative mental model):
factorial(4)
  = 4 * factorial(3)
    = 3 * factorial(2)
      = 2 * factorial(1)
        = 1 * factorial(0)
          = 1
        ← 1
      ← 2
    ← 6
  ← 24
← 24

Tree structure:
        fact(4)
          ↓
      4 * fact(3)
            ↓
        3 * fact(2)
              ↓
          2 * fact(1)
                ↓
            1 * fact(0)
                  ↓
                  1
```

### Referential Transparency

An expression can be replaced with its value without changing program behavior.

```
expression = add(2, 3)

Since add is pure:
  result = add(2, 3) * 2
  
Can be replaced with:
  result = 5 * 2
  
Both produce the same result: 10
```

### Main Benefits

```
┌─────────────────────────────────────┐
│  FUNCTIONAL PROGRAMMING BENEFITS    │
├─────────────────────────────────────┤
│                                     │
│  Predictability                     │
│  └─→ Pure functions = no surprises │
│                                     │
│  Testability                        │
│  └─→ Easy to test isolated units   │
│                                     │
│  Concurrency                        │
│  └─→ No shared state = safe        │
│                                     │
│  Reasoning                          │
│  └─→ Easier to understand flow     │
└─────────────────────────────────────┘
```

The essence is: **treat programs as mathematical transformations** rather than sequences of state changes. This leads to more predictable, maintainable, and testable code.

***

## Object-Oriented Programming: In General and Compared to Functional Programming

### What is OOP?

Object-Oriented Programming organizes code around **objects** - bundles of data (state) and behavior (methods) that work together.

```
OOP CORE CONCEPT:

Object = Data + Behavior

┌─────────────────────────┐
│      BankAccount        │
├─────────────────────────┤
│ Data (State):           │
│  - balance: 1000        │
│  - owner: "Alice"       │
│  - accountNum: "123"    │
├─────────────────────────┤
│ Behavior (Methods):     │
│  - deposit(amount)      │
│  - withdraw(amount)     │
│  - getBalance()         │
└─────────────────────────┘
```

### The Four Pillars of OOP

#### 1. Encapsulation

Bundling data and methods together, hiding internal details.

```
┌──────────────────────────────────┐
│  Public Interface (visible)      │
│  ├─ deposit()                    │
│  ├─ withdraw()                   │
│  └─ getBalance()                 │
├──────────────────────────────────┤
│  Private Implementation (hidden) │
│  ├─ balance                      │
│  ├─ validateAmount()             │
│  └─ updateLedger()               │
└──────────────────────────────────┘

Outside world only sees public methods
Internal details are protected
```

#### 2. Inheritance

Objects can inherit properties and methods from parent objects.

```
        ┌──────────────┐
        │   Vehicle    │
        ├──────────────┤
        │ speed        │
        │ start()      │
        │ stop()       │
        └──────────────┘
              ↑
      ┌───────┴───────┐
      │               │
┌──────────┐    ┌──────────┐
│   Car    │    │   Boat   │
├──────────┤    ├──────────┤
│ doors    │    │ anchor   │
│ drive()  │    │ sail()   │
└──────────┘    └──────────┘

Car inherits: speed, start(), stop()
Car adds: doors, drive()
```

#### 3. Polymorphism

Different objects can respond to the same message in different ways.

```
Same message, different behaviors:

     makeSound()
          ↓
    ┌─────┴─────┬─────────┐
    ↓           ↓         ↓
┌────────┐  ┌────────┐  ┌────────┐
│  Dog   │  │  Cat   │  │  Bird  │
├────────┤  ├────────┤  ├────────┤
│ "Woof" │  │ "Meow" │  │ "Tweet"│
└────────┘  └────────┘  └────────┘

animals = [dog, cat, bird]
for each animal:
  animal.makeSound()
  
Output: "Woof", "Meow", "Tweet"
```

#### 4. Abstraction

Hiding complexity, showing only essential features.

```
User's View:
┌─────────────────┐
│  car.start()    │ ← Simple interface
└─────────────────┘

Hidden Complexity:
┌─────────────────────────────┐
│ - Check fuel level          │
│ - Initialize ignition       │
│ - Start fuel pump           │
│ - Engage starter motor      │
│ - Monitor engine sensors    │
│ - Adjust timing             │
└─────────────────────────────┘
```

### OOP vs Functional Programming

#### Fundamental Philosophy

```
OOP WORLDVIEW:
┌─────────────────────────────────────┐
│ Program = Objects sending messages  │
│                                     │
│  Object1 → message → Object2        │
│     ↓                   ↓           │
│  changes state      changes state   │
└─────────────────────────────────────┘

FUNCTIONAL WORLDVIEW:
┌─────────────────────────────────────┐
│ Program = Data transformations      │
│                                     │
│  data1 → function → data2           │
│           ↓                         │
│    (no state change, new data)      │
└─────────────────────────────────────┘
```

#### State Management

```
OOP APPROACH:
┌─────────────────────────────┐
│  account = new BankAccount  │
│  account.balance = 1000     │ ← State stored in object
│                             │
│  account.deposit(500)       │ ← Modifies internal state
│  account.balance = 1500     │
│                             │
│  account.withdraw(200)      │ ← Modifies internal state
│  account.balance = 1300     │
└─────────────────────────────┘

FUNCTIONAL APPROACH:
┌─────────────────────────────┐
│  account1 = {balance: 1000} │ ← Immutable data
│                             │
│  account2 = deposit(        │
│    account1, 500)           │ ← Returns new data
│  account2 = {balance: 1500} │
│  account1 = {balance: 1000} │ ← Original unchanged
│                             │
│  account3 = withdraw(       │
│    account2, 200)           │ ← Returns new data
│  account3 = {balance: 1300} │
└─────────────────────────────┘
```

#### Code Organization

```
OOP: Organize by ENTITIES
┌────────────────────────────┐
│  User                      │
│  ├─ data: name, email      │
│  ├─ register()             │
│  ├─ login()                │
│  └─ updateProfile()        │
└────────────────────────────┘
┌────────────────────────────┐
│  Order                     │
│  ├─ data: items, total     │
│  ├─ addItem()              │
│  ├─ calculateTotal()       │
│  └─ checkout()             │
└────────────────────────────┘

FUNCTIONAL: Organize by OPERATIONS
┌────────────────────────────┐
│  Data (separate):          │
│  user = {name, email}      │
│  order = {items, total}    │
└────────────────────────────┘
┌────────────────────────────┐
│  Functions (separate):     │
│  registerUser(userData)    │
│  loginUser(credentials)    │
│  updateProfile(user, data) │
│  addItemToOrder(order, it) │
│  calculateTotal(order)     │
└────────────────────────────┘
```

#### Side-by-Side Comparison

```
┌──────────────────┬─────────────────┬──────────────────┐
│   Aspect         │      OOP        │   Functional     │
├──────────────────┼─────────────────┼──────────────────┤
│ Building block   │ Objects         │ Functions        │
│ State           │ Mutable         │ Immutable        │
│ Data & behavior │ Together        │ Separated        │
│ Core mechanism  │ Method calls    │ Function calls   │
│ Flow control    │ Loops, methods  │ Recursion, HOFs  │
│ Changes         │ Modify in place │ Create new       │
└──────────────────┴─────────────────┴──────────────────┘
```

#### Example: Shopping Cart

```
OOP STYLE:

┌─────────────────────────────┐
│  ShoppingCart               │
├─────────────────────────────┤
│ State:                      │
│  items = []                 │
│  total = 0                  │
├─────────────────────────────┤
│ Methods:                    │
│  addItem(item)              │
│    items.append(item)       │ ← Mutates state
│    total += item.price      │ ← Mutates state
│                             │
│  removeItem(id)             │
│    items.remove(id)         │ ← Mutates state
│    total -= item.price      │ ← Mutates state
└─────────────────────────────┘

Usage:
  cart = new ShoppingCart()
  cart.addItem(book)      ← cart changes
  cart.addItem(pen)       ← cart changes
  cart.total              ← access state


FUNCTIONAL STYLE:

Data:
  cart = {items: [], total: 0}

Functions:
  addItem(cart, item)
    newItems = concat(cart.items, item)
    newTotal = cart.total + item.price
    return {items: newItems, total: newTotal}
  
  removeItem(cart, id)
    newItems = filter(cart.items, notId(id))
    removedItem = find(cart.items, id)
    newTotal = cart.total - removedItem.price
    return {items: newItems, total: newTotal}

Usage:
  cart1 = {items: [], total: 0}
  cart2 = addItem(cart1, book)  ← new cart
  cart3 = addItem(cart2, pen)   ← new cart
  cart3.total                    ← access data
  
  cart1 still exists unchanged!
```

#### When to Use Each

```
OOP EXCELS AT:
┌────────────────────────────────┐
│ • Modeling real-world entities │
│ • Complex stateful systems     │
│ • UI components                │
│ • Game objects                 │
│ • Domain modeling              │
│                                │
│ Example domains:               │
│ - Simulations                  │
│ - GUI applications             │
│ - Business domain models       │
└────────────────────────────────┘

FUNCTIONAL EXCELS AT:
┌────────────────────────────────┐
│ • Data transformations         │
│ • Concurrent/parallel code     │
│ • Mathematical computations    │
│ • Data pipelines               │
│ • Stateless services           │
│                                │
│ Example domains:               │
│ - Data processing              │
│ - APIs/microservices           │
│ - Analytics                    │
└────────────────────────────────┘
```

#### Hybrid Approach (Modern Reality)

Many modern languages and applications blend both:

```
┌─────────────────────────────────────┐
│  HYBRID APPROACH                    │
├─────────────────────────────────────┤
│                                     │
│  Objects for structure:             │
│  ┌──────────────────┐               │
│  │  User object     │               │
│  └──────────────────┘               │
│         ↓                           │
│  Functional methods inside:         │
│  ├─ map over data                   │
│  ├─ filter results                  │
│  └─ reduce collections              │
│                                     │
│  Immutable objects (hybrid):        │
│  - Object structure (OOP)           │
│  - Immutable data (FP)              │
│  - Methods return new objects       │
└─────────────────────────────────────┘
```

The key insight: **OOP organizes around "things" that have state and behavior**, while **FP organizes around transformations of immutable data**. Neither is universally better - they're different tools for different problems!
