La programación funcional puede ayudarnos a crear software más robusto, mantenible y fácil de testear. Quizás hayas empezado a oír hablar de lenguajes de programación funcional como Scala, Haskell o Lisp, pero quizá no sepas todavía que Java en su versión 8 permite usar la potencia de la programación funcional sin abandonar su orientación a objetos.

Pero, ¿qué hace que lenguajes como C, C++ o Java adopten la programación funcional?

Como dijo C.A.R. Hoare:

“Hay dos formas de diseñar software: una forma es hacerlo tan simple que obviamente no haya deficiencias, y la otra es hacerlo tan complicado que no haya deficiencias obvias. El primer método es mucho más difícil”.

Desde que empiezas a programar con Java te enseñan qué es un lenguaje de programación orientado a objetos y que Java es uno de ellos. Te enseñan a programar de manera imperativa y es como has programado desde entonces.

Con estas herramientas tienes que crear la mejor solución posible y hasta hoy no ha ido mal. Pero, ¿y si te digo que hay una forma mejor de llegar a esas soluciones?

En la programación declarativa no definimos cómo queremos resolver un problema, sino que definimos cuál es el problema. Un ejemplo sencillo para comparar estas dos formas de programar es encontrar en una lista de colores si tenemos el color “red”:


boolean hasRed = false;
for (String color : colors) {
   if (color.equals("red")) {
      hasRed = true;
      break;
   }
}
System.out.println("Has color red? " + hasRed);

Aquí vemos cómo estamos definiendo la manera de resolver el problema. Esta forma de hacerlo es muy verbosa y nos hace tener que definir una variable hasRed para marcar si se ha encontrado o no, lo que hace que este código sea un poco “feo”.

¿Y si te digo que ya has usado la forma declarativa?:


System.out.println(“Has color red?:” + colors.contains(“red”));

Esta solución es más concisa, más clara y más fácil de entender por cualquier persona. No sabemos la implementación que estamos usando ya que eso es cosa del código que hay por debajo.

Lo que sí sabemos es exactamente lo que hace ese código: nos dice si colors contiene “red”. Por suerte, para este ejemplo el API de Java nos provee del método contains, que nos ayuda a hacer nuestro código más legible, pero no siempre tendremos esa suerte.

En los casos en los que tengamos que crear nuestros propios métodos podemos usar la programación funcional, que es declarativa y por tanto nos puede ayudar a hacer nuestro código más limpio. Veamos un ejemplo de cómo podemos mejorar nuestro código usando programación funcional.

Dada una lista de números decimales queremos descontar un 20% a todos los que sean mayores de 25 y sumarlos:


BigDecimal sum = BigDecimal.ZERO;
for (BigDecimal number : numbers) {
   if (number.compareTo(BigDecimal.valueOf(25)) > 0) {
      sum = sum.add(number.multiply(BigDecimal.valueOf(0.8)));
   }
}
System.out.println("Total: " + sum);

Seguro que ese código es muy familiar para todos. Como vemos, estamos creando una variable sum donde vamos cambiando su valor en función de las condiciones que hemos definido en el enunciado.

Veamos ahora cómo escribir ese código de una manera mucho más clara de forma funcional primero en Java 8:


final BigDecimal sum =
   numbers.stream()
      .filter(number -> number.compareTo(BigDecimal.valueOf(25)) > 0)
      .map(number -> number.multiply(BigDecimal.valueOf(0.8)))
      .reduce(BigDecimal.ZERO, BigDecimal::add);
System.out.println("Total: " + sum);

Y el mismo código usando Scala:

scala

val sum = numbers.filter(_ > 25)
      .map(_ * .8)
      .sum
    println(sum)

Este código se puede “leer”. Cualquier persona que se ponga delante de él puede leerlo de la siguiente forma:

Estamos declarando el problema mientras escribimos su implementación en el código. Lo único que tenemos que hacer es coger los requisitos de la funcionalidad que queremos implementar y escribirlos.

De esta manera, si alguna vez cambian o si algún otro compañero tiene que mirar nuestro código será muy sencillo saber qué es lo que está haciendo ahora y, por lo tanto, añadir las nuevas especificaciones.

Esta es una pequeña introducción a la programación funcional. Te aconsejo que sigas buscando más acerca de las novedades en Java 8 sobre este paradigma de programación y verás cómo tu código se vuelve más simple y más conciso, haciendo que tenga menos fallos y que los que tenga sean más sencillos de encontrar y corregir.

¿Quieres seguir profundizando en el tema?

Si te interesa el tema de la programación funcional y quieres seguir aprendiendo más sobre ella, no te pierdas esta serie de posts:

Cuéntanos qué te parece.

Los comentarios serán moderados. Serán visibles si aportan un argumento constructivo. Si no estás de acuerdo con algún punto, por favor, muestra tus opiniones de manera educada.

Suscríbete

Estamos comprometidos.

Tecnología, personas e impacto positivo.