Functional Programming after many years of OOP

A couple of months ago, I started using Clojure as the main programming language in the new team at the BBC. It was supposed to be a temporary switch for a couple of weeks, but things have changed and here I am today doing Clojure.

How was the switch?

It took me a while to understand the syntax and to be able to write code without too much help from the team.

That was really an unusual change. I mean for the first time I got rid of the weight of designing my code in classes, thinking about public and private methods or OOP design patterns in the favour of just functions.

Before diving more, let’s see what is OOP and what is Functional Programming.

Both of them are part of programming paradigms. A programming paradigm is a way of classifying the programming languages based on their features.

Object-Oriented Programming – OOP

OOP is a technique that is based on the creation of objects. An object is an instance of a class, which can have properties, public and private methods.

Imagine that whole world could be an object:

class World {
    public static void main(String[] args) {
        Universe universe = new Universe();
        Galaxy milkyWay = new Galaxy();

        universe.addGalaxy(milkyWay);

        TerrestrialPlanet earth = new TerrestrialPlanet();
        earth.setName("Earth");
        earth.setColor("blue");
        earth.setLiveable(true);

        GiantPlanet jupiter = new GiantPlanet();
        jupiter.setName("Jupiter");
        jupiter.setColor("red");
        jupiter.setLiveable(false);

        milkyWay.addPlanet(earth);
        milkyWay.addPlanet(jupiter);

        milkyWay.getPlanets().forEach(planet -> planet.description());
    }
}

Which the whole world would be an instance of a universe, with many galaxies, each galaxy would have many planets and, there can be two types of planets that can have different properties.

interface IPlanet {
    public void setName(String name);
    public void setLiveable (Boolean liveable);
    public void description ();
}

interface IUniverse {
    public List<IGalaxy> getGalaxies ();
    public void addGalaxy (Galaxy galaxy);
}

interface IGalaxy {
    public List<IPlanet> getPlanets ();
    public void addPlanet (IPlanet planet);
}

class Universe implements  IUniverse {
    private List<IGalaxy> galaxies = new ArrayList<>();

    public List<IGalaxy> getGalaxies () {
        return galaxies;
    }

    public void addGalaxy (Galaxy galaxy) {
        galaxies.add(galaxy);
    }
}

class Galaxy implements IGalaxy{
    private List<IPlanet> planets = new ArrayList<>();

    public List<IPlanet> getPlanets () {
        return planets;
    }

    public void addPlanet (IPlanet planet) {
        planets.add(planet);
    }
}

class TerrestrialPlanet implements IPlanet {
    public String name;
    public String color;
    public Boolean liveable;

    public void setName (String name) {
        this.name = name;
    }

    public void setLiveable (Boolean liveable) {
        this.liveable = liveable;
    }

    public void setColor (String color) {
        this.color = color;
    }

    public void description () {
        System.out.println("Planet: " + name);
        System.out.println("Color: " + color );
        System.out.println("Liveable: " + (liveable ? "Yes" : "No"));
    }
}

class GiantPlanet extends TerrestrialPlanet implements IPlanet {
    private int rings;

    public void setRings (int rings) {
        this.rings = rings;
    }

    @Override
    public void description() {
        super.description();
        System.out.println("Rings: " + rings);
    }
}

And this is an example of how can Object Oriented Programming can be used. If you have enough lifetime you can build the world up to atoms.

Concepts … so, the main features of Object Oriented programming are:

  • Abstraction – provide to the user, just the relevant data, a simple interface and hide the complexity;
  • Inheritance – inheriting methods and properties from a super class by deriving from it;
  • Encapsulation – mechanism where you can derive a class from another class or many depending on the programming language you’re using, used for inheriting the properties and the methods;
  • Polymorphism – is the concept of using the same interface on different classes;

Can you find the concepts that I used in the World example?

Functional Programming

Now, let’s see the Functional Programming concepts:

  • First-class and higher-order functions – functions that takes functions as arguments or returns a function (e.g. map, reduce, etc.)
  • Pure functions – functions with no side-effects in the memory or input/output. Given the same list of arguments, it will always return the same output.
  • Recursion – recursive functions are functions that invoke themselves.
  • Strict versus non-strict evaluation – is a concept that refers to how are function parameters evaluated, strict (eager) or non-strict (lazy). If the evaluation strategy is strict, the function parameters are fully evaluated before invoking the function. On the other hand if the evaluation strategy is non-strict, the function parameters are not evaluated unless their values are required to evaluate the function call itself.
  • Type systems – it refers to a set of rules that can be applied as types for variables, functions, expressions or modules.
  • Referential transparency – having assignment statements (e.g. x = x + 5) will cause side effects to your program. In functional programming there are no assignment statements and an equivalent function like (defn plusFive [x] (+ x 5)) is transparent, it doesn’t change the value of x so, there are no side effects.

pure functions + immutable data = referential transparency

  • Functional programming in non-functional languages – using functional style programming in non-functional programming languages (Python, PHP, etc.).
  • Data structures
What was new for me after switching to Functional Programming?

There are some concepts that I’ve used before, like recursion, typed languages but what I found interesting in the functional programming concepts, are the pure functions which used with immutability makes your functional program referential transparent. The opposite of this concept is referential opaque and this concept causes side effects to your program.

What does side effect actually mean? And how can you structure your project/component accordingly?

And I start hearing about side effect functions a lot since I start doing functional programming, because my team was structuring a component in just two files:

  • src
    • shell.clj
    • core.clj
  • test
    • shell_test.clj
    • core_test.clj

Where in the shell.clj was living just the side effect functions and in the core just the pure functions. I think this is a good pattern and helps a lot with the code organisation.

The Syntax

The new functional syntax gave me a headache, even more when you see that everything starts with ( and you might end up your statement like this ))}])).If you are using VSCode I would recommend the Bracket Pair Colorizer.

Was there any benefit? Can I replace OOP with Functional?

There are benefits, but only when you are using it in the right place. But where is the right place?

For example, for building small programs that are doing mathematical computations, I find amazing using functional programming because of the syntax. Why to make things more complicated than it needs? Why to try to design classes with methods, make it less readable, if you can just write a couple of functions and your job is done?

Which Programming Paradigm are you using?

Leave a Reply

Your email address will not be published. Required fields are marked *