Functional.Programming

I like to think about Functional Programming as another level of abstraction that brings the code far from the physical machine, maybe like the next step after the Memory Management that has hidden the memory location. I like to think about Functional Programming as a guidance to create an application without memory assignments.

It is all about Immutability

What is the problem with memory assignment; or in other words, what is the problem with mutable data? In a context where every software runs in parallel, shared mutable states are a problem, a big problem. Plenty of solutions has been built to solve it but at the end they all imply a sort of synchronization with locks and waitings and potentially performances and scalability issues.

Another way to solve the problem is by avoiding it in the first place, so writing a software without any shared mutable states; or in other terms, using exclusively immutable data structures.

In this context a paradigm that works well with immutability can very attractive. Functional Programming fits very well in this role and it can be seen like a discipline that helps to abstracts the software from the need of memory assignments.

Be Functional

How well Functional Programming fits with immutability? The base principle of Functional Programming is transformation: the function takes an input, applies a transformation and returns an output. This principle has the same expressivity of any imperative code based on memory allocations. Functional Programming offers tools, patterns and disciplines to guide the developer to code with this different paradigm that does not involve memory assignment.

Let’s compare an example of imperative code that calculates the biggest value in a list with the functional version.

List<Integer> list = Arrays.asList(3, 6, 5);
int max = Integer.MIN_VALUE;
for (int value : list) {
  if (value > max) max = value;
}

In this example the imperative code uses the max variable to store the final result while the functional code uses the max parameter.

int calculateMax(List<Integer> list, int max) {
  if (list.isEmpty()) return max;
  else {
    int head = list.get(0);
    List<Integer> tail = list.subList(1, list.size() - 1);
    int newMax = head > max ? head : max;
    return calculateMax(tail, newMax);
  }
}
List<Integer> list = Arrays.asList(3, 6, 5);
calculateMax(list, Integer.MIN_VALUE);

All the other concepts around Functional Programming like pipelines, higher order functions, compositions make more efficient or easier working with immutable data but at end the idea is very simple and it is all about data transformation.

Be Pure

An entire application can be seen a single function, a huge complex function of thousand and thousand lines of code. It is clear that such a thing is not a good practice and luckily functions can be easily modularized: more than one function can be composed together to create a bigger transformation. A simple definition of function composition is using the output of one function as input of another one.

int f(double input) { ... }
String g(int input) { ... }
String output = g(f(1.2));

Pure functions are functions with no side effects: meaning, when a function is called all the observable effects are in the output. If you think about composition you can see how important is the role of the output because it defines the interface between the two functions. For example If the first function throws an Exception the second function would not be able to catch it and it would be out of the transformation flow.

Be Typed

A typed language helps to define the signature of a function: more the type is precise, more the composition is safe. The type assumes the role of interface between functions and consequently part of the software validation is done by the type system through the compiler.

Builder Pattern

In Java one of the most powerful ways to create an instance, except for dependency injection, is using the builder pattern.

The builder pattern helps to create immutable object and avoid to use long or many constructors.

The immutability in Java beans can be guaranteed defining all the attributes final, so once set, they remain the same and the status of the object never changes. As consequence, the constructor should set all the attributes and if there are a lot it can cause misleading set. This because Java constructors use only the position to identify the attributes and place the parameters in the wrong order is very easy, especially of the same type.

public class Person {
  private final String name;
  private final String surname;
  private final Integer age;

  public Person(String name, String surname, Integer age) {
    this.name = name;
    this.surname = surname;
    this.age = age;
  }

  public String getName() { return name; }

  public String getSurname() { return surname; }

  public Integer getAge() { return age; }

}

In this example is easy to declare the Person class with name and surname inverted.

To avoid this problem is possible to use a second class, the Builder, where the constructor is replaced with methods with meaningful names.

public class Builder {

  private String name;
  private String surname;
  private Integer age;

  public Builder withName(String name) {
    this.name = name;
    return this;
  }

  public Builder withSurname(String surname) {
    this.surname = surname;
    return this;
  }

  public Builder withAge(Integer age) {
    this.age = age;
    return this;
  }

  public Person build() {
    return new Person(name, surname, age);
  }

}

The Builder class contains the attributes values until the object is built and each parameter is set through a method.

Person person = new Builder()
  .withName("Alessandro")
  .withSurname("Simi")
  .withAge(32)
  .build();

The disadvantage of this solution (although is a good solution) is the Builder in itself, because requires to have another object and it doesn’t guarantee is used instead of the Person constructor.

To improve the solution the Builder can be defined as inner class of the Person table and reduce the visibility of the constructor, so the object can be created only through the Builder.

public class Person {
  ...
  private Person(String name, String surname, Integer age) {
  ...
  public static class Builder {
    ...
  }
}

Still this solution has two drawbacks. First, the object can be built before all the parameters are set. Second, the Builder is not immutable.

Solving the first problem means introducing a chain of Builders where only the leaf contains the build method. This approach can, for example, divides the mandatory attributes from the optional ones and in general can be expressed through a Fluent Interface.

The immutability can be possible if every method return a new instance of the Builder, but can produce a lot of boilerplate code.

public class Person {
  private final String name;
  private final String surname;
  private final Integer age;

  private Person(String name, String surname, Integer age) {
    this.name = name;
    this.surname = surname;
    this.age = age;
  }

  public String getName() { return name; }

  public Integer getAge() { return age; }

  public String getSurname() { return surname; }

  public static AfterName name(String name) {
    return new Person(name, null, null).new AfterName();
  }

  public class AfterName {
    public AfterAge age(Integer age) {
      return new Person(name, null, age).new AfterAge();
    }
  }

  public class AfterAge {
    public Builder surname(String surname) {
      return new Person(name, surname, age).new Builder();
    }
  }

  public class Builder {
    public Person build() {
      return Person.this;
    }
  }
}

This solution defines the Builder as inner class so it can access to the attributes and create a new instance for each method call. It also forces the creation when all the properties are set.