Programación pointfree en javascript

By | 12 julio, 2016

Javascript es realmente un lenguaje muy flexible. Tiene tanto características funcionales como de orientación a objetos y permite la programación en una gran cantidad de estilos diferentes.
En este post vamos a ver lo que se llama el estilo de programación PointFree y vamos a ir a trabes de algunos escenarios comunes para demostrar sus beneficios.

Un paso atrás.

En primer lugar permitanme mostrarles la forma imperativa estándar para extraer información de una matriz. El bucle for.

¿Qué hace esta función? Vamos a analizarla. Tengo un array de emails vacío. Luego recorro todos los usuarios y verifico si rol de un usuario es igual a “admin”, y si es así añadimos el correo electrónico del usuario al array para finalmente retornar dicho array. ¿bastante familiar no?.

Aunque acabo de describir el código de la función paso a paso, todavía no esta muy claro lo que hace. Una manera mucho mas clara de decir lo que haría seria así: devuelve todos los mensajes de correo electrónico de los usuarios con rol de administrador.

Vamos a reescribir esto de una manera un poco mas funcional, utilizando las funciones propias de Javascript como filter y map. (Estoy usando la sintaxis ECS6, tienes que amar estas funciones de flecha) xd.

El análisis de esta función es mucho mas fácil.
1. Se obtienen solamente los usuarios con el rol del admin.
2. luego se extraen solamente los mensajes de correo electrónico.

El primer punto fuerte de este estilo de programación es que el código de la función se acerca mucho mas a la descripción de lo que hace la función . Esto hace que sea mucho mas fácil entenderla y razonar sobre ella, y al ver una nueva pieza de código se comprende rápidamente lo que se supone que debe hacer dicha función sin la necesidad de entrar en detalle sobre como lo hace.

Los filtros y los mapas nos sirven para iterar sobre los elementos de un array, al igual que el bucle for, pero tienen propósitos específicos: regresan subconjuntos y transformaciones de elementos , respectivamente.
Por el contrario, cualquier cosa puede suceder dentro de un bucle for. Eso significa que cada vez que te encuentres con un código for se tendrá que investigar un poco mas para saber si lo que se desea obtener es un subconjunto o no, si se transformara un elemento , si se agregaran los valores , o cualquier combinación de estos resultados.

Cuando se utilizan filtros y mapas, uno tiene una comprensión mas rápida sobre la función, y se puede profundizar en la comprensión poco a poco a medida que lo necesite. Lo se getAdminEmails retorna un array, ya que tiene filter y map. En una segunda mirada uno ve que primero filtra a los usuarios y luego los transforma.
Ahora uno puede investigar solamente filter y entender que elementos van a ser transformados y comprender que sucede durante la transformación en si.

Componible

Algo que me parece muy interesante sobre este código en su versión funcional, es que uno pude entender fácilmente pieza por pieza lo que hace en las diferentes capas.  Voy a tratar de hacerlo aun mas claro ahora.

Vamos a comenzar por tratar de escribir el código lo mas cerca posible a lo que hace la función. Queremos transformar una lista filtrada, así que vamos a empezar por la composición de estas 2 piezas.

compose es una función que toma 2 funciones como argumento, y ejecuta una después de la otra, su definición mas simple es así:

Ahora vamos a ver las 2 funciones que van a estar compuestas.

getTheEmailsOf es una función que transforma una lista retornando la propiedad email.  “Transformar una lista” es lo que hace map  y obtener una propiedad de un objeto suena como una tarea muy común, así que vamos a implementar map desde un punto de vista un poco diferente y una función prop para obtener una propiedad de un objeto fácilmente.

Esto da lugar a:

onlyTheAdminRoleUsers es un filtro. La prueba para decidir que elementos serán retornados implica comparar si una propiedad es igual a algún valor.

Y la versión definitiva de la función:

Esto es lo que se llama programación PointFree o programación tacita.
Lo que mas sorprende de esta versión es que esta enteramente compuesta de otras funciones mas pequeñas genéricas y reutilizarles. Estas funciones no solamente le ayudaran con sus próximas funciones, sino que le ayudara a comprender mas rápido cualquier función con solo un vistazo.
Después de saber lo que hace prop, se hace mas fácil de entender prop(“algo”) que obj => obj.algo  ademas de que no es necesario entrar en el stress de tener que elegir un nombre para la variable temporal obj.

Nota: La mayoría de estas funciones mas pequeñas son genéricas y lo suficientemente útiles para utilizarlas en casi todos los proyectos.  Ramda es una librería que tiene exactamente eso: un montón de funciones muy pequeñas y genéricas.

Para ir terminando vamos a ver otra situación bastante común.

Este código lo podemos entender rápidamente debido a la familiaridad. Pero el flujo del código es por todo el lugar. Aquí lo que se hace es: Calcular el total de las promociones del primer producto del carrito de compras.

Mira el orden de esta ultima frase, y compara el orden del código anterior con la siguiente función:

Leer el código y entender lo que va a ocurrir es mucho mas sencillo! 🙂

Conclusión
PointFree programming tiene que ver con la modularización de funciones a trabes de la composición. El uso de funciones mas pequeñas, genéricas, bien definidas y bien probadas para construir las funciones que necesitamos. Dentro de compose o composeP, una función es llamada, luego la otra, y esto es lo que pasa. No importa si la función tiene 17 lineas o 3. Esto funciona siempre de la misma manera, y la complejidad del código no se incrementa.

Tampoco tenemos porque preocuparnos acerca de las variables temporales, lo que hace que sea mucho mas fácil de entender el código y mas difícil introducir errores. Ademas, es mas fácil de entender y poner a prueba las partes mas pequeñas del código, lo que hace que sea mas fiable.

Por supuesto que no es una bala de plata, y existen una gran cantidad de veces que uno termina escribiendo una función que no es totalmente pointfree. Me parece que su principal debilidad se produce cuando la función tiene mas de un parámetro (de ahí que usemos curring);  muy a menudo se llega a tener un código no pointfree. Pero, dicho esto, en mi experiencia personal es que la parte pointfree del código es mucho mas robusta y los errores son identificados mas fácilmente durante la fase de desarrollo. Los errores casi nunca se encuentran en código pointfree!!.

Si te gusto el articulo, comentanos :)