protips

Logo

This site lists the protips that we shared with students during our courses

View the Project on GitHub appliedtechnology/protips

Object oriented vs functional oriented programming

Programming languages come in many different flavors, just as human languages. Each language gives you different opportunities and possibilities to express a solution to a problem. Again just as human languages - let’s examine that a bit deeper.

Example from human language

For example, consider Chinese - a language that is made up of signs. There’s a sign for house and another for wagon. If you want to express the concept of a mobile home - you will make a new sign that is the combination of house and wagon (I presume - I don’t know Chinese.)

In the language of heroes and Gods (Swedish) we instead use letters to build words. The word for “house” is h, u and s put next to each other, with spaces before and after - to make the word hus. Wagon is vagn. If you want to represent the concept of mobile home you would combine the letters into a new word husvagn.

The type of language decides how we describe things and how we think about things.

Programming languages

There are a few different types of programming languages that, in a similar fashion as human languages, affects how we think about the task at hand. This post will describe two of the two big types of programming languages, but there are many more types.

You can’t decisively say that one type of language is better than another language; they are all good in the things they are designed to do. You can solve just about any problem using any kind of language (at least the general purpose programming languages) but they all have their strengths and weaknesses.

Before we start; the topics that we describe here are both 10-week courses at university and then took me (Marcus) at least 2-3 years more to use to my advantage in real life. This will be a very shallow brush on the surface.

Object-oriented programming languages

Object oriented languages (OOP - object orient programming) is obviously based around the concept of objects. These objects contain data and operations to work on that data.

Famous OOP languages are C#, Java, and Smalltalk. OOP was made popular in the 80-is with the rise of the graphical user interface, that has a good fit for object orientation.

When writing OOP programs we represent our code as classes. Classes are templates for creating objects. Classes describe how the objects should be structured and behave. We describe the problem we are working with as structures of these classes. Classes can inherit functionality from other classes.

An example

An (overused) example hopefully clarifies what this means. Let’s say that we are building a register for animals:

class Animal {
  constructor(name) { this.name = name }
  getName() { return this.name.toUpperCase() }
}

class Dog extends Animal {
  constructor(name) { super(name) }
  makeYourSound() { return `${this.getName()} says WOOOF` }
  paws() { return 4 }
}

class Bird extends Animal {
  constructor(name) { super(name) }
  makeYourSound() { return `${this.getName()} says Tweet-tweet` }
  beekLength() { return 2.5 }
}

Let’s go through this example and see a lot of the OOP paradigms in action. These are the different way that we think about a problem and we will see constraints and opportunities.

Let’s use these classes and create a few concrete objects:

const d = new Dog('Fido')
console.log(d.makeYourSound()) // Logs: FIDO says WOOOF
console.log(d.paws()) // 4

const b = new Bird('Jacko')
console.log(b.makeYourSound()) // JACKO says Tweet-tweet
console.log(b.beekLength()) // 2.5

We create an instance of the Dog class by using the new keyword, that will call the constructor passing Fido as the name of the Dog. The instance is called an object and we store it in a variable called d. There’s only one and has the name Fido. We can see that by calling the makeYourSound()` method.

The same behavior can be witnessed as we create a Bird object const b = new Bird('Jacko'). The makeYourSound method now returns the sound of the bird.

Now, we know that everything inheriting from Anmial have a getName method so we can use that to our advantage. Let’s create an array of Animals:

const d = new Dog('Fido')
const b = new Bird('Jacko')
const animals = [d, b]
animals.forEach((a) => console.log(a.getName()))
// FIDO
// JACKO

Both d and b is Animals since they extends animals and we can safely use getName to logs their individual names.

But even cooler is that we can use the makeYourSound method on both of the animals. They both have them and we don’t need to care what kind (or type) of animal it is - as long as we know that it has a makeYourSound method.

animals.forEach((a) => console.log(a.makeYourSound()))
// FIDO says WOOOF
// JACKO says Tweet-tweet

Now it a behaves differently depending on what type it is, but our code doesn’t care. This is called Polymorphism.

(Notice that since JavaScript (that the code is written in) doesn’t have basic OOP features has overrides and interfaces the example is not complete, but showing a point.)

Functional programming languages

Functional programming (FP) is oriented around functions that you pass data too. We strive to write immutable (once defined, unchangeable) data and pure (stateless) functions. Program is made up by composing many small functions into a larger whole.

FP is much older than OOP and dates back to the childhood of computer science (1950-is). Commonly used functional programming languages are JavaScript, Haskell and Erlang (or Elixir).

In FP our function operates on data (objects) and we seldom describe the template (classes) for such data. Function themselves are first class citizens and very often is passed as parameters to other functions, building so-called high-order functions (functions that take functions as parameters).

An example

Again, an example might be useful:

const dogPrinter = d => `${d.name} has ${d.paws} paws and says WOOF`
const birdPrinter = b => `${b.name} says tweet-tweet with her ${b.beekLength} cm beek`
const animalPrinter = a => {
  switch (a.type) {
    case 'Dog':
      return dogPrinter(a)
    case 'Bird':
      return birdPrinter(a)
  }
}
const animalSorter = (a, b) =>
  a.name.toLowerCase() > b.name.toLowerCase() ? 1 : -1

(Yes, I’m using the arrow function syntax throughout my example - read up on it if it confuses you. Also, I’m not a fan of semi-colons where they are not needed. So I have not used them - sue me! :))

Let’s go through the code line by line

Let’s use the functions and put them together. First, we need some data to operate on:

const animalList = [
  { name: 'Jacko', type: 'Bird', beekLength: 2.5 },
  { name: 'Fido', type: 'Dog', paws: 4 }
]

animalList
  .sort((a, b) => animalSorter(a, b))
  .map(a => animalPrinter(a))
  .forEach(el => console.log(el))

There’s an even tighter way to call the functions above, that you might see. If all there parameters that a function takes are the same as the parameter of the calling function we can just write the name of the function.

So this part:

animalList
  .sort((a, b) => animalSorter(a, b))
  .map(a => animalPrinter(a))
  .forEach(el => console.log(el))

Could be written like this:

animalList
  .sort(animalSorter)
  .map(animalPrinter)
  .forEach(el => console.log(el))

Notice some of the functional paradigms in action here:

What type of language is JavaScript then?

From Wikipedia we can read:

JavaScript has curly-bracket syntax, dynamic typing, prototype-based object-orientation, and first-class functions.

and

As a multi-paradigm language, JavaScript supports event-driven, functional, and imperative (including object-oriented and prototype-based) programming styles.

This means …

JavaScript is not really OOP but rather more FP. Meaning you can do most of the things needed to call it an FP-language but not all of it (pattern matching is lacking for example).

You can do some of the OOP things too but it has an even poorer fit.

Thinking in FP paradigms and patterns is most useful when doing JavaScript development.

Summary

Object-oriented programming (OOP) is built around the object that encapsulates data and methods that operate and change that data. We represent the problem we are working with as classes (templates for objects) that inherit functionality from each other.

Functional programming (FP) is built around functions that operate on data. Functions are often passed as parameters to other functions (high-order functions) making up more advanced features from simpler. Functions should be stateless and operate on data passed to it (pure function). The functions should not modify the data passed to it but rather return new data (immutable).

I hope it’s a bit more clear what the difference between the two paradigms are. If not, here’s a lovely graphics that probably is a much better summary than I can do. It is from https://www.educba.com/functional-programming-vs-oop/ and is really good.

Functional Programming vs OOP