We're planting a tree for every job application! Click here to learn more

Functional Programming? Don’t Even Bother, It’s a Silly Toy

Ilya Suzdalnitski

14 Jun 2023

13 min read

Functional Programming? Don’t Even Bother, It’s a Silly Toy
  • Scala

It will make your productivity plummet

Perhaps you’ve heard of so-called “functional” programming. Maybe you’ve even been wondering whether you should try it next.

The short answer is hell no!

Functional programming is full of flaws, is not suitable for real-world projects, and will make your productivity plummet. Why? Keep reading to find out!

Sign up to FunctionalWorks to join our community of talented developers sharing insights and discovering jobs and opportunities

Functional Programming is Unable to Fulfill Complex Enterprise Requirements

Real-world enterprise software demands a complex set of rigorous and compulsory requirements pertaining to the expected amount of embedded abstractions within the software solution. In other words, object-oriented programming enables the programmer to utilize multiple mechanisms of abstraction that fully satisfy the complex requirements demanded by the enterprise.

That was a mouthful, but bear with me! Things will become crystal-clear in a moment.

So-called “functional” programming has no proper mechanism of abstraction since it is based on mathematics (which obviously is inferior and has no applications in the real world apart from academia). Unlike OOP, functional programming makes no attempt to fulfill the numerous rigorous and complex requirements demanded by the enterprise.

This code snippet to demonstrates the issues prevalent with functional programming:


const filterByType = type =>
  filter( x => x.type === type );

const fruits = [
  { type: 'apple', price: 1.99 },
  { type: 'orange', price: 2.99 },
  { type: 'grape', price: 44.95 }  
];

const getFruitPrice = type => fruits =>
  fruits
  |> filterByType(type)
  |> first
  |> get('price');

const getApplePrice = getFruitPrice('apple');

console.log('apple price', getApplePrice(fruits));

If this makes you angry, you’are not alone!

Functional programming makes no attempt to properly abstract and encapsulate the functionality, as typically is demanded by any serious enterprise.

No self-respecting software engineer would ever write anything like this! If they do, then immediately they should be fired by any seriously large enterprise to prevent further damage. In the next section, we’ll take a look at a properly abstracted OOP program.

Functional Software Solutions Aren’t Future-Proof

It’s no secret that the foremost duty of any professional and self-respecting software engineer is to write future-proof code that satisfies complex business requirements.

In contrast with the disastrous functional code snippet above, let’s take a quick look at a properly abstracted OOP program. It does the same thing, but in an abstract and a future-proof way:

  constructor(type, price) {
    this.type = type;
    this.price = price;
  }
}

class AbstractFruitFactory {
  make(type, price) {
    return new Fruit(type, price);
  }
}

class AppleFactory extends AbstractFruitFactory {
  make(price) {
    return super.make("apple", price);
  }
}

class OrangeFactory extends AbstractFruitFactory {
  make(price) {
    return super.make("orange", price);
  }
}

class GrapeFactory extends AbstractFruitFactory {
  make(price) {
    return super.make("grape", price);
  }
}

class FruitRepository {
  constructor() {
    this.fruitList = [];
  }

  locate(strategy) {
    return strategy.locate(this.fruitList);
  }

  put(fruit) {
    this.fruitList.push(fruit);
  }
}

class FruitLocationStrategy {
  constructor(fruitType) {
    this.fruitType = fruitType;
  }

  locate(list) {
    return list.find(x => x.type === this.fruitType);
  }
}

class FruitPriceLocator {
  constructor(fruitRepository, locationStrategy) {
    this.fruitRepository = fruitRepository;
    this.locationStrategy = locationStrategy;
  }

  locatePrice() {
    return this.fruitRepository.locate(this.locationStrategy).price;
  }
}

const appleFactory = new AppleFactory();
const orangeFactory = new OrangeFactory();
const grapeFactory = new GrapeFactory();

const fruitRepository = new FruitRepository();
fruitRepository.put(appleFactory.make(1.99));
fruitRepository.put(orangeFactory.make(2.99));
fruitRepository.put(grapeFactory.make(44.95));

const appleLocationStrategy = new FruitLocationStrategy("apple");

const applePriceLocator = new FruitPriceLocator(
  fruitRepository,
  appleLocationStrategy
);

const applePrice = applePriceLocator.locatePrice();

console.log("apple", applePrice);

As you can see, this has all of the core functionality properly abstracted. This code is solid.

Don’t let the simplicity fool you! It completely fulfills all of the complex business requirements that would typically be demanded by any seriously large enterprise.

This robust solution is completely future-proof, and properly makes use of enterprise-grade dependency injection.

Serious Management Needs Serious Features

Hopefully by now the development team has fulfilled the complex business requirements pertaining to code abstraction, as set forth by the enterprise. The developer resources should now shift focus towards implementing the features defined by the project managers.

As any real-world enterprise product manager knows, only new features delivered have real business value. They shouldn’t be allowed to waste their resources on time-wasters like unit-testing and refactoring.

It is obvious that so-called “functional” programming is flawed, it makes redundant things like refactoring and unit testing unnecessarily easy. This, in turn, will act as a distraction to the development team — they might accidentally waste time on those useless activities, instead of delivering new features.

This example clearly demonstrates the inferiority of functional programming — it makes refactoring too easy:


// calculator.js:
const isValidInput = text => true;

const btnAddClick = (aText, bText) => {
  if (!isValidInput(aText) || !isValidInput(bText)) {
    return;
  }
}


// after refactoring:

// inputValidator.js:
export const isValidInput = text => true;

// calculator.js:
import { isValidInput } from './inputValidator';

const btnAddClick = (aText, bText, _isValidInput = isValidInput) => {
  if (!_isValidInput(aText) || !_isValidInput(bText)) {
    return;
  }
}

If such refactoring makes you cringe from its simplicity, then you’re not alone! Six lines of code before the refactor, and only seven lines of code after? You must be kidding me!

Let’s contrast it with a proper refactor of object-oriented code:

// before refactoring:
public class CalculatorForm {
    private string aText, bText;
    
    private bool IsValidInput(string text) => true;
    
    private void btnAddClick(object sender, EventArgs e) {
        if ( !IsValidInput(bText) || !IsValidInput(aText) ) {
            return;
        }
    }
}


// after refactoring:
public class CalculatorForm {
    private string aText, bText;
    
    private readonly IInputValidator _inputValidator;
    
    public CalculatorForm(IInputValidator inputValidator) {
        _inputValidator = inputValidator;
    }
    
    private void btnAddClick(object sender, EventArgs e) {
        if ( !_inputValidator.IsValidInput(bText)
            || !_inputValidator.IsValidInput(aText) ) {
            return;
        }
    }
}

public interface IInputValidator {
    bool IsValidInput(string text);
}

public class InputValidator : IInputValidator {
    public bool IsValidInput(string text) => true;
}

public class InputValidatorFactory {
    public IInputValidator CreateInputValidator() => new InputValidator();
}

That’s what proper programming looks like! Nine lines of code before, and 22 after. There’s more effort required to refactor, which will make the enterprise developer resources think twice before engaging in such wasteful activity as refactoring.

The Fallacy of Declarative Code

The so-called “functional” programmers erroneously pride themselves in writing declarative code. That’s nothing to be proud of — such code merely creates an illusion** **of productivity.

The core responsibility of any developer should consist of thinking about proper rigorous object-oriented abstractions (as also demanded by any seriously large enterprise).

Let’s take a look at properly abstracted OOP code:

class CountryUserSelectionStrategy {
  constructor(country) {
    this.country = country;
  }
  
  isMatch(user) {
    return user.country === this.country;
  }
}

class UserSelector {
  constructor(repository, userSelectionStrategy) {
    this.repository = repository;
    this.userSelectionStrategy = userSelectionStrategy;
  }
  
  selectUser() {    
    let user = null;

    for (const u in users) {
      if ( this.userSelectionStrategy.isMatch(u) ) {
        user = u;
        break;
      }
    }
    
    return user;
  }
}

const userRepository = new UserRepository();
const userInitializer = new UserInitializer();
userInitializer.initialize(userRepository);

const americanSelectionStrategy = new CountryUserSelectionStrategy('USA');
const americanUserSelector = new UserSelector(userRepository, americanSelectionStrategy);

const american = americanUserSelector.selectUser();

console.log('American', american);

Please focus on the imperative loop at line 20. Ignore the minor boilerplate OOP code, unrelated to the task at hand. It had to be included in order to make the code sample adhere to the rigorous abstraction requirements set forth by the serious enterprise.

Declarative code, on the other hand, is too concise, and erroneously makes the developers focus on the less important things, like business logic. Contrast the robust enterprise solution described above to a snippet of inferior “declarative” code:

SELECT * FROM Users WHERE Country=’USA’;

SQL makes me cringe every single time because of being declarative. Why SQL? Why can’t they have the developers make use of proper enterprise-grade abstractions and write normal object-oriented code? Especially when we already have those tools at our disposal. It’s mind-blowing.

Real World Modelling

Object-Oriented Programming is genius. Unlike “functional” programming, it perfectly models the real world with advanced techniques like inheritance, polymorphism, and encapsulation.

Any self-respecting software developer should be making use of inheritance on a daily basis to achieve code reusability. As I said earlier, inheritance perfectly models the real world. Cats, for example, always inherit their properties and behaviors from a single abstract real-world animal. Life originated in the ocean a few billion years ago. Therefore all mammals (including the cats) have inherited the properties of the primordial fish, like garfield.fishHead, and their methods like garfield.swim and garfield.layCaviar. No wonder cats enjoy bathing and swimming so much! Humans are actually the same, we can easily start laying caviar if we want to!

Our programs should always follow similar hierarchical approaches to code organization. Functional programming erroneously rids the developers of such amazing code sharing constructs inspired by the real world. This has far-reaching consequences, especially in seriously complex enterprise software.

Functions Should Always be Bound to Objects

This is just common sense and also perfectly models the real world. The notebook you buy at Chapters comes with a built-in “write method”. This method is to be called whenever you’re planning to write things down. You may not realize this, but you also have methods like .eat(veggies), doHomeWork . This is just common sense, how else would your mom be able to make you eat your veggies and have you complete your homework? Of course, she used to call those methods directly!

No job in the real world can be done without hiring a dedicatedManager that coordinates tasks. Young people probably need a manager to satisfy their basic human needs, you know, things like “netflix-n-chill”. Who is going to coordinate the entire process, after all? If they’re smart, then they’d hire multiple managers, just like OOP recommends.

In the real world, creating anything new and cool also requires having a dedicated Factory. Leonardo owned a MonaLisaFactory , Trump builds a secretWallFactory. Russia used to have a CommunismFactory , and nowadays mainly maintains itsCorruptionFactory, hidden somewhere deep within the dungeons of Kremlin.

One can clearly see that this is just another nail in the “functional” coffin since it makes no attempt to model the real world. The functions are allowed to exist separately from objects, which is plain wrong. Functional programming, obviously, is unsuitable for any serious real-world coding.

Functional Programming Provides no Opportunity for Growth

First and foremost, software engineers should focus on constant improvement and growth. A vast amount of knowledge has to be acquired by a software engineer in order to truly master Object-Oriented Programming.

First, they’d have to learn advanced OOP techniques like inheritance, abstraction, encapsulation, and polymorphism. Then they should familiarize themselves with a multitude of design patterns (like the Singleton), and start making use of them in their code. There about 30 basic design patterns that have to be learned. Ideally, somewhere around this point, the developer should start making use of various enterprise-grade abstraction techniques in their code.

The next step is to get familiar with techniques like Domain-Driven Design and to learn to break down the monolith. It is also recommended to learn proper refactoring tools, like Resharper, since OOP code is not trivial to refactor.

It takes at least 20–30 years to get good with OOP. Even then most people with 30 years of OOP experience haven’t truly mastered it. The learning path is rough, filled with uncertainty. A lifetime of learning awaits the OOP developer, how exciting is that?

What about the poor functional programmers? Unfortunately, there’s not much to learn. I have personally taught a few junior developers functional programming in JavaScript, and they became really good at it in about half a year. They simply had to understand a few basic concepts and then learned to apply them pretty quickly. Where’s the thrill of lifetime learning? I wouldn’t envy them.

Success is a Journey, Not a Destination

Let’s admit it, we programmers are being paid for our time. Just as the construction workers who’ve been digging holes not far from my house for the past two years (btw they’re building a ̶w̶a̶l̶l road).

Let’s define programmer productivity. Everyone who has worked in any seriously large enterprise knows the simple formula for success:

`productivity = lines_of_code x bugs_fixed`

Bugs Fixed

Human brains are really bad at working with state, we can only hold about five items in our working memory at a given time. State in programming usually refers any data in memory — e.g. fields/variables in OOP. Working with mutable state is very similar to juggling. I don’t know too many people who can juggle three balls, let alone five.

OOP makes good use of this weakness. Almost everything is mutable in OOP. Thank god that OOP takes the matter of developer productivity seriously! In OOP all of the mutable state is also shared by reference! This means that you not only have to think about the mutable state of the object that you currently are working with, you also have to think about the mutable state of 10–50 of other objects that it interacts with! This is akin to trying to juggle 50 balls at the same time, and also has the added benefit of acting as a really good exercise for our brain-muscle.

Bugs? Yes, eventually we will drop some of the balls that we’ve been juggling. We will maybe miss some smallish details from the interaction of those 50 objects. But who cares, really? Bugs should be reported by customers in production, that’s how any seriously large enterprise works. Then the bugs go into the JIRA backlog (serious enterprise-grade software as well). A few years from now the bugs will be fixed. Problem solved!

God, I love using my mobile banking app. It is very advanced, the bank values my business and they take my privacy seriously. The bugs are just features (I was told)!

So-called “functional” programming erroneously isolates state and makes the state immutable. This has an unfortunate consequence of reducing complexity, and thus reducing the number of bugs. Having fewer bugs in the codebase means that we will have fewer bugs to fix. Contractors won’t be able to keep charging their clients for those bug fixes. Developers working in any seriously large enterprise will start looking bad in the eyes of their managers, while seriously jeopardizing their chances of success within the organization.

Lines of Code

We should also be able to show continuous progress to our management. And what is the most effective way to show progress? Lines of code, of course! Had we all switched to functional programming, we’d make the management very upset and suspicious. The “declarative” code would have made our code more concise, and the lines of code would decrease drastically. Up to 3–5 times less code to achieve the exact same goal, this is unacceptable!

In other words, our productivity would plummet in the face of serious enterprise management, and our jobs once again would be put in jeopardy. It is in our best interests to stay away from the “functional” programming.

The same advice applies to the contractors who charge their clients for hours worked. Here’s a simple formula for success:

`lines_of_code = time_to_write = $$$pure_profit$$$`

This formula for success, of course, also directly applies to the serious software contractors who get paid for the lines of code:

   if (1 == '1') {
     doStuff();
   } else {
     // pure profit
   }

Spaghetti is Our Bread and Butter

Unlike Functional Programming, OOP offers us a consistent way to write spaghetti code — a real boon to developer productivity. Spaghetti code equates to more billable hours, which translates to pure profit for the serious OOP engineers. Spaghetti doesn’t only taste delicious, it is the bread and butter of OOP programmers!

Object-orientation is a true boon for contractors and employees of serious enterprise alike.

Bug Prevention Department

You should not fear using OOP. Once again, those pesky bugs are nothing to worry about! Any serious enterprise has an entire bug prevention department (aka customer support), whose main job is to protect their developer resources from angry customers. It’s the customer’s fault that they can’t use the app properly, after all.

The developers should not be bothered with such irrelevant things as bug reports. This ensures that none of the enterprise resources are wasted, and allows the developers to focus on implementing new features while making use of proper enterprise-grade object-oriented abstractions and complex design patterns.

Bug Report Process

An elaborate and rigorous process is typically put in place to protect enterprise resources. Once a customer has encountered a bug, they typically have to look for the customer support phone number online. Then the customer is presented with an advanced and interactive phone menu consisting of various options. It usually takes two to five minutes to listen to the menu and select the correct option. The least persistent customers usually fall off at this step.

Then the customer is usually told that the company is experiencing an “unexpectedly large volume of calls”, and that “the average wait time is 56 minutes”. They usually apologize for the inconvenience and mention how much they value the business of the customer. Most of the customers will usually decide not to report the bug at this step. To keep the customer entertained, inspirational music typically is being played. They’re also told to check out the awesome new app. The app that the customer was having trouble with in the first place.

After the 56-minute wait is over, the call gets routed to a call centre located somewhere in The Northern Americas. The local American employees typically go through rigorous training that enables them to speak with a thick Indian or Bulgarian accent. The agent mentions that the app in question is not his responsibility but happily will transfer the client to another department.

After another 42 minute wait, an agent happily tells the customer that this bug actually is a feature, and recommends the user to go through the help section of the app. If the customer is still being persistent, the agent might create a support ticket and the customer might even hear back! The bug can’t be reproduced.

I hope by now you are convinced, that worrying about bugs is not the job of a developer. Serious measures are typically put in place by the enterprise to protect their developer resources.

Avoid Rookie Job Interview Mistakes

If you are actively looking for a job, then put some effort into removing all of the “functional” nonsense from your resume or nobody will take you seriously. Nobody in the real enterprise world is trained in childish things like “function composition”, “purity”, “monads” or “immutability”. You don’t want to look like an outsider. Speaking about such things will make your interviewer appear dumb, and will completely annihilate your chances of success.

The enterprise technical recruiters also go through mandatory rigorous training, which enables them to properly differentiate between serious technologies like Java and JavaScript.

Be sure to sprinkle words throughout your resume that demonstrate your extensive knowledge of the various rigorous enterprise-grade abstraction techniques like classes, inheritance, design patterns, dependency injection, SOLID, abstract factory, and singleton.

When asked to implement the classical FizzBuzz job interview problem on the whiteboard, make sure that you come well-prepared. This is your opportunity to shine and demonstrate your rigorous enterprise-grade system design abilities. Your first step is to adequately design the solution while making use of proper OOP design patterns and rigorous enterprise-grade abstraction techniques. FizzBuzzEnterpriseEdition is a good starting point. Many make the rookie mistake of relying on inferior design techniques like functions. No wonder they never hear back from the potential employer.

Functional Programming Can’t Possibly be Used to Build Serious Software Solutions

Having considered all of the serious and rigorous arguments above, one can now clearly see that nothing good ever came out of this so-called “functional” programming. It’s clear it should be avoided at all costs.

The so-called “functional” programming was a fad of the last couple of years. It’s good that it is already going away! The big fish like Facebook and Microsoft have long ago realized the limitations of functional programming and the clear superiority of object-oriented approaches to code organization. They’re shifting their resources towards a new generation of object-oriented languages, namely ReasonOL and BosqueOOP. Such languages bring state mutability to a whole new level and fortunately have no support for useless functional things like immutable data structures.

The Boon of Gods

So you might ask what are the alternatives to the so-called “functional” programming? Object-Oriented Programming, silly! It was bestowed upon us by the one true god of programming himself. OOP is a force to be reckoned with. It is the ultimate tool for developer productivity and will always keep you and your teammates busy (and employed).

May the (object-oriented) force be with you. And your codes. I’m one with the force. Peace.

For a more in-depth explanation, check out my other article **Object-Oriented Programming, the Boon of Gods.**

PS> As most of you have guessed, the post is a satire. To all of the new developers out there — don’t take this seriously, FP is great! Invest some time into learning functional programming, and you will be ahead of most of your peers.

I hope you’ve enjoyed reading this post as much as I’ve enjoyed writing it!

Sign up to FunctionalWorks to join our community of talented developers sharing insights and discovering jobs and opportunities

Did you like this article?

Ilya Suzdalnitski

See other articles by Ilya

Related jobs

See all

Title

The company

  • Remote

Title

The company

  • Remote

Title

The company

  • Remote

Title

The company

  • Remote

Related articles

JavaScript Functional Style Made Simple

JavaScript Functional Style Made Simple

Daniel Boros

12 Sep 2021

JavaScript Functional Style Made Simple

JavaScript Functional Style Made Simple

Daniel Boros

12 Sep 2021

WorksHub

CareersCompaniesSitemapFunctional WorksBlockchain WorksJavaScript WorksAI WorksGolang WorksJava WorksPython WorksRemote Works
hello@works-hub.com

Ground Floor, Verse Building, 18 Brunswick Place, London, N1 6DZ

108 E 16th Street, New York, NY 10003

Subscribe to our newsletter

Join over 111,000 others and get access to exclusive content, job opportunities and more!

© 2024 WorksHub

Privacy PolicyDeveloped by WorksHub