cover-image

Programming Paradigms: Procedural vs. Object Oriented vs. Functional

#education
#javascript
#programming

Andrew Vo-Nguyen

September 1, 2021

4 min read

Programming paradigms refer to the style of programming you choose to implement in your codebase. The paradigms are a way to logically write and structure your code. It is not a strict set of rules set by your browser, IDE or compiler, however certain languages or frameworks may be opinionated about which paradigm is preferred. We will be exploring three paradigms with working examples and comparisons. Firstly, a general overview of each paradigm:

Procedural

Procedural programming involves running a set of instructions in sequential order. This type of programming is the simplest form of programming and can be often referred to as scripting. When I first learnt JavaScript to manipulate the DOM, this was the quick and easy solution to make changes to an HTML page.

Object Oriented

Object Oriented Programming or OOP is the concept of reasoning your code with the real world. Entities are represented as objects that have properties (it's attributes) and methods (it's actions). This is the first paradigm I learnt going to university and it is usually the first concept that you need to wrap your head around when starting with programming. This style of programming is prominent in Java and C#.

Functional

Functional programming is kind of the new kid on the block. It is the idea of organising your code into pure functions that take input parameters and return a result. The idea of this approach is to keep your code as predictable as possible by not omitting side effects in your functions. This style or programming I picked up mostly while learning the React framework. It is the most prominent with React and the idea of re-usable functional components. Javascript's array methods such as .map(), .reduce(), .filter() are prime examples of taking in an argument and producing an output.

To quickly demonstrate how all three paradigms are used, I will be show a very basic use case for creating a new user in JavaScript.

Procedural Paradigm

1const users = [];
2
3function procedural() {
4  const username = document.getElementById("username").value;
5  const password = document.getElementById("password").value;
6
7  // Validations
8  const userExists = users.find((user) => user.username === username.trim());
9  if (userExists) {
10    throw new Error("User already exists");
11  }
12  const passwordValid = password.length < 6;
13  if (!passwordValid) {
14    throw new Error("Password must be at least 6 characters long");
15  }
16
17  // Add user
18  users.push({ username, password });
19}

Object Oriented Paradigm

1const users = [];
2
3class User {
4  username;
5  password;
6  constructor(username, password) {
7    this.username = username;
8    this.password = password;
9  }
10
11  static extractFromDOM() {
12    const username = document.getElementById("username").value;
13    const password = document.getElementById("password").value;
14    return { username, password };
15  }
16
17  validate() {
18    const userExists = users.find((user) => user.username === username.trim());
19    if (userExists) {
20      throw new Error("User already exists");
21    }
22    const passwordValid = password.length < 6;
23    if (!passwordValid) {
24      throw new Error("Password must be at least 6 characters long");
25    }
26  }
27
28  save() {
29    users.push({ username, password });
30  }
31}
32
33function oop() {
34  const { username, password } = User.extractFromDOM();
35  const user = new User(username, password);  
36
37  // Validations
38  user.validate()
39
40  // Add user
41  user.save()
42}

Functional Paradigm

1const users = [];
2
3function extractFromDOM(id) {
4  return document.getElementById(id).value;
5}
6
7function validateUsername(users, username) {
8  return users.find((user) => user.username === username.trim());
9}
10
11function validatePassword(password) {
12  password.length < 6
13}
14
15function saveUser(username, password) {
16  users.push({ username, password });
17}
18
19function functional() {
20	const username = extractFromDOM("username");
21	const password = extractFromDOM("password");
22
23  // Validations
24  const isUsernameValid = validateUsername(users, username);
25  if (!isUsernameValid) {
26    throw new Error("User already exists");
27  }
28
29  const isPasswordValid = validatePassword(password);
30  if (!isPasswordValid) {
31    throw new Error("Password must be at least 6 characters long");
32  }
33
34  // Add user
35  saveUser(username, password);
36}

As you can see, all three paradigms offer a vastly different way of structuring your code. In the end, they all yield the same result. There is no hard and fast rule about which style to use and the usage is very much circumstantial. In many cases a codebase can have a mix of these paradigms, however the only hard and fast rule is to keep the codebase consistent.

Some things to consider when choosing a paradigm:

  • How readable is your code?
  • How easy is it for someone else to work on your codebase?
  • Is there repeated code that can be consolidated in to a re-usable function or method?
  • How does the paradigm affect your folder and file structure?
  • How much boilerplate code is required to operate the paradigm?
  • How much technical overhead does the paradigm introduce?
  • Does your code scale well?