Cómo adoptar principios básicos de Programación Funcional

Código más legible es código más mantenible y código más simple es código más legible.

Juan Pablo Rodríguez (ornitie)
IbaDev
4 min readNov 3, 2020

--

Hay un paradigma que cada vez está más de moda, la programación funcional. Sin embargo, cambia muchas reglas de un mundo dominado por el paradigma orientado a objetos. Quizás la mejor forma de implementar (o migrar) a programación funcional es adoptar, inicialmente, parte de sus principios. El día de hoy te traigo tres conceptos claves que puede que quieras considerar incluir en tu estilo de escribir código.

Shahadat Rahman on Unsplash, Definición de “función” para Unsplash

Centrarse más en el qué y no en el cómo

Este es el primer concepto que se explica al hablar de programación funcional y, en particular, de programación declarativa. La programación declarativa es más una forma de aproximarse a los problemas que una práctica en términos estrictos. Según este paradigma, tu código sería un manual de instrucciones en lugar de ser una enciclopedia de cómo se crearon cada una de las partes.

Irónicamente, uno de los conceptos más apreciados de la programación orientada a objetos, la abstracción, es ignorada cuando el proyecto crece demasiado. Tu código debe indicar qué se hace y no el cómo se hace.

Funciones Puras

Las funciones puras son quizás el concepto más fácil de implementar ya que muchos lo hacemos sin siquiera saber que lo hacemos.

Las funciones puras en resumidas cuentas son funciones que, dado un grupo de parámetros, siempre retornará lo mismo sin alterar el estado general de la aplicación. Esto quiere decir que:

  1. La función retornará lo mismo independientemente de quién la implemente.
  2. La función retornará lo mismo independientemente de quién la invoque o bajo qué contexto lo haga.
  3. Al terminar de ejecutar la función, cada aspecto de la aplicación permanece exactamente igual.

Pensemos primero en una implementación tradicional:

Una función no pura que depende de quién la implemente

Partiendo de la noción de que, al ver esta función (y únicamente la función), no tenemos idea de qué es someEntity, sólo sabemos que puede tener la propiedad id. Sin embargo, ese valor puede cambiar a lo largo de la ejecución.

Ahora pensemos en cómo cambiaríamos ligeramente esa implementación de manera más funcional:

Un cambio bastante ligero

Ahora, cualquiera dirá que el cambio es bastante insignificante, pero el hecho de que ahora nuestra función esté accediendo a un objeto que estamos pasando por parámetro, obliga a dicha función a limitar su scope a lo que está dentro de las llaves. No importa qué haga el resto de las funciones en el archivo, no importa quién o dónde invoque la función, esta siempre nos retornará los mismos valores para someEntity.

¿Qué beneficios nos trae esto? Aparte de los mencionados anteriormente respecto a limitar el scope y no tener que preocuparse por el estado de la aplicación al hacer la invocación, las funciones puras son predecibles. Algo que, al momento de hacer debugging será de bastante utilidad.

Inmutabilidad

La inmutabilidad es quizás el concepto que más difícil se me hizo de asimilar. Puesto que implica la no reutilización de las variables, algo con lo que todos aprendimos a programar y, de hecho le de su calidad de variables.

Pero, al igual que el gran maestro de ajedrez, el buen programador debe poder eliminar la mayor cantidad de variables para poder centrarse en lo esencial.

Consideremos el siguiente código que, dados una orden y unos productos asociados a esa orden, la transforma (para ejecutar un request o guardar en base de datos):

Un pipeline para una orden y unos productos

Ahora, el anterior código llama a una serie de funciones y retorna la orden original completamente transformada. En la palabra resaltada está la clave, esta función modifica en cada iteración la orden original, de la cual no queda rastro al terminar la ejecución. Comparemos esto con lo siguiente:

De nuevo, ligero pero no insignificante

El cambio no es tan radical, de hecho solo hay dos cambios notables: el uso de const para guardar el valor de retorno en cada paso de la transformación y que la salida de un proceso es la entrada de otro, a modo de pipeline.

¿Qué nos ofrece esta opción? Sencillo, en primer lugar respetamos el concepto anterior, al no modificar la orden original, estamos respetando el estado general de la aplicación. En segundo lugar, tenemos una trazabilidad mucho mejor, ahora podemos saber paso a paso el estado de la orden sin tener que ahondar en otras funciones.

Conclusión

Estos tres conceptos fueron quizás los que me sirvieron como puerta de entrada a la programación funcional y te invito a que los implementes en la medida de lo posible en tus proyectos. Claramente no hay balas de plata, y cada caso es diferente, pero quizás por eso mismo es importante tratar de implementar las cosas de forma diferente, o al menos pensarlas de forma diferente para implementarlas de forma mejor.

--

--

Juan Pablo Rodríguez (ornitie)
IbaDev

Desarrollador de Software, con hambre de aprender, con gusto por escribir y con ansias de programar.