Hace un tiempo escribí una artículo sobre el patrón de functional options: Patrón de ‘functional options’.
En este entrada reviso alguno de los errores que cometí al redactarla.
Photo by Mabel Amber
Hace un tiempo escribí una artículo sobre el patrón de functional options: Patrón de ‘functional options’.
En este entrada reviso alguno de los errores que cometí al redactarla.
Uno de los problemas que he encontrado en mi reinterpretación de la API que uso en el trabajo ha sido la conexión con la base de datos.
Siguiendo las buenas prácticas, mi intención era reutilizar el cliente a la base de datos. En vez de usar una variable global, que suele ser la aproximación recomendada, guardaba la struct en el contexto de Gin.
Sin embargo, el contexto se propaga para una misma petición, pero no se mantiene entre peticiones… Así que para cada nueva petición que recibía la API se creaba un nuevo client 😞.
Todo lo relacionado con la base de datos se encuentra en su propio paquete, por lo que tendría sentido crear una variable “global” dentro del paquete…
Sin embargo, seguía quedando pendiente el tema de cerrar la conexión con la base de datos al finalizar la aplicación…
En esta entrada explico la solución que quiero probar (ya veremos si funciona 😉, parece que sí).
El functional options pattern permite crear un objeto con un número arbitrario de “opciones” manteniendo siempre la signature de la función que lo crea.
La idea original fue propuesta, si no estoy equivocado, por Dave Cheney allá por 2014 en el artículo Functional options for friendly APIs. El artículo muestra múltiples maneras de atacar el problema y cómo las functional options es una de la soluciones más sencillas.
Imagina que quieres crear un objeto pizza
. Pero no todo el mundo quiere la misma pizza; unos quieren masa fina, con extra de queso o con peperoni y champiñones, otros masa normal sin ningún extra o topping adicional, etc.
¿Cómo defines la función NewPizza
para que puedas satisfacer a todos tus clientes? Tampoco quieres tener que cambiar la función cada vez que se añada una nueva opción o ingrediente a la pizza…
La solución son las funcional options.
Actualización: 26/12/2023 Algunos aspectos de este artículo quizás no están del todo bien explicados; por ejemplo, las propiedades en
config
están en mayúsculas (exportadas), por lo que se puede establecer sin necesidad de functional options. La signatura de la funciónNewClient
es incorrecta, pues no incluye que devuelve(*DBClient, error)
… En vez de corregirla, he creado una entrada más concisa y sin errores conocidos, al menos por ahora.La nueva entrada es Functional Options revisitadas
Hace unas semanas comentaba que estaba trabajando en un proyecto personal para implementar un parseador de reglas para el proxy, en Go.
Después de leer los artículos Write packages, not programs y From packages to commands de John Arundel (así como los artículos a los que enlaza), decidí enfocar de manera diferente el parseador de reglas del proxy.
Empecé a escribir un nuevo módulo rules
guiado por tests…
El resultado se encuentra disponible en ontehdock/proxy-rules en Github, pero aquí apunto algunas pinceladas (a modo de notas personales).
En la entrada Convertir CSV en JSON con Jq comentaba cómo realizar la conversión de un fichero CSV en JSON usando Jq.
En esta entrada repito (parcialmente) el ejercicio, pero usando Go.
Hace unos días me topé con el vídeo Why You Shouldn’t Nest Your Code del canal CodeAesthetic de YouTube. Me recordó en cierto modo al artículo de Mat Ryer Code: Align the happy path to the left edge.
Aprovechando la calma de estos días, he revisado algo del código que tenemos en algunas de nuestras pipelines. He aplicado las ideas explicadas en estos artículos y el incremento en la claridad del código ha sido espectacular.
En entradas anteriores he escrito sobre cómo interaccionar con una API a través de scripts en Bash, usando curl
y poco más… En vez de dejar en manos de los usuarios la tarea de generar el payload que enviar vía curl
a la API, desarrollé un cliente en Bash: Cliente API en Bash (con curl).
Desde entonces, he estado trabajando en una versión en Go del cliente para ésta API… Y creo que ¡ya está lista 🎉!
En esta entrada, describo por encima cómo funciona, pero sobre todo cómo ha sido la experiencia de desarrollarla.
Hace unos días leía en el foro de Kubernetes el caso de un usuario que no tenía claro cómo hacer que su aplicación fuera escalable, ya que al llegar a un determinado nivel de carga, la aplicación se saturaba.
El problema, por lo que entendí, es que la aplicación hacía “todo el trabajo”: recibía las peticiones de los usuarios, gestionaba las acciones para procesar cada petición y devolvía el resultado a los usuarios una vez finalizado.
Una solución rápida podría ser desplegar un horizontal pod autoscaler, pero probablemente lo ideal sería cambiar la arquitectura de la aplicación…
Así que me puse a ello en mi lenguaje de programación favorito: Go ;)
Habitualmente, al insertar un valor en el backend a través de la API, si la operación tiene éxito, se devuelve el identificador del registro creado.
En el tutorial de Jeremy Morgan Building a Web App with Go and SQLite, se devuelve un mensaje genérico {"message": "success"}
, que no permite realizar acciones adicionales sobre el nuevo registro.
En esta entrada modificamos el código de la función AddPerson
para devolver el identificador del nuevo registro.
En la entrada Mejora al tutorial ‘Building a Web App with Go and SQLite’: limitar el número de registros devueltos por defecto modificamos el código original del tutorial de Jeremy Morgan Building a Web App with Go and SQLite para que el usuario pudiera especificar el número de resultados devueltos al consultar la API a través del parámetro count
: http://<URL>/api/v1/person?count=15
.
El problema es que siempre se devuelven las entradas empezando por la de Id más bajo (habitualmente, 1
).
En esta entrada, modificamos la función getPersonById
para introducir también el parámetro count
y que se devuelvan count
resultados a partir del Id especificado.