Skip to content

Instantly share code, notes, and snippets.

@marcossevilla
Created February 10, 2021 17:13
Show Gist options
  • Save marcossevilla/32e6cf914047d964f3169df0f52d232f to your computer and use it in GitHub Desktop.
Save marcossevilla/32e6cf914047d964f3169df0f52d232f to your computer and use it in GitHub Desktop.

Programación Funcional en Dart con dartz

Functional Programming in Dart with dartz

Cerrá tus ojos un momento.

Estás en primer año de tu carrera de TI, la que sea, acá no se discrimina. Vas a tu primera clase de programación y tu profesor(a) empieza a explicarte qué es un algoritmo y cómo existen en todas partes aunque no se noten a simple vista.

De pronto introduce esta palabra de "programación" y te menciona que existen varios tipos, estilos o como suena más intelectual: paradigmas. Te dice que van a aprender el paradigma estructurado, porque es tu primera clase. Escuchás que también menciona el paradigma orientado a objetos, y tranquilo/a, eso lo vas a ver un semestre más adelante.

Hay varios que menciona que probablemente no te van a enseñar en la universidad, al menos así me pasó a mí. Una de esas fue programación -o el paradigma- funcional. Este paradigma a veces se deja de lado porque no todos los lenguajes permiten implementarlo al pie de la letra.

Como dice el título, este artículo es enfocado en el lenguaje Dart y además en el paquete dartz. Existen otros paquetes para programar funcionalmente en Dart pero no tienen la amplitud ni uso de dartz.

El paradigma funcional

https://media.giphy.com/media/DHqth0hVQoIzS/giphy.gif

Por esa introducción podrás intuir que no soy un experto en este paradigma, pero vamos a centrarnos en lo base para que puedan entender los trucos geniales que se pueden lograr con él.

La programación funcional tiene como características ser declarativa y además tratar a las funciones como un tipo de datos primitivos, o como suena más bonito, ciudadanos de primera clase.

Los que ya conocen bien a Dart saben que calza muy bien con estas características. Nosotros podemos mandar una función a una clase u otra función como propiedad o argumento.

https://gist.github.com/91d8249e2dc45bf0336c37dee28dfffe

Ahí creamos un objeto que es una función y lo podemos ejecutar si lo pasamos como argumento a otra. Compatibilidad con el paradigma, chequeada.

En sí, la programación funcional tiene un origen muy ligado a la matemática ya que usa este fundamento científico para ser capaz de procesar tareas más complejas computacionalmente gracias al reemplazo de ciclos, que aumentan muchas veces la complejidad, por funciones que aceptan funciones como argumento o devuelven como resultado una función. A esas últimas se les llama funciones de orden superior o higher order functions, para los/as bilingües.

Ventajas

La gran pregunta es: ¿cuál es la ventaja que nos trae incorporar este paradigma a nuestro código?

Lo resumiría en que nos permite hacer código más conciso, reduce la complejidad al leerlo al no tener varias sentencias de control en él. Facilita mucho el hacerle pruebas ya que tenemos resultados específicos de funciones. Lo más genial, se puede combinar fácilmente con otros paradigmas.

Desventajas

No todo es bueno, hay algunos problemas cuando necesitamos un estado de variables ya que se devuelven resultados, aquí es donde combinarlo con otros paradigmas es muy útil. Puede ser lento cuando se entra en muchas recursiones.

En general, no es la mejor alternativa para todas las tareas.

Dartz

Este paquete contiene muchas herramientas que nos facilitan incorporar la programación funcional en nuestro proyecto. Vamos por partes ejemplificando.

Primero, como base, vamos a tener una entidad de persona para ejemplificar algunos casos de uso donde podamos utilizar herramientas de programación funcional.

https://gist.github.com/06a63f73da8a1b812b7313aabe68d563

Either

La primera clase que es súper útil es Either. Es una clase abstracta que admite dos tipos de datos como valores de retorno, es decir, puede retornar un entero y una cadena, por ejemplo.

https://gist.github.com/aaf9f65426a146623bf0ea7a94ab1eae

En este caso, definimos una función que retorna un Either que puede contener un valor de int o String. Entonces nuestra función recibe un objeto de persona y en base a un valor aleatorio que generamos, enviamos una respuesta.

Si notan, no regresamos el nombre o la edad de una vez, si no que los envolvemos en una clase Right o Left. El primer valor que definimos en el Either debe ser regresado envuelto en Right y el segundo valor en Left. Estas son las clases que implementan Either y las formas de retornar el resultado del mismo.

https://gist.github.com/6023a648bcb2eb03ed0302ff3f6be784

Ahora que instanciamos la clase y la pasamos como argumento a nuestra función, pasa algo interesante. Ya que nuestra variable puede adoptar dos posibles valores del Either, tenemos un método muy útil llamado fold que nos da acceso a dos funciones que retornan un tipo de dato cada una para realizar alguna acción en específico, como asignaciones o la ejecución de otra función que necesite el argumento que nos devuelve.

Si les parece un poco confuso, vean fold como un if-else para los dos posibles tipos de datos que puede regresar la función.

Esta clase es muy útil cuando hacemos algún llamado un API de terceros que no conozcamos muy bien para poder atrapar cualquier error desconocido y retornarlo en la función.

Option

https://gist.github.com/6154939042072def5a4bcce639d64547

Uno muy similar a Either es Option. A veces no queremos retornar dos posibles valores, y aquí dirán "ah, eso es una función normal" pero Option nos permite más que eso.

Empezando porque nos permite adaptar esa lógica del if para decidir qué se hace en base al resultado obtenido. Se puede utilizar para devolver una validación de la ejecución de alguna operación.

https://gist.github.com/ffc06bceb6f71678c91ae13624ec5623

Tenemos las nuevas clases que la implementan: None y Some. None nos permite devolver un objeto que representa que no se puede efectuar la acción esperada y Some contiene el valor que se esperaba que devolviera la operación efectuada.

Considera None como un valor perdido que no se pudo enviar. Esto nos ayuda a manejar errores generales y la composición de nuestro código de una manera más expresiva.

Ah, sí...

Either y Option son estructuras que se llaman mónadas. Estas pueden ser aplicadas a los tipos de datos para que sigan una secuencia de pasos específicas. Como cuando obtenemos uno de dos valores específicos y ejecutamos alguna acción en base a lo que recibimos.

Hay mónadas mucho más complejas como Evaluation que comprenden distintos tipos de mónadas y se le conoce como la navaja suiza de estas estructuras pero las que hemos visto creo que son suficientes para no complejizar tanto nuestro código.

Palabras de cierre

Pueden adentrarse mucho más en este paquete si quieren, contiene mucha funcionalidad que viene bien si se te dan bastante las matemáticas y teorías de categorización. Yo me considero más pragmático, me gusta bastante este estilo y les comparto esta pequeña parte porque considero que viene bien en cualquier tipo de proyecto.

Igualmente las mónadas que vimos tienen más métodos que les pueden ser de utilidad. Me recuerdan bastante los métodos que tenemos en las clases que hacemos con Freezed pero aplicados a funciones -claro, programación funcional- y a sus valores de retorno.

Muy útil para manejar distintos escenarios en tus proyectos, más que nada posibles errores o resultados imprevistos.

https://media.giphy.com/media/3o7qDT9Yp5DdcN3qi4/giphy.gif

Una cosa más...

También hay versiones inmutables de las colecciones de datos ya existentes en Dart. Por si van a usar datos que no cambian en este tipo de estructura, en el paradigma funcional se ocupan mucho ya que los cambios de variables se hacen a través de las funciones.

Estas incluyen IList, IMap, IVector, IHashMap... entre otras variantes.

https://gist.github.com/61912439e7b03cee1ca0906875b0090a

https://media.giphy.com/media/5rnYD6hCSDBmXXP14U/giphy.gif

Lo de siempre...

Si aprendiste algo nuevo y te fue de utilidad, podés compartir este artículo para ayudar a otro/a desarrollador(a) a seguir mejorando su productividad y calidad al escribir aplicaciones con Flutter.

También hay una versión de este mismo artículo en inglés publicado en dev.to. De nada. 🇺🇸

Además, si te gustó este contenido, podés encontrar aún más y seguir en contacto conmigo en mis redes sociales:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment