OOP vs functional programming
Tags: javascript, oop, functional, tutorial
Published: 2020-08-28 06:59:27

## Introduction
Before we get started with coding I want to give you a quick introduction to object-oriented and functional programming.
Both are [programming paradigms](https://en.wikipedia.org/wiki/Programming_paradigm) differing in the techniques they allow and forbid.
There are programming languages that only support one paradigm e.g. [Haskell](https://www.haskell.org/) (purely functional).
Aswell as languages that support multiple paradigms such as [JavaScript](https://en.wikipedia.org/wiki/JavaScript), you can use JavaScript to write object-oriented or functional code or even a mixture of both.

## Setup
Before we can dive deep into the differences between these two paradigms we need to setup the project.
For that we first create all the files and folders we need like this:

```Shell
$ mkdir func-vs-oop
$ cd ./func-vs-oop
$ cat index.html
$ cat functional.js
$ cat oop.js 
```
I'm using the *cat* command because it works both on Linux-systems and Windows Powershell.

Next up we need to create a simple form for the factorial calculator inside the *index.html*.
```HTML
<!DOCTYPE html>
<html>
<head>
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
  <script src="functional.js" defer></script>
</head>
<body>
  <div class="container mt-5">
    <div class="container mt-3 mb-5 text-center">
      <h2>Functional vs OOP</h2>
    </div>
    <form id="factorial-form">
      <div class="form-group">
        <label for="factorial">Factorial</label>
        <input class="form-control" type="number" name="factorial" id="factorial" />
      </div>
      <button type="submit" class="btn btn-primary">Calculate</button>
    </form>
    <div class="container mt-3">
      <div class="row mt-4 text-center">
        <h3>Result:</h3>
        <h3 class="ml-5" id="factorial-result"></h3>
      </div>
    </div>
  </div>
</body>
</html>
```
To give this form a better look and feel we use [bootstrap](https://getbootstrap.com/) as a *CSS-Framework*.
If you display this HTML in the browser it should look like this:
![factorial-calc](https://dev-to-uploads.s3.amazonaws.com/i/zvor4q02e8ldy5o3ojpd.PNG)

Currently this form won't do anything.
Our goal is to implement a logic where you can enter a number up to 100. After clicking the "Calculate"-button it should show the result in the *result-div*.
We will implement this both in the object-oriented way and the functional way.

## Functional implementation
First off we will create a file for the functional programming approach.
```Shell
$ cat functional.js
```
To get started we need a function that get's called when loading this file into the browser.
This function should get the form and then add the functionality we need to the submit-event of the form.
```JavaScript
function addSubmitHandler(tag, handler) {
  const form = getElement(tag);
  form.addEventListener('submit', handler);
}

addSubmitHandler("#factorial-form", factorialHandler);
```
First we declare the function called *addSubmitHandler*.
This function takes in two parameters, the first one being the tag we want to look for in our HTML, the second one being the function we want to bind to the submit-event of our Element.

Next we call this function by passing in *#factorial-form* and the function name *factorialHandler*.
The hashtag in front of the tag indicates that we are looking for the id-attribute in the HTML.

This code will throw an error if you try to run it now, because neither the function *getElement* nor *factorialHandler* are defined anywhere.
So let's first define *getElement* above our *addSubmitHandler* function like this:
```JavaScript
function getElement(tag) {
  return document.querySelector(tag);
}
```
This function is really simple and only returns the HTML-Element we found by the tag we passed in.
But we will reuse this function later on.

Now let's start creating the core logic by adding the *factorialHandler* function above the *addSubmitHandler*.
```JavaScript
function factorialHandler(event) {
  event.preventDefault();

  const inputNumber = getValueFromElement('#factorial');
  
  try {
    const result = calculateFactorial(inputNumber);
    displayResult(result);
  } catch (error) {
    alert(error.message);
  } 
}
```
We pass in the event and instantly call *[preventDefault](https://developer.mozilla.org/en-US/docs/Web/API/Event/preventDefault)*.
This will prevent the default behavior of the submit event, you can try out what happens on the button click without calling *preventDefault*.

After that we get the value entered by the user from the input-field by calling the *getValueFromElement* function.
Upon getting the number we try to calculate the factorial by using the function *calculateFactorial* and then render the result to the page by passing the result to the function *displayResult*.

If the value is not in the correct format or the number is higher than 100, we will throw an error and display that as and alert.
This is the reason for using a try-catch-block in this particular case.

In the next step we create two more helper functions, *getValueFromElement* and *displayResult*.
Let's add them below the *getElement* function.
```JavaScript
function getValueFromElement(tag) {
  return getElement(tag).value;
}

function displayResult(result) {
  getElement('#factorial-result').innerHTML = result
}
```
Both of these functions use our *getElement* function. This reusablility is one part why functional programming is so effective.
To make this even more reusable we could potentially add a second argument to *displayResult*, called tag.
So that we can dynamically set the element that should display the result.
But in this example I went with the hard-coded way.

Next up we create our *calculateFactorial* function right above *factorialHandler*.
```JavaScript
function calculateFactorial(number) {
  if (validate(number, REQUIRED) && validate(number, MAX_LENGTH, 100) && validate(number, IS_TYPE, 'number')) {
    return factorial(number);
  } else {
    throw new Error(
      'Invalid input - either the number is to big or it is not a number'
    );
  }
}
```
We validate if the argument 'number' is not empty, not above 100 and of type number.
For that we use a function called *validate* that we will need to create next.
If the checks pass we call the function *factorial* and return it's result.
If these checks don't pass we throw the error we catched in the *factorialHandler* function.

First let's create the *validate* function right below *displayResult* and the three constants MAX_LENGTH, IS_TYPE and REQUIRED.
```JavaScript
const MAX_LENGTH = 'MAX_LENGTH';
const IS_TYPE = 'IS_TYPE';
const REQUIRED = 'REQUIRED';

function validate(value, flag, compareValue) {
  switch (flag) {
    case REQUIRED:
      return value.trim().length > 0;
    case MAX_LENGTH:
      return value <= compareValue;
    case IS_TYPE:
      if (compareValue === 'number') {
        return !isNaN(value);
      } else if (compareValue === 'string') {
        return isNaN(value);
      }
    default:
      break;
  }
}
```
In this function we use a switch to determine which kind of validation we are going to perform.
After determining that, it is just a simple value validation.

Now we are going to add the actual *factorial* function right above the *calculateFactorial* declaration.
This will be our last function for this approach.
```JavaScript
function factorial(number) {
  let returnValue = 1;
  for (let i = 2; i <= number; i++) {
    returnValue = returnValue * i;
  }
  return returnValue;
}
```
There are many different ways to perform a factorial calculation, I went with the iterative approach.
If you want to learn more about the different approaches I recommend you check out this article on geeksforgeeks:
- [https://www.geeksforgeeks.org/program-for-factorial-of-a-number/](https://www.geeksforgeeks.org/program-for-factorial-of-a-number/)

The final **functional.js** file should look like this:
```JavaScript
const MAX_LENGTH = 'MAX_LENGTH';
const IS_TYPE = 'IS_TYPE';
const REQUIRED = 'REQUIRED';

function getElement(tag) {
  return document.querySelector(tag);
}

function getValueFromElement(tag) {
  return getElement(tag).value;
}

function displayResult(result) {
  getElement('#factorial-result').innerHTML = result
}

function validate(value, flag, compareValue) {
  switch (flag) {
    case REQUIRED:
      return value.trim().length > 0;
    case MAX_LENGTH:
      return value <= compareValue;
    case IS_TYPE:
      if (compareValue === 'number') {
        return !isNaN(value);
      } else if (compareValue === 'string') {
        return isNaN(value);
      }
    default:
      break;
  }
}

function factorial(number) {
  let returnValue = 1;
  for (let i = 2; i <= number; i++) {
    returnValue = returnValue * i;
  }
  return returnValue;
}

function calculateFactorial(number) {
  if (validate(number, REQUIRED) && validate(number, MAX_LENGTH, 100) && validate(number, IS_TYPE, 'number')) {
    return factorial(number);
  } else {
    throw new Error(
      'Invalid input - either the number is to big or it is not a number'
    );
  }
}

function factorialHandler(event) {
  event.preventDefault();

  const inputNumber = getValueFromElement('#factorial');
  
  try {
    const result = calculateFactorial(inputNumber);
    displayResult(result);
  } catch (error) {
    alert(error.message);
  } 
}

function addSubmitHandler(tag, handler) {
  const form = getElement(tag);
  form.addEventListener('submit', handler);
}

addSubmitHandler("#factorial-form", factorialHandler);
```
In this approach we worked exclusively with functions. Every function got a single purpose and most of them are reusable in other parts of the application.
For this simple web application the functional approach is a bit of an overkill. Next we will code the same functionality but this time object-oriented.

## Object-oriented implementation
First of all we need to change the src in the script-tag of our *index.html* file to the following.
```HTML
<script src="oop.js" defer></script>
```
Now we create the *oop.js* file.
```Shell
$ cat oop.js
```
For the OOP approach we want to create three different classes, one for validation, one for the factorial calculation and one for handling the form.
We get started with creating the class that handles the form.
```JavaScript
class InputForm {
  constructor() {
    this.form = document.getElementById('factorial-form');
    this.numberInput = document.getElementById('factorial');

    this.form.addEventListener('submit', this.factorialHandler.bind(this));
  }

  factorialHandler(event) {
    event.preventDefault();

    const number = this.numberInput.value;

    if (!Validator.validate(number, Validator.REQUIRED) 
      || !Validator.validate(number, Validator.MAX_LENGTH, 100)
      || !Validator.validate(number, Validator.IS_TYPE, 'number'))
      {
        alert('Invalid input - either the number is to big or it is not a number');
        return;
      }

      const factorial = new Factorial(number);
      factorial.display();
  }
}

new InputForm();
```
In the constructor we get the form-element and the input-element and store it in class variables, also called properties.
After that we add the method *factorialHandler* to the submit-event.
In this case we need to [bind](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind) 'this' of the class to the method.
If we don't do that we will get reference errors, e.g. calling *this.numberInput.value* will be undefined.
After that we create the class method *factorialHandler* with the event as an argument.

The code of this method should look somewhat familiar, for example the if-statement checks if the inputvalue is valid or not, like we did in the *calculateFactorial* function.
*Validator.validate* is a call to a static method inside the class *Validator* that we still need to create.
We don't need to initialize a new instance of an object if we work with static methods.
After the validations pass we create a new instance of the *Factorial class*, pass in the inputvalue and then display the calculated result to the user.

Next up we are going to create the *Validator class* right above the *InputForm class*.
```JavaScript
class Validator {
  static MAX_LENGTH = 'MAX_LENGTH';
  static IS_TYPE = 'IS_TYPE';
  static REQUIRED = 'REQUIRED';

  static validate(value, flag, compareValue) {
    switch (flag) {
      case this.REQUIRED:
        return value.trim().length > 0;
      case this.MAX_LENGTH:
        return value <= compareValue;
      case this.IS_TYPE:
        if (compareValue === 'number') {
          return !isNaN(value);
        } else if (compareValue === 'string') {
          return isNaN(value);
        }
      default:
        break;
    }
  }
}
```
As you can see everything inside of this class is static, the method *validate* aswell as the three properties.
Therefor we do not need any constructor.
The advantage of this is that we do not need to initialize this class everytime we want to use it.
*validate* is mostly the same as the *validate* function is our *functional.js* except that we do *this.REQUIRED*, *this.MAX_LENGTH* and *this.IS_TYPE* instead of just the variable name.

Next up we create our *Factorial class* right below the *Validator class*.
```JavaScript
class Factorial {
  constructor(number) {
    this.resultElement = document.getElementById('factorial-result');
    this.number = number;
    this.factorial = this.calculate();
  }

  calculate() {
    let returnValue = 1;
    for (let i = 2; i <= this.number; i++) {
      returnValue = returnValue * i;
    }
    return returnValue;
  }

  display() {
    this.resultElement.innerHTML = this.factorial;
  }
}
```
Upon initializing an instance of this class we get the resultelement and store it as a property aswell as the number we pass in.
After that we call the method *calculate* and store it's return value in a property.
The *calculate* method contains the same code as the *factorial* function in *functional.js*.
Last but not least we got the *display* method that sets the *innerHTML* of our resultelement to the calculated factorial number.

The complete *oop.js* file should look like this.
```JavaScript
class Validator {
  static MAX_LENGTH = 'MAX_LENGTH';
  static IS_TYPE = 'IS_TYPE';
  static REQUIRED = 'REQUIRED';

  static validate(value, flag, compareValue) {
    switch (flag) {
      case this.REQUIRED:
        return value.trim().length > 0;
      case this.MAX_LENGTH:
        return value <= compareValue;
      case this.IS_TYPE:
        if (compareValue === 'number') {
          return !isNaN(value);
        } else if (compareValue === 'string') {
          return isNaN(value);
        }
      default:
        break;
    }
  }
}

class Factorial {
  constructor(number) {
    this.resultElement = document.getElementById('factorial-result');
    this.number = number;
    this.factorial = this.calculate();
  }

  calculate() {
    let returnValue = 1;
    for (let i = 2; i <= this.number; i++) {
      returnValue = returnValue * i;
    }
    return returnValue;
  }

  display() {
    this.resultElement.innerHTML = this.factorial;
  }
}

class InputForm {
  constructor() {
    this.form = document.getElementById('factorial-form');
    this.numberInput = document.getElementById('factorial');

    this.form.addEventListener('submit', this.factorialHandler.bind(this));
  }

  factorialHandler(event) {
    event.preventDefault();

    const number = this.numberInput.value;

    if (!Validator.validate(number, Validator.REQUIRED) 
      || !Validator.validate(number, Validator.MAX_LENGTH, 100)
      || !Validator.validate(number, Validator.IS_TYPE, 'number'))
      {
        alert('Invalid input - either the number is to big or it is not a number');
        return;
      }

      const factorial = new Factorial(number);
      factorial.display();
  }
}

new InputForm();
```
We created three different classes handling three different aspects of our application:
- Validation: **Validation class**
- Factorial Handling: **Factorial class**
- Form Handling: **InputForm class**

## Conclusion
Both approaches are valid ways of structuring your code.
Personally I like to try out what works best in the different projects I work on.
Most of the time it is not even possible to seperate both paradigms so clearly.
I hope this little comparison gave you a fundamental understanding of what the different approaches look like.

As always you can find the code for this project on my [github](https://github.com/JakobKIT/func-vs-oop).