La creación de la libreria @yobo/queue

¡Hola #Yobers!

En este artículo os contamos cómo surgió y cual ha sido el proceso de creación de nuestra librería. Además, os detallamos cómo y dónde podéis obtener esta librería para implementarla donde más queráis. Sí, sí, como leéis, toda para vosotros.

Os preguntaréis ¿cómo surgió esta creación? Todo fue gracias a un proyecto que nos pidió un cliente en el cual necesitaba publicar de manera periódica a ciertas horas del día.

Antes de implementar la funcionalidad al cliente, buscamos en internet si había soluciones que lo solventaran, ya que no hay que reinventar la rueda en cada proyecto. Al no encontrar nada que realizara las acciones que necesitábamos, implementamos la funcionalidad acoplada al proyecto del cliente. Tras realizarlo, vimos que esta funcionalidad podíamos modularizarla, es decir, crear una librería (conjunto de métodos) para que se pueda utilizar en cualquier proyecto.

Pero ¿qué es una funcionalidad modularizada? Vamos a poner de ejemplo un armario, de esta manera será mucho más fácil entenderlo. El armario solo tiene una barra en la que se pueden colgar perchas, pero en la tienda nos venden un módulo de cajones. La funcionalidad de este módulo es guardar la ropa en cajones. Al igual que la cajonera, podemos instalar otros módulos como baldas o separadores, entre otros. De esta manera, cada módulo cumple su función.

Si trasladamos este ejemplo al mundo del software, podemos decir que el armario es el proyecto y la cajonera es nuestro modulo, que cumple una función específica y no necesita conocer los otros módulos para otorgar su funcionalidad al proyecto, que en este caso es nuestro armario.

Esta manera de programar se conoce en el ámbito de los paradigmas de programación, como programación modular.

Creacion de la librería

Una vez explicado qué es una funcionalidad modularizada, os detallamos cómo fue la creación de la librería.

Para la creación no se tardó mucho tiempo debido a que la implementación ya estaba realizada en el proyecto del cliente, juntamente con sus tests unitarios. Tuvimos que extraer la funcionalidad a un módulo aparte y preparar los ficheros de configuración para poder subirlo al registro/repositorio de software correspondiente.

Esta librería la utilizamos nosotros mismos en el proyecto del cliente, además de otras ideas en las que la funcionalidad que ofrecía nos venía muy bien.

Por esa misma razón, nosotros tuvimos que analizar si la librería hacía lo que "decimos que hace" o si lo hacía con un buen rendimiento. Para ello, usamos los tests unitarios, funcionales y de rendimiento. Para esta librería hemos publicado los test unitarios, que los podéis encontrar aquí. Como caso curioso, diseñamos dos funciones para ver si una fecha-hora estaba dentro del rango de publicación:

Método 1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
function isInPublishingRange({ startTime, endTime }, now = new Date()) {
  const parseStart = startTime.split(":").map(s => Number(s));
  const parseEnd = endTime.split(":").map(s => Number(s));
  const nowDate = { hour: now.getHours(), minute: now.getMinutes() };
  const startDate = { hour: parseStart[0], minute: parseStart[1] };
  const endDate = { hour: parseEnd[0], minute: parseEnd[1] };

  // Check hours when end date is after midnight
  if (endDate.hour < startDate.hour) {
    // Date between start and midnight
    if (nowDate.hour >= startDate.hour) {
      return true;
      // same hour
    } else if (nowDate.hour >= 0 && nowDate.hour <= endDate.hour) {
      // minutes in range
      if (nowDate.hour === endDate.hour && nowDate.minute > endDate.minute) {
        return false;
      }
      return true;
    }
  } else {
    // In range
    if (nowDate.hour < endDate.hour && nowDate.hour > startDate.hour) {
      return true;
      // same hour
    } else if (
      nowDate.hour === endDate.hour ||
      nowDate.hour === startDate.hour
    ) {
      // minutes in range
      if (
        nowDate.minute > endDate.minute ||
        nowDate.minute < startDate.minute
      ) {
        return false;
      } else {
        return true;
      }
    }
  }
}

Método 2

1
2
3
4
5
6
7
8
9
10
11
12
13
function isInPublishingRange2({ startTime, endTime }, now = new Date()) {
  const startDate = stringTimeToDate(startTime);
  const endDate = stringTimeToDate(endTime);

  if (endDate < startDate) {
    endDate.setDate(endDate.getDate() + 1);
  }
  if (now < startDate) {
    startDate.setDate(startDate.getDate() - 1);
    endDate.setDate(endDate.getDate() - 1);
  }
  return now <= endDate && now >= startDate;
}

Y como las dos funciones cumplían con la funcionalidad para la que estaban diseñadas, pensamos ¿por qué no quedarnos con la más rápida? Es decir, la que mejor rendimiento daba. Para ello, diseñamos una prueba de rendimiento sencilla y comprobamos cual sería la función final para publicar.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
const { isInPublishingRange, isInPublishingRange2 } = require("./index");
const { performance } = require("perf_hooks");

function runNTimes(times, callback) {
  for (let index = 0; index < times; index++) {
    callback({ startTime: "09:00", endTime: "22:00" });
  }
}

function main() {
  var times = 10000;
  for (let index = 0; index < times; index++) {
    getTimes(index);
  }
}

function getTimes(runTimes) {
  var t0a = performance.now();
  runNTimes(runTimes, isInPublishingRange);
  var t1a = performance.now();
  var t0b = performance.now();
  runNTimes(runTimes, isInPublishingRange2);
  var t1b = performance.now();
  console.log(runTimes + "\t" + (t1a - t0a) + "\t" + (t1b - t0b));
}

main();
Resultados del test de rendimiento

Sin embargo, son los usuarios de la librería los que deben comprobar si ésta es funcional para ellos. Ya que, la creación está hecha por y para lo que nosotros queríamos. Por ello, hemos querido que los usuarios puedan obtenerla de manera gratuita y, así, ver si es funcional para ellos.

Para poder obtener la librería y empezar a usarla, solo hay que descargarla del registro de software npm con el comando npm install @yobo/queue. Aquí tenéis el código de la librería y la página web en NPM.JS. Para saber cómo usar la librería, tenéis un ejemplo de uso en un post previo.

Aportación a la comunidad

Realmente, al publicar estos tipos de proyectos no buscamos que nos aporte nada, al contrario, lo que buscamos es aportar nosotros a la comunidad "free software". Gracias a esta comunidad, muchos desarrolladores encontramos librerías y software, los cuales podemos estudiar, analizar, mejorar y volver a compartir.

Esta librería te permite ejecutar una función cada X minutos dentro de un rango de horas. Por ejemplo, quiero enviar un mensaje de Telegram cada 30 minutos desde las 9 de la mañana hasta las 10 de la noche. En eso, concretamente, es en lo que nos ayuda nuestra librería: hacer tareas periódicas en un rango de horas predeterminados.

Además, no tienen por qué ser tareas repetitivas. En la función o callback que se ejecuta puedes poner lo que quieras, lo único que tienes que hacer es dejar que tu imaginación vuele.

Si has llegado hasta aquí es porque te interesa mucho esta creación y te preguntarás ¿Puedo usar yo esta librería? La respuesta es .

Cualquier persona puede usarla. Tan solo hay que saber un poco de programación o constar de algún programador para su instalación y explicación de su funcionalidad. Cualquier sector que la necesite puede descargársela, importarla y usarla. Por ejemplo, una Agencia de Marketing puede utilizarla para publicar un Tweet cada x horas ¡Ahí va la imaginación de cada persona!

Pero lo mejor de todo, la librería no tiene límites. Lo puedes usar en infinidad de proyectos.

Así que coge el proyecto que tienes en mente y adapta la librería a ello. Si necesitas ayuda, no dudes en contactarnos, estamos disponibles para ello. Y, si quieres un proyecto con esta funcionalidad o una nueva en Estudio Yobo haremos realidad tu proyecto.

¡Feliz semana Yobers!