Optimización de Tareas con Asincronía en Proyectos
El concepto de asincronía es uno de los más relevantes a la hora de trabajar, no sólo en el desarrollo de software, sino que en la gestión de tareas y proyectos en general.
Entender su funcionamiento y correlación entre la abstracción de la programación de aplicaciones y los eventos del mundo real, a mi parecer es clave.
En general, la formación tradicional en el desarrollo de software considera la ejecución de tareas de forma secuencial, en donde una tarea (instrucción) se ejecuta después de la anterior y así secuencialmente hasta que no queden más tareas por completar, es decir, una ejecución de forma síncrona.
Podemos agrupar una serie de tareas en un bloque o sección que se denomina función (método en el caso de acciones realizadas por objetos).
Ahora, bajo este concepto, el programa durante la ejecución de una instrucción o tarea, espera a que esta finalice para continuar con la siguiente.
Si hablamos de instrucciones simples, puede que no se visualice un problema en el uso de un programa, pero en un escenario real, en donde existen diversas tareas que implican mayor tiempo de ejecución, ciertamente se pueden presentar inconvenientes como bloqueos en la ejecución de un programa.
Dado lo anterior, es que resulta muy importante lograr garantizar la ejecución del programa mientras se ejecutan estas tareas que toman tiempos considerables en finalizar.
¿Qué tipo de tareas? Por ejemplo llamar a un API o leer el contenido de un archivo. Más adelante veremos algunos de estos ejemplos.
LA ASINCRONÍA EN EL MUNDO REAL
Al comenzar mi carrera profesional, no fue trivial comprender este concepto.
Por lo tanto me tomo la oportunidad de explicarlo con un par de ejemplos prácticos del mundo real para, de esta forma, contar con un ángulo no tan técnico de explicar y que de paso nos permitirá visualizar como optimizar también los tiempos en nuestras tareas cotidianas.
Luego, les mostraré con un código simplificado, cómo orquestar la ejecución de dos tareas en un programa, tanto de forma síncrona y asíncrona para visualizar la diferencia en tiempos de ejecución.
Ejemplo 1: Tomar desayuno ☕🥞
Imagina que estás preparando y tomando tu desayuno. Tendrías las siguientes tareas:
Si hiciéramos estas tareas de forma secuencial, tardaríamos 25 minutos en total (5+2+3+15).
Sin embargo, en la vida real, resulta posible y lógico preparar por ejemplo las tostadas mientras ponemos a calentar el agua, lo cual nos permitiría ahorrar tiempo, ya que no sumaríamos los 3 minutos de preparar la tostada al tiempo total.
De esta forma, el tiempo total para desayunar se reduciría a 22 minutos en el caso asíncrono (5+2+15).
Ejemplo 2: Tomar una llamada importante y enviar un email. 📞📩
En este caso imaginemos que, dentro de nuestras tareas al iniciar la jornada, tenemos que tomar una llamada importante planificada para una hora específica y por otro lado redactar y enviar un email.
Se darían las siguientes tareas:
Si realizamos estas tareas de forma secuencial síncrona, tardaríamos hasta 30 minutos. Esto porque esperaríamos a que nos llamen, asumamos los 10 minutos. Luego tendríamos la conversación de 5 minutos y tras finalizar la llamada, redactaríamos y enviaríamos el email (10+5+15)
Sin embargo, en la vida real resultaría lógico no perder tiempo e iniciar con la redacción del email y tomar la llamada cuando suene el teléfono para luego seguir con el email.
De esta manera, en el caso asíncrono, el tiempo de espera de la llamada no impactaría en el total del tiempo de las tareas, logrando totalizar 20 minutos (5+15).
En ambos casos resulta de sentido común no tener que esperar a que se finalicen algunas tareas por completo, para iniciar las siguientes, sobre todo en los casos en que una vez que se inicia, nosotros no controlamos su ejecución y esto mismo pasa en el escenario del software.
Ahora, veamos cómo llevamos este escenario al software.
LA ASINCRONÍA EN EL SOFTWARE ⚙️
Como siempre, todo queda más claro con un ejemplo.
Ejemplo de software: Entregar información de una stock (acción de una compañía).
Supongamos que deseamos obtener información de una stock, a partir de su nemotécnico (ticker).
Para ello se tendrían que realizar las siguientes tareas, considerando un tiempo hipotético de ejecución para cada caso:
Ambas acciones necesitarían el nemotécnico de la stock como parámetro.
Una vez obtenida la información, podríamos finalizar su ejecución imprimiendo en pantalla.
Recomendado por LinkedIn
Si ejecutamos las tareas de forma síncrona, tendremos un tiempo de 7 segundos (2+5).
Aquí podemos ver un código de ejemplo para este caso:
Ahora, si ejecutamos las tareas de forma asíncrona, dado que podemos lanzar una tarea sin esperar que finalice la anterior, el tiempo que nos tomaría la ejecución, sería el de la tarea que toma más tiempo, en este caso serían 5 segundos.
Aquí podemos ver un código de ejemplo para este caso:
Considerar que el código está simplificado para que resulte legible su ejecución. Una alternativa opcional para este ejemplo sería utilizar la función Promise.all que junte ambas promesas en un array, de modo que la resolución de la promesa de este array se realice cuando todas las de cada ítem del arreglo se hayan resuelto.
Como se observa en el ejemplo y al igual que en los ejemplos de la vida real, el pensar la ejecución de tareas de forma asíncrona, trae como consecuencia el poder reducir los tiempos de ejecución.
TIPOS DE EJECUCIÓN ASÍNCRONA EN EL SOFTWARE
A continuación les comparto algunas situaciones y operaciones en el desarrollo de software que por lo general son ejecutadas de forma asíncrona:
📌 Llamadas a API externas: Al interactuar con servicios externos, como API web, las llamadas pueden ser realizadas de forma asíncrona para evitar bloquear el flujo de ejecución del programa.
En general las API además tienen tiempos de ejecución desconocidos y variables, ya sea por el volumen de datos de la respuesta o por factores como la velocidad de conexión, por lo que es muy recomendable el uso de asincronía para no ver comprometida la ejecución del programa.
📌 Operaciones de entrada salida (E/S): Muchas operaciones de E/S, como la lectura y escritura de archivos, conexiones de red o consultas a bases de datos, pueden ser ejecutadas de forma asíncrona utilizando técnicas no bloqueantes.
Esto permite que el programa continúe ejecutándose y procesando otras tareas mientras se espera a que la operación de E/S se complete.
📌 Colas de tareas y sistemas de mensajería: Las colas de tareas y los sistemas de mensajería permiten a las aplicaciones enviar y recibir mensajes de forma asíncrona, lo que facilita la comunicación y la coordinación entre diferentes componentes.
📌 Uso de promesas y async/await: En el caso de lenguajes como Javascript usado en NodeJS (uno de mis favoritos), es factible encapsular tareas para realizar su ejecución de forma asíncrona (muchas librerías de paso consideran esta implementación).
ASINCRONÍA VS. PARALELISMO
Aunque la asincronía y el paralelismo pueden parecer similares en ciertos aspectos, considero que es importante hablar un poquito sobre las diferencias entre ambos ya que se suelen confundir.
La asincronía se refiere a la capacidad de ejecutar tareas de forma independiente y sin la necesidad de esperar a que una tarea finalice para comenzar otra.
En este caso no es necesario que se garantice que las tareas se ejecuten al mismo tiempo, pero permite a un programa continuar su ejecución mientras espera que se complete una tarea en segundo plano. Esto puede resultar en una mejor utilización de los recursos y una mejora en el tiempo de ejecución.
Por otro lado, el paralelismo implica la ejecución de varias tareas al mismo tiempo, aprovechando el hardware de múltiples núcleos y procesadores.
En este caso, las tareas se dividen en subprocesos (threads) y se ejecutan simultáneamente en diferentes núcleos del procesador (CPU – GPU). El paralelismo puede mejorar significativamente el rendimiento, especialmente en tareas que requieren un gran volumen de cálculos y procesamiento de dato (por ej. procesamiento científico o renderizado gráfico)
Dicho lo anterior, tenemos que la asincronía se enfoca en cómo las tareas se organizan y se ejecutan de forma independiente, mientras que el paralelismo se centra en la ejecución simultánea de tareas.
Ahora, ambos conceptos son importantes en el desarrollo de software y pueden emplearse juntos para mejorar la eficiencia y el rendimiento de un programa.
YA FINALIZANDO
Como pudimos ver en los ejemplos:
Comprender la asincronía es fundamental para optimizar la gestión de tareas y proyectos en la vida real y también en el desarrollo de software.
Me tomo la licencia de escribir este artículo, más técnico de la habitual, ya que sé de forma empírica que “pensar en asíncrono” es algo que no necesariamente se satisface o domina a la perfección al iniciar la carrera profesional y dada su importancia en la profesión, tengo la esperanza de que este contenido le servirá de ayuda a alguien que esté iniciando en su camino del software, o tal vez a alguien que ya trabajando no logra comprender la importancia de la asincronía en el mundo de la tecnología.
¿Y tú?
📌¿Conocías el concepto de asincronía y su importancia en tecnología?
📌¿Aplicas de forma consciente el uso de asincronía en la vida cotidiana para optimizar tus tareas?
📌¿Tuviste dificultades para entender este concepto a la hora de iniciar en el desarrollo de software?
✌️Agradezco mucho tus comentarios y también que compartas mi contenido, es gratis, muy fácil de compartir y me ayudas un montón 💬.
Puedes ver mis otros artículos accediendo en la parte superior al Newsletter, o si estás en el móvil, haciendo swipe lateral (deslizar hacia los lados 👈📱👉)