Functional Programming is preferable to Object-Oriented Programming

  • Using component state yields code that is hard to reason about.
  • Moving from object-oriented programming (OOP) to functional programming (FP) will greatly improve the maintainability of our code base.

TLDR;

“Object State + Behavior” = 👍

Let’s talk about OOP

One of the key principals of OOP is that data and behavior are bound together. Part of the motivation is to model real-world data and relationships. Presumably, having code that mirrors the subjects of your application is a good thing; which it is, if you are building smoke detectors, computerized automotive parts or other realtime controls.

OOP is a good fit for many use-cases

Suppose we are building embedded software for an a/c unit. It would make sense to create classes for the Thermostat, Fan, and Coolant system. Your software would implement an object for each component in the system; each with its own state and connections (event handlers) to other components. The logic contained in the various event handlers would operate on the state (e.g. temperature) maintained for that system component. You can imagine how this could work well and be very easy to maintain — it makes sense that “business logic” is coupled with state — after all, the modeled components do things, and they do things based on what they “know.”

OOP can be an application killer

Consider the case of a business application where the subjects are records in a database. Records don’t “do things”. Before and/or after a CRUD operation is performed for a record, business rules may need to be applied and actions taken (e.g. emails sent) that are scoped to many other records and types of records. Also, there are going to be use-cases that require your application to aggregate data across complex data relationship graphs.

Use Functional Programming, it is safer

Rather, you should first acquire the data that is needed, and then pass that data as input to a function that will perform the required business rule on that data and return the results of that rule to the caller; which can then take whatever action fits the application requirements.

Example application which illustrates the difference between OOP and FP

A code snippet from this example angular project on stackblitz.com is included below:

import { Component } from '@angular/core';
import { DataService } from '../data.service';
@Component({
selector: 'oop',
template: `
<h1>{{ label }}</h1>
`,
styles: [
`
h1 {
font-family: Lato;
}
`,
],
})
export class OopComponent implements OnInit {
label: string;
firstName: string;
lastName: string;
constructor(private dataService: DataService) {} ngOnInit(): void {
this.dataService.getFirstName().subscribe((firstName) => {
this.firstName = firstName;
});
this.dataService.getLastName().subscribe((lastName) => {
this.lastName = lastName;
});
// using this approach is hard to reason about
this.formatFirstName();
this.formatLastName(); this.formatLabel();
}
formatFirstName() {
this.firstName = this.firstName.toLowerCase();
}
formatLastName() {
this.lastName = this.lastName.toUpperCase();
}
formatLabel() {
this.label = `Mr. ${this.firstName} ${this.lastName}`;
}
}
import { Component, Input, OnInit } from '@angular/core';
import { forkJoin } from 'rxjs';
import { DataService } from '../data.service';
@Component({
selector: 'fp',
template: `
<h1>{{ label }}</h1>
`,
styles: [
`
h1 {
font-family: Lato;
}
`,
],
})
export class FpComponent implements OnInit {
label: string;
constructor(private dataService: DataService) {} ngOnInit() {
forkJoin({
firstName: this.dataService.getFirstName(),
lastName: this.dataService.getLastName(),
}).subscribe(({ firstName, lastName }) => {
this.label = `Mr.
${(firstName as string).toLowerCase()}
${(lastName as string).toUpperCase()}`;
});
}
}

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store