<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Axel Espinosa</title>
    <description>The latest articles on DEV Community by Axel Espinosa (@fromchiapasdev).</description>
    <link>https://dev.to/fromchiapasdev</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F186583%2F9cef57b1-206b-4316-9880-0fe5907f987f.jpeg</url>
      <title>DEV Community: Axel Espinosa</title>
      <link>https://dev.to/fromchiapasdev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/fromchiapasdev"/>
    <language>en</language>
    <item>
      <title>Cómo proteger tu proyecto de paquetes maliciosos en npm</title>
      <dc:creator>Axel Espinosa</dc:creator>
      <pubDate>Sat, 04 Apr 2026 05:57:09 +0000</pubDate>
      <link>https://dev.to/fromchiapasdev/como-proteger-tu-proyecto-de-paquetes-maliciosos-en-npm-gea</link>
      <guid>https://dev.to/fromchiapasdev/como-proteger-tu-proyecto-de-paquetes-maliciosos-en-npm-gea</guid>
      <description>&lt;p&gt;Haces &lt;code&gt;npm install&lt;/code&gt;, confías en que todo está bien, y sin saberlo un script malicioso ya se ejecutó en tu máquina. Así funcionan los ataques de supply chain en npm: infectan paquetes populares (o sus dependencias) y usan los lifecycle scripts para correr código antes de que te des cuenta.&lt;/p&gt;

&lt;p&gt;Este tipo de ataque se viene hablando desde el 2022 pero los atacantes lo han utilizado con mayor frecuencia debido al alcance que logran tener en el ecosistema de npm. Un ejemplo reciente: &lt;a href="https://www.microsoft.com/en-us/security/blog/2025/12/09/shai-hulud-2-0-guidance-for-detecting-investigating-and-defending-against-the-supply-chain-attack/" rel="noopener noreferrer"&gt;Shai Hulud&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;En este post te explico cómo funcionan estos ataques y qué configuraciones puedes aplicar hoy para proteger tus proyectos.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Qué es un "supply chain attack" o ataque a la cadena de suministro?
&lt;/h2&gt;

&lt;p&gt;Este tipo de ataque se caracteriza por infectar alguna parte del ciclo de entrega del software.&lt;br&gt;
Muchos proyectos tienen este ciclo de vida:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Escribir el código&lt;/li&gt;
&lt;li&gt;Instalar paquetes&lt;/li&gt;
&lt;li&gt;Mandar a un ambiente de CI/CD&lt;/li&gt;
&lt;li&gt;Enviar proyecto a producción&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Los ataques de supply chain se insertan en uno de estos pasos comprometiendo toda la cadena de pasos siguientes.&lt;/p&gt;
&lt;h2&gt;
  
  
  ¿Cómo se infecta una librería?
&lt;/h2&gt;

&lt;p&gt;Los atacantes no siempre comprometen el paquete popular directamente. Muchas veces infectan una dependencia interna de ese paquete.&lt;/p&gt;

&lt;p&gt;Tu al instalar el paquete popular, sin saberlo estás instalando también el código de la dependencia infectada.&lt;/p&gt;
&lt;h2&gt;
  
  
  ¿Cómo funcionan los lifecycle scripts en npm?
&lt;/h2&gt;

&lt;p&gt;Los ataques recientes han utilizado una funcionalidad del gestor de paquetes de npm: la capacidad de ejecutar scripts antes o después de la instalación de un paquete.&lt;/p&gt;

&lt;p&gt;A esto se le llaman "lifecycle scripts". Muchos paquetes los usan de manera legítima para preparar pasos previos a la instalación, como la compilación de paquetes nativos. Aunque la documentación de npm recomienda evitarlos, algunos paquetes los necesitan, y es precisamente esa característica la que los paquetes infectados utilizan.&lt;/p&gt;

&lt;p&gt;Como esto es un proceso que sucede antes de que se instale el paquete, nosotros no nos percatamos de lo que se ejecuta. Los paquetes con malware ejecutan todos los pasos que necesitan para infectar tu equipo, robar información y después dejar todo limpio como si nada hubiera pasado. Eso es lo más crítico.&lt;/p&gt;
&lt;h2&gt;
  
  
  ¿Cómo proteger tu proyecto de paquetes maliciosos en npm?
&lt;/h2&gt;

&lt;p&gt;Hay varias medidas que podemos tomar. Vamos una por una.&lt;/p&gt;
&lt;h3&gt;
  
  
  No actualices versiones a lo loco
&lt;/h3&gt;

&lt;p&gt;Es muy común utilizar herramientas como &lt;a href="https://www.npmjs.com/package/npm-check-updates" rel="noopener noreferrer"&gt;npm-check-updates&lt;/a&gt; para actualizar dependencias automáticamente. Siempre queremos tener lo último y pensamos que eso es lo correcto, pero realmente introducimos un vector de ataque.&lt;/p&gt;

&lt;p&gt;La última versión puede traer malware. Mejor revisa qué se publicó, qué cambió en el changelog y si hay reportes antes de actualizar.&lt;/p&gt;
&lt;h3&gt;
  
  
  Bloquea los lifecycle scripts
&lt;/h3&gt;

&lt;p&gt;Como vimos, es por estos scripts que muchos de los ataques suceden. Podemos desactivarlos al instalar una dependencia.&lt;/p&gt;

&lt;p&gt;De manera individual:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--ignore-scripts&lt;/span&gt; &amp;lt;pkg&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;De manera global:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm config &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; ignore-scripts &lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O por proyecto con el archivo &lt;code&gt;.npmrc&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ignore-scripts&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esto se agregó en la versión v11 de npm.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bloquea instalaciones desde Git
&lt;/h3&gt;

&lt;p&gt;Adicional a esto necesitas configurar el flag de &lt;code&gt;allow-git&lt;/code&gt; para evitar que se instalen paquetes desde algún repositorio de Git en vez del registro de npm.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--ignore-scripts&lt;/span&gt; &lt;span class="nt"&gt;--allow-git&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;none &amp;lt;pkg&amp;gt;

&lt;span class="c"&gt;# global&lt;/span&gt;
npm config &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; allow-git none

&lt;span class="c"&gt;# .npmrc&lt;/span&gt;
ignore-scripts&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true
&lt;/span&gt;allow-git&lt;span class="o"&gt;=&lt;/span&gt;none
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Fija la versión de tus dependencias
&lt;/h3&gt;

&lt;p&gt;Algo que yo particularmente no sabía es que fijar las versiones es una buena práctica. Estamos acostumbrados a instalar con &lt;code&gt;npm install&lt;/code&gt; y asumir que el símbolo &lt;code&gt;^&lt;/code&gt; al inicio de la versión en &lt;code&gt;package.json&lt;/code&gt; está bien.&lt;/p&gt;

&lt;p&gt;Pero ese &lt;code&gt;^&lt;/code&gt; significa que al actualizar puedes descargar cualquier versión del paquete que no haga un salto de major version (el primer número). Es decir, si tienes la versión &lt;code&gt;1.x.x&lt;/code&gt;, npm puede instalar cualquier &lt;code&gt;1.y.z&lt;/code&gt; sin preguntarte.&lt;/p&gt;

&lt;p&gt;Para fijar la versión exacta:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-exact&lt;/span&gt; &amp;lt;pkg&amp;gt;

&lt;span class="c"&gt;# global&lt;/span&gt;
npm config &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; save-exact &lt;span class="nb"&gt;true&lt;/span&gt;

&lt;span class="c"&gt;# .npmrc&lt;/span&gt;
save-exact&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  No instales la versión más reciente
&lt;/h3&gt;

&lt;p&gt;Otra precaución: evita instalar el paquete más reciente que existe. Esto puede pasar cuando haces un &lt;code&gt;npm update&lt;/code&gt; o instalas el paquete por primera vez.&lt;/p&gt;

&lt;p&gt;Muchos de los infectados en los ataques fue porque se publicó una versión nueva y muchas personas la instalaron de inmediato. Al paso de unas horas los contribuidores del paquete se dieron cuenta de que el paquete había sido comprometido.&lt;/p&gt;

&lt;p&gt;Para evitar esto existe &lt;code&gt;min-release-age&lt;/code&gt;: configuras cuánto tiempo debe haber pasado desde que se publicó un paquete para que npm lo instale.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--min-release-age&lt;/span&gt; 3 &amp;lt;pkg&amp;gt;

&lt;span class="c"&gt;# .npmrc&lt;/span&gt;
min-release-age&lt;span class="o"&gt;=&lt;/span&gt;3 &lt;span class="c"&gt;# 3 dias (npm usa días)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esta configuración está disponible a partir de la versión v11 de npm.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tu &lt;code&gt;.npmrc&lt;/code&gt; defensivo mínimo
&lt;/h3&gt;

&lt;p&gt;Así queda el &lt;code&gt;.npmrc&lt;/code&gt; mínimo para tus proyectos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;save-exact&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true
&lt;/span&gt;ignore-scripts&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true
&lt;/span&gt;min-release-age&lt;span class="o"&gt;=&lt;/span&gt;3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Y en CI, siempre &lt;code&gt;npm ci --ignore-scripts&lt;/code&gt;, nunca &lt;code&gt;npm install&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Considerar pnpm
&lt;/h2&gt;

&lt;p&gt;pnpm es una alternativa a npm que bloquea los lifecycle scripts por defecto. Personalmente lo estoy usando para mis proyectos porque reduce el consumo de espacio (optimiza los &lt;code&gt;node_modules&lt;/code&gt;) y porque trae estas protecciones incluidas.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bloqueo de dependencias y builds
&lt;/h3&gt;

&lt;p&gt;Por defecto, pnpm bloquea los scripts de pre/post instalación. Si algún paquete legítimo los necesita (como &lt;code&gt;esbuild&lt;/code&gt; o &lt;code&gt;next&lt;/code&gt;), puedes permitirlo explícitamente en el &lt;code&gt;pnpm-workspace.yml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Permitir dependencias que sí pueden usar los lifecycle scripts (pnpm 10+)&lt;/span&gt;
&lt;span class="na"&gt;allowBuilds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;esbuild&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="na"&gt;next&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

&lt;span class="na"&gt;strictDepBuilds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="c1"&gt;# Muestra error si alguna dependencia no listada hace uso de lifecycle scripts&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Tiempo de antigüedad
&lt;/h3&gt;

&lt;p&gt;Como en npm, puedes configurar el tiempo mínimo que debe haber pasado para instalar un paquete:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;allowBuilds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;esbuild&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="na"&gt;next&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

&lt;span class="na"&gt;strictDepBuilds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

&lt;span class="na"&gt;minimumReleaseAge&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1440&lt;/span&gt; &lt;span class="c1"&gt;# mínimo 24 hrs (pnpm usa minutos)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Snyk recomienda que usemos al menos 21 días como periodo para instalar una nueva dependencia.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Cómo funciona &lt;code&gt;trustPolicy&lt;/code&gt;?
&lt;/h3&gt;

&lt;p&gt;pnpm asigna un &lt;strong&gt;nivel de confianza&lt;/strong&gt; a cada versión publicada de un paquete, basado en cómo fue publicada. Los niveles de mayor a menor son:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Trusted Publisher&lt;/strong&gt;: publicado vía GitHub Actions con OIDC (el CI firma criptográficamente que el paquete viene de un workflow específico en un repo específico)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Provenance&lt;/strong&gt;: tiene una prueba verificable de npm que confirma dónde y cómo se construyó el paquete&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Signatures&lt;/strong&gt;: tiene firma del registry de npm&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sin evidencia&lt;/strong&gt;: publicado sin ninguna señal de confianza&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Si configuras &lt;code&gt;trustPolicy: no-downgrade&lt;/code&gt;, pnpm compara el nivel de confianza de la versión que vas a instalar con el de versiones anteriores del mismo paquete. Si la confianza baja (por ejemplo, un paquete que siempre se publicó desde CI de repente aparece publicado sin ninguna evidencia), pnpm aborta la instalación.&lt;/p&gt;

&lt;h2&gt;
  
  
  Revisar antes de instalar
&lt;/h2&gt;

&lt;p&gt;No instales paquetes de manera ciega. Existen herramientas que te ayudan a revisarlos antes.&lt;/p&gt;

&lt;h3&gt;
  
  
  npq
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/lirantal/npq" rel="noopener noreferrer"&gt;npq&lt;/a&gt; te ayuda a revisar lo que piensas instalar antes de siquiera instalarlo. Te advierte de posibles vulnerabilidades.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx npq &lt;span class="nb"&gt;install &lt;/span&gt;express &lt;span class="nt"&gt;--dry-run&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A partir de lo que veas puedes decidir si instalas la última versión o te esperas.&lt;/p&gt;

&lt;h3&gt;
  
  
  Socket Firewall
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://socket.dev/blog/introducing-socket-firewall" rel="noopener noreferrer"&gt;Socket Firewall&lt;/a&gt; es similar a npq pero además te permite usarlo con el manejador de paquetes de Python (uv). Personalmente no lo he utilizado, pero lo mencionan en las buenas prácticas.&lt;/p&gt;

&lt;h2&gt;
  
  
  Medidas adicionales
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Evitar el uso de .env con información sensible
&lt;/h3&gt;

&lt;p&gt;No tengas tus claves de producción, tokens o lo que sea importante en tu &lt;code&gt;.env&lt;/code&gt; de manera plana como solíamos hacerlo. Si bien no subimos esta información a GitHub, en los ataques de supply chain los paquetes maliciosos tienen acceso al entorno donde se ejecutan. Esto quiere decir: tus accesos están expuestos.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.nodejs-security.com/blog/do-not-use-secrets-in-environment-variables-and-here-is-how-to-do-it-better" rel="noopener noreferrer"&gt;Una alternativa es usar secretos. En su blog, Liran te explica cómo hacerlo.&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Usa devcontainers
&lt;/h3&gt;

&lt;p&gt;Personalmente ya sabía que existían pero no suelo trabajar con ellos. En las &lt;a href="https://github.com/lirantal/npm-security-best-practices?tab=readme-ov-file#8-work-in-dev-containers" rel="noopener noreferrer"&gt;buenas prácticas de seguridad de Node.js mencionan&lt;/a&gt; la opción de usarlos para aislar los ataques y reducir el área de ataque a únicamente ese contenedor.&lt;/p&gt;

&lt;p&gt;Si te gustaría un tutorial, déjame un comentario.&lt;/p&gt;

&lt;h3&gt;
  
  
  Verifica tu ambiente
&lt;/h3&gt;

&lt;p&gt;Para verificar si tu ambiente ya bloquea los pre/post scripts puedes probar &lt;a href="https://www.npmjs.com/package/@lavamoat/preinstall-always-fail" rel="noopener noreferrer"&gt;este paquete creado específicamente para eso&lt;/a&gt;. Si la instalación falla, significa que tus protecciones están funcionando.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  npm &lt;span class="nb"&gt;install&lt;/span&gt; @lavamoat/preinstall-always-fail
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  No estamos 100% seguros
&lt;/h2&gt;

&lt;p&gt;Con estas prácticas reducimos el área de ataque, pero lo importante es mantenernos atentos a las noticias de seguridad y reducir el número de paquetes instalados si es posible.&lt;/p&gt;

&lt;p&gt;Entre menos paquetes tengas, menos área de ataque y menos dependencias que vigilar. JavaScript ha evolucionado tanto que muchas cosas que antes necesitaban una librería hoy son triviales de hacer de forma nativa, o la librería estándar de Node.js ya las incluye.&lt;/p&gt;

&lt;p&gt;Con un &lt;code&gt;.npmrc&lt;/code&gt; bien configurado ya reduces la mayoría de los vectores de ataque. Recuerda revisar tus paquetes con npq o algún otra herramienta antes de instalarlos.&lt;/p&gt;

&lt;p&gt;¿Ya tenías alguna de estas configuraciones? ¿Usas alguna otra medida? ¿Hay algo que no sea correcto? Deja tus comentarios.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclaimer: no soy experto en seguridad. Esto es información recopilada para mi propio uso y para ayudar a los demás.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>node</category>
      <category>security</category>
      <category>npm</category>
    </item>
    <item>
      <title>npm install tips para la seguridad</title>
      <dc:creator>Axel Espinosa</dc:creator>
      <pubDate>Tue, 31 Mar 2026 19:10:23 +0000</pubDate>
      <link>https://dev.to/fromchiapasdev/npm-install-tips-para-la-seguridad-3lm9</link>
      <guid>https://dev.to/fromchiapasdev/npm-install-tips-para-la-seguridad-3lm9</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Actualización: Escribí un &lt;a href="https://dev.to/fromchiapasdev/como-proteger-tu-proyecto-de-paquetes-maliciosos-en-npm-gea"&gt;artículo&lt;/a&gt; sobre lo minimo que debes hacer para protegerte&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxwcvjhlyzj5i6k9tj5rj.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxwcvjhlyzj5i6k9tj5rj.gif" alt="Gif espantado por el ataque de NPM hoy" width="334" height="480"&gt;&lt;/a&gt;&lt;br&gt;
Hay un nuevo ataque en el ecosistema de npm y con esto crece la duda de cómo prevenir infectarse.&lt;/p&gt;

&lt;p&gt;Compartamos los mejores consejos para evitar infectarse en los comentarios para mantenernos seguros.&lt;/p&gt;

&lt;p&gt;Empiezo ⬇️&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>npm</category>
      <category>javascript</category>
      <category>node</category>
    </item>
    <item>
      <title>¿Qué son los arrays y para qué sirven? Explicación sencilla</title>
      <dc:creator>Axel Espinosa</dc:creator>
      <pubDate>Fri, 20 Mar 2026 18:40:05 +0000</pubDate>
      <link>https://dev.to/aws/arrays-los-bloques-fundamentales-de-la-programacion-3jmf</link>
      <guid>https://dev.to/aws/arrays-los-bloques-fundamentales-de-la-programacion-3jmf</guid>
      <description>&lt;p&gt;Bienvenido a esta serie de artículos donde cubrimos temas fundamentales de computación. Hoy platicaremos sobre arrays, una de las estructuras de datos más utilizadas en cualquier lenguaje de programación.&lt;/p&gt;

&lt;p&gt;Pero antes de entrar de lleno, necesitamos hablar sobre la memoria. Específicamente, la memoria RAM.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;En estos ejemplos usaremos JavaScript como lenguaje principal y algunos ejemplos básicos de C. No necesitas ser experto en ninguno de los dos.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Cómo funciona la RAM
&lt;/h2&gt;

&lt;p&gt;Todas las computadoras utilizan memoria para funcionar. En particular, hablamos de la memoria RAM, la cual almacena información temporal sobre los programas que estás ejecutando. Cuando digo temporal es porque, cuando la computadora se apaga, toda esa información se pierde y, al encender, la memoria vuelve a estar limpia. Es como si la RAM tuviera mala memoria.&lt;/p&gt;

&lt;p&gt;Al hablar de memoria RAM, es inevitable hablar de direcciones y sé lo que estás pensando. ¿Cómo que direcciones?&lt;/p&gt;

&lt;p&gt;Déjame darte un ejemplo que me ayudó a entender este concepto:&lt;/p&gt;

&lt;p&gt;Imagina un elevador en un edificio. Cada piso tiene un número: 0, 1, 2, 3... y en cada piso hay exactamente una oficina con información. Cuando presionas el botón del piso 42, el elevador no necesita detenerse en cada piso antes. No importa si es el piso 1 o el 99, el tiempo de llegada es prácticamente el mismo. Así funciona la RAM: cada posición de memoria tiene una dirección numérica y tu computadora accede a cualquiera de forma instantánea, sin recorrer las anteriores.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Finhnrgftlyqrubqx45lw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Finhnrgftlyqrubqx45lw.png" alt="Edificio analogía" width="800" height="1509"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Qué es un array?
&lt;/h2&gt;

&lt;p&gt;Ahora imagina que una empresa renta 5 pisos consecutivos para sus 5 departamentos, todos del mismo tamaño. Eso es un array: una secuencia de datos del mismo tipo, almacenados en posiciones contiguas de memoria. Si sabes en qué piso empieza la empresa y cuánto ocupa cada departamento, puedes llegar a cualquiera de ellos con el elevador sin recorrer los demás.&lt;/p&gt;

&lt;p&gt;La contigüidad importa porque, como vimos en la analogía, podemos acceder de manera directa a cualquier elemento sin necesidad de recorrer los anteriores. Tu computadora calcula la dirección exacta del elemento que necesitas y va directo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd8qvvxor1v4szs4tgc5q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd8qvvxor1v4szs4tgc5q.png" alt="Ejemplo de memoria" width="800" height="339"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;En un momento vamos a ver cómo lucen los arrays en código. Por ahora, quédate conmigo para hablar de los tipos de arrays que existen.&lt;/p&gt;

&lt;h2&gt;
  
  
  Arrays estáticos
&lt;/h2&gt;

&lt;p&gt;Los arrays en su forma original son un bloque de memoria contigua con un tamaño fijo. No pueden crecer ni reducirse después de creados. Este tipo de arrays lo vemos en lenguajes como C, donde tú tienes que decirle explícitamente al lenguaje cuántos espacios debe reservarte en la memoria.&lt;/p&gt;

&lt;p&gt;Volviendo a la analogía: la empresa rentó exactamente 5 pisos. Si después necesita un sexto, no hay forma de crecer en el mismo lugar.&lt;/p&gt;

&lt;p&gt;Ventajas: predecible en memoria, sin costo adicional de redimensionamiento.&lt;br&gt;
Limitaciones: Si necesitas más espacio, no puedes agregarlo.&lt;/p&gt;

&lt;p&gt;Este es un ejemplo de cómo se ve un array estático en C:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;my_array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Aquí le estamos diciendo a C: "Reserva espacio para exactamente 10 números enteros". Ni más ni menos.&lt;/p&gt;

&lt;h2&gt;
  
  
  Arrays dinámicos
&lt;/h2&gt;

&lt;p&gt;Los arrays dinámicos resuelven la limitación principal de los estáticos: no necesitas saber de antemano cuántos elementos vas a almacenar. Crecen conforme vas insertando elementos.&lt;/p&gt;

&lt;p&gt;¿Cómo funciona esto por debajo? Cuando el array se llena, el lenguaje crea uno nuevo más grande en otra parte de la memoria y copia todos los elementos. Siguiendo la analogía: cuando la empresa necesita más pisos, se muda a un edificio más grande y lleva todo consigo.&lt;/p&gt;

&lt;p&gt;Ventajas: flexibilidad, no necesitas definir un tamaño desde el inicio.&lt;br&gt;
Desventajas: la cantidad de memoria no es predecible y la "mudanza" tiene un costo.&lt;/p&gt;

&lt;p&gt;En lenguajes como JavaScript y Python, los arrays dinámicos vienen integrados por defecto:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En JavaScript no necesitas preocuparte por declarar el tamaño. El lenguaje se encarga de todo por debajo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkbhcu93gm6188ddy0ov7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkbhcu93gm6188ddy0ov7.png" alt="Arrays dinámicos" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Estáticos vs. Dinámicos
&lt;/h2&gt;

&lt;p&gt;Ahora que conoces ambos tipos, aquí va una comparación directa:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Característica&lt;/th&gt;
&lt;th&gt;Array estático&lt;/th&gt;
&lt;th&gt;Array dinámico&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Tamaño&lt;/td&gt;
&lt;td&gt;Fijo, definido al crear&lt;/td&gt;
&lt;td&gt;Crece automáticamente&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Flexibilidad&lt;/td&gt;
&lt;td&gt;Baja&lt;/td&gt;
&lt;td&gt;Alta&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Uso de memoria&lt;/td&gt;
&lt;td&gt;Predecible&lt;/td&gt;
&lt;td&gt;Variable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Costo de inserción&lt;/td&gt;
&lt;td&gt;No aplica (tamaño fijo)&lt;/td&gt;
&lt;td&gt;O(1) amortizado, O(n) al crecer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lenguajes comunes&lt;/td&gt;
&lt;td&gt;C, C++&lt;/td&gt;
&lt;td&gt;JavaScript, Python, Java (ArrayList)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;En la práctica, la mayoría de lenguajes modernos usan arrays dinámicos por defecto. Pero entender los estáticos te da una mejor perspectiva de lo que sucede por debajo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Operaciones comunes
&lt;/h2&gt;

&lt;p&gt;Vamos a platicar sobre lo que puedes hacer con los arrays. Todos los ejemplos están en JavaScript.&lt;/p&gt;

&lt;h3&gt;
  
  
  Acceso por índice
&lt;/h3&gt;

&lt;p&gt;El acceso por índice nos permite seleccionar un elemento a partir de su posición. Como en el elevador: tú sabes directamente a qué piso vas.&lt;/p&gt;

&lt;p&gt;Los arrays tienen una forma particular de numerar sus elementos. Se empieza a contar a partir del 0.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🥸&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;☺️&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;👻&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🐆&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;👾&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🐶&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// nos devuelve "🥸"&lt;/span&gt;
&lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// nos devuelve "☺️"&lt;/span&gt;
&lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// nos devuelve "🐶"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Insertar al final
&lt;/h3&gt;

&lt;p&gt;Podemos insertar elementos al final del array utilizando el método &lt;code&gt;push()&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🥸&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;☺️&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;👻&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🐆&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;👾&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🐶&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;👏🏻&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// resultado: ["🥸", "☺️", "👻", "🐆", "👾", "🐶", "👏🏻"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Eliminar el último elemento
&lt;/h3&gt;

&lt;p&gt;Podemos eliminar el último elemento del array con &lt;code&gt;pop()&lt;/code&gt;. Este método además te devuelve el elemento que eliminó.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🥸&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;☺️&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;👻&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🐆&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;👾&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🐶&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;eliminado&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;eliminado&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// "🐶"&lt;/span&gt;
&lt;span class="c1"&gt;// resultado: ["🥸", "☺️", "👻", "🐆", "👾"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Obtener longitud
&lt;/h3&gt;

&lt;p&gt;Podemos obtener la longitud de nuestro array con la propiedad &lt;code&gt;length&lt;/code&gt;. Esto nos dice cuántos elementos contiene.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🥸&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;☺️&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;👻&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🐆&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;👾&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🐶&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 6&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Recorrer los elementos
&lt;/h3&gt;

&lt;p&gt;Algo muy utilizado en los programas es recorrer un array, ya sea para mostrar qué elementos hay dentro o para buscar algún elemento. En JavaScript puedes hacer este recorrido con &lt;code&gt;for&lt;/code&gt;, &lt;code&gt;forEach&lt;/code&gt; o &lt;code&gt;map&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🥸&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;☺️&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;👻&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🐆&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;👾&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🐶&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si te das cuenta, aquí acabamos de utilizar lo que aprendimos en los conceptos anteriores. Usamos el acceso por índice con &lt;code&gt;array[i]&lt;/code&gt;. El &lt;code&gt;for&lt;/code&gt; nos ayuda a repetir algo muchas veces y en nuestro ejemplo, vamos aumentando el valor del índice para ir de izquierda a derecha. Y también usamos &lt;code&gt;.length&lt;/code&gt; para saber cuántos elementos tiene el array.&lt;/p&gt;

&lt;h3&gt;
  
  
  Modificar el inicio del array
&lt;/h3&gt;

&lt;p&gt;Podemos hacer modificaciones al inicio del array o en el medio. El detalle es que estas operaciones requieren pasos adicionales. Déjame explicarte.&lt;/p&gt;

&lt;p&gt;Cuando tienes un array, hablamos de posiciones contiguas en memoria.&lt;/p&gt;

&lt;p&gt;Si insertamos un elemento al inicio, necesitamos desplazar todos los elementos una posición a la derecha para hacer espacio. Primero se mueven los elementos y luego se inserta el nuevo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy5r5appthk1yty38jfph.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy5r5appthk1yty38jfph.png" alt="Insertar al inicio" width="800" height="939"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Y al contrario, si eliminamos un elemento del inicio, tenemos que mover todos los elementos que le seguían una posición hacia la izquierda para llenar el hueco.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwttf6mp0perdjoq4q8ni.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwttf6mp0perdjoq4q8ni.png" alt="Eliminar al inicio" width="800" height="751"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Esto hace que sea más costoso que insertar o eliminar al final. En JavaScript podemos hacer estas operaciones con &lt;code&gt;unshift()&lt;/code&gt; para insertar al inicio y &lt;code&gt;shift()&lt;/code&gt; para eliminar del inicio.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;☺️&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;👻&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🐆&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="c1"&gt;// Insertar al inicio&lt;/span&gt;
&lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;unshift&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🥸&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// resultado: ["🥸", "☺️", "👻", "🐆"]&lt;/span&gt;

&lt;span class="c1"&gt;// Eliminar del inicio&lt;/span&gt;
&lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;shift&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="c1"&gt;// resultado: ["☺️", "👻", "🐆"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Costo de las operaciones
&lt;/h2&gt;

&lt;p&gt;Pero no todo es miel sobre hojuelas. Como vimos, es muy fácil trabajar con los arrays pero las operaciones tienen un costo. El costo de las operaciones nos lo indica Big O, una notación matemática que nos ayuda a conocer cuánto tarda una operación a medida que el array crece. Nos ayuda a identificar la mejor estructura de datos para lo que necesitamos.&lt;/p&gt;

&lt;p&gt;En esta tabla te dejo el costo de las operaciones que vimos:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Operación&lt;/th&gt;
&lt;th&gt;Complejidad&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Acceso por índice&lt;/td&gt;
&lt;td&gt;O(1)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Buscar un elemento&lt;/td&gt;
&lt;td&gt;O(n)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Insertar al final&lt;/td&gt;
&lt;td&gt;O(1)*&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Insertar al inicio&lt;/td&gt;
&lt;td&gt;O(n)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Eliminar al final&lt;/td&gt;
&lt;td&gt;O(1)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Eliminar al inicio&lt;/td&gt;
&lt;td&gt;O(n)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;* Amortizado. Ocasionalmente O(n) cuando el array dinámico necesita crecer.&lt;/p&gt;

&lt;p&gt;Las operaciones &lt;code&gt;O(1)&lt;/code&gt; indican que toman tiempo constante. No importa cuántos elementos haya en el array, el tiempo va a ser el mismo. Por eso acceder por índice es tan rápido: tu computadora calcula la dirección exacta y va directo, como el elevador.&lt;/p&gt;

&lt;p&gt;Las operaciones &lt;code&gt;O(n)&lt;/code&gt; quieren decir que toman un tiempo lineal: entre más elementos haya, más tiempo tarda. Por eso insertar al inicio es costoso: hay que mover todos los elementos una posición.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Si quieres saber más sobre Big O y complejidad algorítmica, dime en los comentarios y preparo un artículo dedicado.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Construye tu propia implementación de un array
&lt;/h2&gt;

&lt;p&gt;Vamos a construir tu propia implementación de un array. Para este ejercicio debemos asumir que no tenemos los métodos especiales que vimos anteriormente. Vamos a utilizar el acceso por índices para todo.&lt;/p&gt;

&lt;p&gt;Implementaremos los métodos: &lt;code&gt;get(index)&lt;/code&gt;, &lt;code&gt;push(item)&lt;/code&gt;, &lt;code&gt;pop()&lt;/code&gt; y &lt;code&gt;delete(index)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;El objetivo es que entiendas qué pasa por debajo cuando usas un array y los métodos que los lenguajes de alto nivel nos proporcionan.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyArray&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Índice inválido&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;El array está vacío&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lastItem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="k"&gt;delete&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;lastItem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Índice inválido&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_shiftItems&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;_shiftItems&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;delete&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Probemos nuestra implementación:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;miArray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MyArray&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;miArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🥸&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;miArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;☺️&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;miArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;👻&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;miArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🐆&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;miArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// "🥸"&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;miArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// "👻"&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;miArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// "🐆"&lt;/span&gt;
&lt;span class="nx"&gt;miArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;miArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// "👻"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Este código puedes probarlo en &lt;a href="https://runjs.app/play" rel="noopener noreferrer"&gt;RunJS&lt;/a&gt; o de una forma visual en &lt;a href="https://pythontutor.com/visualize.html#mode=edit" rel="noopener noreferrer"&gt;PythonTutor&lt;/a&gt; que tiene soporte para JavaScript y te muestra el paso a paso.&lt;/p&gt;

&lt;p&gt;Fíjate en el método &lt;code&gt;_shiftItems&lt;/code&gt;: ahí puedes ver exactamente por qué eliminar un elemento del inicio o del medio es O(n). Tenemos que recorrer todos los elementos que están después del índice eliminado y moverlos una posición.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Te reto a que implementes el método &lt;code&gt;unshift(item)&lt;/code&gt; para agregar elementos al inicio. Comparte tu solución en los comentarios&lt;/em&gt;. 💪&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Conclusión
&lt;/h2&gt;

&lt;p&gt;Entender los arrays al principio puede ser intimidante. Recuerdo que yo no entendía cómo recorrer un array con &lt;code&gt;for&lt;/code&gt;, pero con la práctica puedes dominarlo.&lt;/p&gt;

&lt;p&gt;Vimos cómo funciona la memoria RAM con la analogía del elevador, los arrays estáticos y los arrays dinámicos. Recuerda que los arrays dinámicos vienen en los lenguajes de alto nivel como Python o JavaScript, así que no debes preocuparte por declarar los elementos que necesitas de antemano. Pero aun así es bueno tener el entendimiento de lo que sucede por debajo. Eso nos da un mayor panorama.&lt;/p&gt;

&lt;p&gt;En el siguiente artículo vamos a cubrir strings como estructura de datos. Y después de eso, vamos a ver patrones de entrevista con arrays y strings.&lt;/p&gt;

&lt;p&gt;Espero que el artículo te sirva. Coméntame si te gustaría que aborde algún tema con mayor profundidad. Gracias por leer. 🙌🏻&lt;/p&gt;

</description>
      <category>datastructures</category>
      <category>algorithms</category>
      <category>beginners</category>
      <category>coding</category>
    </item>
    <item>
      <title>Cómo construí un videojuego usando Kiro</title>
      <dc:creator>Axel Espinosa</dc:creator>
      <pubDate>Sat, 14 Mar 2026 02:00:17 +0000</pubDate>
      <link>https://dev.to/fromchiapasdev/cavernicolas-dinosaurios-y-codigo-como-construi-un-videojuego-usando-kiro-3ifo</link>
      <guid>https://dev.to/fromchiapasdev/cavernicolas-dinosaurios-y-codigo-como-construi-un-videojuego-usando-kiro-3ifo</guid>
      <description>&lt;p&gt;Quería hacer un videojuego, pero no sabía por dónde empezar. No tenía experiencia en desarrollo de juegos y tampoco estaba familiarizado con los conceptos necesarios. Usé &lt;a href="https://kiro.dev/" rel="noopener noreferrer"&gt;Kiro&lt;/a&gt; y terminé construyendo un clon del dinosaurio de Chrome con un cavernícola huyendo de un T-Rex.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;En este artículo te cuento cómo lo hice: los problemas que aparecieron, cómo los resolví y los prompts que usé por si quieres replicarlo.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Vibecoding
&lt;/h2&gt;

&lt;p&gt;¿Cómo construyes un juego sin saber hacer juegos? Con vibecoding.&lt;/p&gt;

&lt;p&gt;El vibecoding es una forma de prototipar y darle vida a tus ideas sin seguir una metodología formal. Tú describes lo que quieres y la IA lo construye. No es para producción, pero funciona perfecto para algo que quieres probar rápido.&lt;/p&gt;

&lt;p&gt;El juego lo creé con Kiro, un editor que convierte tus ideas en código. Mi rol fue simple: supervisar que los resultados me gustaran. Yo dirigía; Kiro ejecutaba.&lt;/p&gt;

&lt;h2&gt;
  
  
  La idea
&lt;/h2&gt;

&lt;p&gt;Quería construir una versión del clásico dinosaurio de Chrome. Pero en vez de un dinosaurio saltando cactus, quería un cavernícola huyendo de un T-Rex. Algo con personalidad propia.&lt;/p&gt;

&lt;p&gt;La mecánica:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Un cavernícola corre de izquierda a derecha&lt;/li&gt;
&lt;li&gt;Un T-Rex lo persigue desde atrás&lt;/li&gt;
&lt;li&gt;Aparecen obstáculos: cactus que hay que saltar, pterodáctilos que hay que esquivar agachándose&lt;/li&gt;
&lt;li&gt;Cada colisión atrasa al cavernícola y el dinosaurio se acerca&lt;/li&gt;
&lt;li&gt;Si el dinosaurio te alcanza, game over 💀&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conceptos rápidos
&lt;/h2&gt;

&lt;p&gt;Antes de contarte el proceso, quiero repasar tres conceptos para que tengas contexto de lo que hace el código por debajo. Si ya los conoces, salta directo a "El proceso".&lt;/p&gt;

&lt;h3&gt;
  
  
  POO (Programación Orientada a Objetos)
&lt;/h3&gt;

&lt;p&gt;¿Recuerdas esa clase donde veías diagramas UML y hablaban de herencia (lamentablemente no monetaria)? Pues ese paradigma finalmente se usa en algo divertido.&lt;/p&gt;

&lt;p&gt;En los videojuegos, la POO es clave porque cada elemento del juego (el cavernícola, el dinosaurio, los obstáculos) es un objeto con su propio estado y comportamiento. Eso facilita mucho el modelo mental cuando tienes decenas de cosas moviéndose en pantalla. Si quieres un &lt;a href="https://es.wikipedia.org/wiki/Programaci%C3%B3n_orientada_a_objetos" rel="noopener noreferrer"&gt;repaso completo, aquí tienes&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Por si no recuerdas, una clase se ve así:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Game&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dino-chase&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  FPS (Frames Per Second)
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn2kqsj3iyfh9fu1jcl4y.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn2kqsj3iyfh9fu1jcl4y.jpeg" alt="FPS ejemplo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Concepto sencillo pero poco entendido. Los FPS son el número de imágenes que tu computadora logra mostrar en un segundo.&lt;/p&gt;

&lt;p&gt;Imagina un cuaderno donde dibujas en cada hoja una secuencia de una persona moviéndose. Cuando pasas las hojas rápido, el dibujo parece cobrar vida. Eso son los FPS.&lt;/p&gt;

&lt;p&gt;Lo más común es 30, 60 y 120 FPS. Cuantos más FPS, más fluidos se sienten los movimientos. Y eso depende mucho del hardware donde se ejecuta el juego.&lt;/p&gt;

&lt;h3&gt;
  
  
  Game Loop
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpwnl9be0jz4t6i392vo9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpwnl9be0jz4t6i392vo9.png" alt="Gameloop diagrama"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;El game loop es el corazón de cualquier videojuego. Es un bucle que se repite continuamente y hace tres cosas:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Recibe los eventos del usuario (presionar una tecla, mover el mouse)&lt;/li&gt;
&lt;li&gt;Actualiza el estado interno de los personajes y el mapa (por eso necesitamos POO)&lt;/li&gt;
&lt;li&gt;Redibuja la pantalla con las nuevas posiciones, vidas, puntajes, etc.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Este ciclo se repite hasta que el juego termina.&lt;/p&gt;

&lt;h2&gt;
  
  
  El proceso
&lt;/h2&gt;

&lt;p&gt;Aquí es donde se pone interesante. El juego no salió bien a la primera. Ni a la segunda. Fueron varias iteraciones, cada una resolviendo algo que solo descubrí jugando.&lt;/p&gt;

&lt;p&gt;Si quieres replicar lo que hice, puedes usar Kiro. &lt;a href="https://builder.aws.com/content/34X2JujaGkTJed5N2KeMYt1Mz9m/como-comenzar-con-kiro-tu-guia-de-primeros-pasos" rel="noopener noreferrer"&gt;En este tutorial&lt;/a&gt; aprendes a instalar Kiro y, si te registras, obtienes créditos gratis para poder replicar lo que hice. No te vas a gastar ni la mitad de créditos haciendo este juego.&lt;/p&gt;

&lt;h3&gt;
  
  
  0. Preparar el proyecto
&lt;/h3&gt;

&lt;p&gt;Antes del primer prompt necesitas un proyecto de Vite y unos sonidos. Abre tu terminal y corre esto:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm create vite@latest game-with-kiro &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nt"&gt;--template&lt;/span&gt; vanilla
&lt;span class="nb"&gt;cd &lt;/span&gt;game-with-kiro
pnpm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Después crea la carpeta &lt;code&gt;public/game-assets/audio/&lt;/code&gt; y agrega 3 archivos &lt;code&gt;.wav&lt;/code&gt;. El juego los va a usar para reproducir efectos de sonido cuando el cavernícola salte, choque con un obstáculo o agarre un power-up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;jump.wav&lt;/code&gt; para el sonido de salto&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;hitHurt.wav&lt;/code&gt; para cuando te golpeas con algo&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;powerUp.wav&lt;/code&gt; para futuros power-ups&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Los sonidos los puedes encontrar en mi &lt;a href="https://github.com/AxelDavid45/building-games-with-kiro" rel="noopener noreferrer"&gt;repositorio&lt;/a&gt;. O puedes generar los tuyos en &lt;a href="https://sfxr.me/" rel="noopener noreferrer"&gt;sfxr.me&lt;/a&gt; en 2 minutos. Es importante que los tengas listos antes de empezar porque en el primer prompt le vamos a decir a Kiro que los use.&lt;/p&gt;

&lt;p&gt;Con eso listo, ya puedes empezar con los prompts.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. El prompt inicial
&lt;/h3&gt;

&lt;p&gt;Este fue el prompt más importante. Le expliqué a Kiro exactamente qué quería construir:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Quiero crear un videojuego en el navegador. El juego se trata de un clon del juego que tiene Chrome cuando te quedas sin internet.

Quiero hacer mi versión inspirada en ese juego. Quiero que el dinosaurio persiga a un cavernícola y que con cada obstáculo que no logre esquivar, el cavernícola se retrase por milisegundos para que al dinosaurio le dé tiempo de atraparlo.

Conforme vayas avanzando los obstáculos deben acercarse a ti más rápido pero siempre permitiéndole al jugador esquivarlos.

El diseño del juego es pixel art minimalista, usando solo tonos de gris. El juego usa la tecla espaciadora o las flechas del teclado.
Los obstáculos son infinitos: cactus en el suelo y pterodáctilos volando donde el cavernícola tenga que agacharse o saltarlos.

Consideraciones:
- Utiliza los sonidos que tengo en la carpeta public/game-assets/audio/
- Todo el trabajo debe ser hecho en la carpeta src/
- Utilizamos Vite
- Utilizamos pnpm
- Los sprites deben ser dibujados con canvas no usar imágenes externas
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kiro creó todo el proyecto. Corrí &lt;code&gt;pnpm dev&lt;/code&gt;, abrí &lt;code&gt;http://localhost:5173&lt;/code&gt; y ya había algo funcionando.&lt;/p&gt;

&lt;p&gt;¿Pero fue suficiente? No del todo.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Simplificar el fondo
&lt;/h3&gt;

&lt;p&gt;El primer problema que encontré: el fondo tenía demasiados elementos. Volcanes, gradientes, parallax. Se veía laggeado y no se sentía como el juego original.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;El fondo se ve laggeado con cada actualización. Mantenlo minimalista como el juego original de Chrome: fondo gris claro sólido, nubes simples, una línea de suelo. Sin volcanes ni parallax complejo.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Los obstáculos tardaban mucho en aparecer
&lt;/h3&gt;

&lt;p&gt;El juego se sentía aburrido. Pasaban segundos sin que apareciera nada.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Necesito que los obstáculos no tarden tanto en aparecer. Que a veces haya que saltar obstáculos seguidos o agacharse para que sea un poco más difícil.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Con eso ya se sentía como un juego de verdad.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Obstáculos imposibles de esquivar
&lt;/h3&gt;

&lt;p&gt;A veces aparecían dos obstáculos encimados, o uno aparecía justo cuando estaba cayendo de un salto. Imposible esquivarlos.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Tenemos un bug: cuando el cavernícola salta, a veces aparece un obstáculo tan cerca que ya no me permite saltar de nuevo y me cuenta como un golpe. Además dos obstáculos aparecen al mismo tiempo. Necesito que eso se arregle.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kiro cambió el sistema de spawn para usar distancia mínima entre obstáculos en vez de tiempo. Mucho mejor.&lt;/p&gt;

&lt;p&gt;Pero algo seguía sintiéndose raro. 🤔&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Mejorar la respuesta de los controles
&lt;/h3&gt;

&lt;p&gt;Este fue un momento clave. Presionaba saltar en el momento correcto, pero el juego no respondía porque el cavernícola todavía estaba en el aire del salto anterior.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Implementa un input buffer porque cuando aparecen combos parece que no logra saltar los obstáculos aunque yo le aplaste la tecla en el tiempo adecuado.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kiro implementó dos técnicas clásicas de platformers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Input Buffer (150ms): Si presionas saltar mientras estás en el aire, el juego recuerda ese input y salta automáticamente cuando aterrices.&lt;/li&gt;
&lt;li&gt;Coyote Time (80ms): Tienes una ventana pequeña para saltar incluso después de empezar a caer.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Esto hizo que el juego se sintiera responsivo. Los combos de obstáculos ahora sí se podían esquivar.&lt;/p&gt;

&lt;p&gt;Perfecto. La mecánica básica ya funcionaba. Pero faltaba algo para competir con amigos.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. El contador y high score
&lt;/h3&gt;

&lt;p&gt;Sin puntaje no hay competencia.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Implementa el counter del juego con high score guardado en localStorage. El formato debe ser de 5 dígitos como el juego original de Chrome.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ahora sí podía retar a mis amigos.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. El efecto dominó
&lt;/h3&gt;

&lt;p&gt;Este fue el bug más difícil. Me tomó varias iteraciones resolverlo.&lt;/p&gt;

&lt;p&gt;El problema era un ciclo vicioso:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Chocas con un obstáculo → el cavernícola se atrasa&lt;/li&gt;
&lt;li&gt;Al atrasarte, el siguiente obstáculo ya está encima tuyo&lt;/li&gt;
&lt;li&gt;Chocas de nuevo → te atrasas más&lt;/li&gt;
&lt;li&gt;Se repite hasta game over&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Era injugable. Le pedí esto a Kiro:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Si choco varias veces es imposible sortear los objetos siguientes porque queda muy cerca de ellos. Necesito que al colisionar se limpien los obstáculos cercanos y haya un periodo de inmunidad para recuperarse.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La solución combinó varias técnicas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Inmunidad de 500ms después de cada colisión&lt;/li&gt;
&lt;li&gt;Limpieza de obstáculos en un radio de 250px al colisionar&lt;/li&gt;
&lt;li&gt;Recuperación de posición más rápida, proporcional a la velocidad del juego&lt;/li&gt;
&lt;li&gt;Spawn basado en la posición del jugador, no del borde del canvas&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ahora tocaba preocuparme del dinosaurio.&lt;/p&gt;

&lt;h3&gt;
  
  
  8. Balancear al dinosaurio
&lt;/h3&gt;

&lt;p&gt;El T-Rex alcanzaba al cavernícola demasiado rápido, incluso sin colisiones. La presión tenía que venir de mis errores, no del paso del tiempo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;El dinosaurio alcanza al cavernícola muy rápido. Haz que empiece más atrás y avance más lento. La presión debe venir de las colisiones, no del avance natural del dinosaurio.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kiro redujo la velocidad de avance del dinosaurio de &lt;code&gt;0.2&lt;/code&gt; a &lt;code&gt;0.08&lt;/code&gt;. Ahora la tensión viene de tus errores, no del reloj.&lt;/p&gt;

&lt;h3&gt;
  
  
  9. Pterodáctilos a dos alturas
&lt;/h3&gt;

&lt;p&gt;Para darle más variedad, agregué pterodáctilos a diferentes alturas. Unos que hay que saltar y otros donde hay que agacharse.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Quiero que haya pterodáctilos a dos alturas: altos donde hay que agacharse y bajos donde hay que saltar. Asegúrate de que las figuras estén bien calibradas para que ambas acciones funcionen a cualquier velocidad del juego.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Estructura final del proyecto
&lt;/h2&gt;

&lt;p&gt;Después de todas las iteraciones, la estructura quedó así:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;├── src/&lt;/span&gt;
&lt;span class="s"&gt;│   ├── main.js&lt;/span&gt;          &lt;span class="c1"&gt;# Entry point, pantallas inicio/game over&lt;/span&gt;
&lt;span class="s"&gt;│   ├── game.js&lt;/span&gt;          &lt;span class="c1"&gt;# Game loop, colisiones, score, renderizado&lt;/span&gt;
&lt;span class="s"&gt;│   ├── caveman.js&lt;/span&gt;       &lt;span class="c1"&gt;# Jugador: salto, agacharse, input buffer, inmunidad&lt;/span&gt;
&lt;span class="s"&gt;│   ├── dinosaur.js&lt;/span&gt;      &lt;span class="c1"&gt;# Enemigo perseguidor&lt;/span&gt;
&lt;span class="s"&gt;│   ├── obstacles.js&lt;/span&gt;     &lt;span class="c1"&gt;# Manager + CactusSmall, CactusBig, Pterodactyl&lt;/span&gt;
&lt;span class="s"&gt;│   ├── background.js&lt;/span&gt;    &lt;span class="c1"&gt;# Nubes y decoraciones del suelo&lt;/span&gt;
&lt;span class="s"&gt;│   ├── audio.js&lt;/span&gt;         &lt;span class="c1"&gt;# Gestión de sonidos&lt;/span&gt;
&lt;span class="s"&gt;│   └── style.css&lt;/span&gt;        &lt;span class="c1"&gt;# Estilos de UI&lt;/span&gt;
&lt;span class="s"&gt;├── public/game-assets/&lt;/span&gt;
&lt;span class="s"&gt;│   └── audio/&lt;/span&gt;           &lt;span class="c1"&gt;# Archivos .wav&lt;/span&gt;
&lt;span class="s"&gt;├── index.html&lt;/span&gt;
&lt;span class="s"&gt;└── package.json&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Lo que aprendí
&lt;/h2&gt;

&lt;p&gt;No sabía hacer un videojuego. No sabía qué conceptos necesitaba ni por dónde empezar. Con ayuda de la IA logré construir algo que de otra forma me hubiera tomado semanas de investigación, y probablemente lo hubiera abandonado por frustración.&lt;/p&gt;

&lt;p&gt;Pero aquí viene el detalle: la IA no lo hizo sola. Fueron 9 iteraciones. Cada una requirió que yo jugara, identificara problemas y supiera explicar qué estaba mal. La IA ejecuta, pero tú diriges.&lt;/p&gt;

&lt;p&gt;Si estás estudiando programación y sientes que la IA viene a dejarte sin oportunidades, no pienses eso. Aprende a usarla. Empodérate con ella. Ahora puedes crear ideas más rápido y dedicarle tiempo a lo que realmente importa: entender los fundamentos.&lt;/p&gt;

&lt;p&gt;Ojo, es importante que, aunque la IA escriba el código, tú seas capaz de leerlo y modificarlo cuando algo salga mal. Porque todavía no es perfecta.&lt;/p&gt;

&lt;p&gt;Sigue aprendiendo y no le tengas miedo a la IA. Úsala como lo que es: una herramienta que amplifica lo que ya sabes y una aliada para aprender construyendo.&lt;/p&gt;




&lt;p&gt;Si te animas a hacer tu propia versión, déjame el link a tu repositorio en los comentarios o puedes escribirme en &lt;a href="https://www.linkedin.com/in/axelespinosa/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; si tienes alguna duda.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;También te dejo el link al repositorio de mi juego 👉 &lt;a href="https://github.com/AxelDavid45/building-games-with-kiro" rel="noopener noreferrer"&gt;Repositorio con juego&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>kiro</category>
      <category>ai</category>
      <category>vibecoding</category>
      <category>programming</category>
    </item>
    <item>
      <title>¿Qué es un encoding? Explicación sencilla: ASCII, UTF-8 y Unicode</title>
      <dc:creator>Axel Espinosa</dc:creator>
      <pubDate>Thu, 19 Feb 2026 20:58:11 +0000</pubDate>
      <link>https://dev.to/fromchiapasdev/encodings-por-que-importan-mas-de-lo-que-crees-41a5</link>
      <guid>https://dev.to/fromchiapasdev/encodings-por-que-importan-mas-de-lo-que-crees-41a5</guid>
      <description>&lt;p&gt;La forma en que nos comunicamos digitalmente ha cambiado muchísimo. Hoy nos comunicamos hasta con stickers, pero ¿alguna vez te has preguntado cómo llegamos hasta aquí?&lt;/p&gt;

&lt;p&gt;Seguramente navegando por internet te has encontrado con textos que muestran caracteres extraños como este: &lt;code&gt;M�xico&lt;/code&gt;&lt;br&gt;
Eso tiene un nombre: &lt;a href="https://en.wikipedia.org/wiki/Mojibake" rel="noopener noreferrer"&gt;Mojibake&lt;/a&gt;. Así se le llama al fenómeno de ver caracteres raros cuando hay un error en la codificación del texto. &lt;/p&gt;

&lt;p&gt;En este artículo te explico a detalle qué es la codificación, con ejemplos claros y sencillos.&lt;/p&gt;
&lt;h2&gt;
  
  
  Encodings
&lt;/h2&gt;

&lt;p&gt;El encoding (o en español, codificación) es el proceso de transformar la información de una representación a otra siguiendo reglas específicas. En este contexto, nos enfocaremos en la codificación de caracteres: cómo se representan letras, números y símbolos en formato digital.&lt;/p&gt;

&lt;p&gt;Me imagino que has escuchado que las computadoras solamente entienden &lt;a href="https://es.wikipedia.org/wiki/Sistema_binario" rel="noopener noreferrer"&gt;números binarios: 0 y 1&lt;/a&gt;. Esto es cierto, pero imagina si tuviéramos que usar únicamente esos números para comunicarnos con ellas todos los días. Por eso, los investigadores desarrollaron sistemas que nos facilitan esta comunicación. &lt;/p&gt;

&lt;p&gt;Te muestro un ejemplo con mi nombre. Sería impráctico tener que escribirlo usando solo ceros y unos.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjhwj04xoc2z6qmojd26x.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjhwj04xoc2z6qmojd26x.jpg" alt="Mi nombre en binario" width="800" height="263"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Son demasiados números, ¿cierto? ¿Cómo pasamos de letras a un montón de números?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Preguntas muy buenas, ser, joven Padawan&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Retrocedamos un paso. Entendamos primero de dónde salieron esos números. Te presento a ASCII.&lt;/p&gt;
&lt;h2&gt;
  
  
  ASCII
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/ASCII" rel="noopener noreferrer"&gt;ASCII&lt;/a&gt; son las siglas de &lt;strong&gt;American Standard Code for Information Interchange&lt;/strong&gt;. Es un estándar que nos dice cómo deben representarse las letras como números para que las computadoras lo entiendan y nosotros también podamos entenderlo. &lt;/p&gt;

&lt;p&gt;La primera versión de este estándar fue creada en 1963 y hasta hoy en día sigue siendo importante conocer que existe, porque es fácil de usar y los fabricantes de computadoras se encargan de que todas las PCs entiendan este formato.&lt;/p&gt;

&lt;p&gt;Podemos encontrar la tabla ASCII que muestra cada letra del idioma inglés con un valor en decimal, hexadecimal y binario. Es por eso que pude transformar mi nombre a números binarios: porque cada letra cuenta con un valor que las computadoras pueden entender. &lt;/p&gt;

&lt;p&gt;Te dejo los caracteres que usé:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxvduapin1dhvgno8uuxn.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxvduapin1dhvgno8uuxn.jpg" alt="ASCII Códigos" width="800" height="291"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;La codificación ASCII solo nos provee de 127 caracteres, lo que equivale a 7 bits (2^7). &lt;strong&gt;Esto es importante porque la computadora utiliza 1 byte (8 bits) para poder almacenar un carácter, es decir, que se está desperdiciando un bit.&lt;/strong&gt; &lt;strong&gt;Y precisamente de eso se dieron cuenta los investigadores, así que después decidieron extender esta tabla de caracteres a 256. Ahora un carácter podía utilizar hasta 8 bits, o lo que es igual a 1 byte completo.&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Esta expansión fue clave para que otros países con idiomas y alfabetos diferentes al inglés pudieran usar la codificación sin problemas de compatibilidad.&lt;/p&gt;

&lt;p&gt;Pero aquí viene el detalle: 256 caracteres no son suficientes cuando tienes que representar chino, árabe, cirílico y todos los demás alfabetos del mundo. Cada fabricante empezó a inventar su propia solución, y ahí es donde empezó el problema de &lt;code&gt;M├®xico&lt;/code&gt; que viste arriba. La solución a este caos fue Unicode. &lt;/p&gt;
&lt;h2&gt;
  
  
  Unicode
&lt;/h2&gt;

&lt;p&gt;Unicode se creó en los años 80 y se convirtió en un estándar hoy en día que define más de 1.1 millones de caracteres. Este estándar asigna a cada carácter un código que después, con ayuda de un encoding, se transforma a bits (lo que realmente la computadora entiende). Y no solamente se trata de letras: los emojis también están dentro de Unicode y por eso podemos utilizarlos en cualquier idioma. &lt;/p&gt;

&lt;p&gt;La idea principal de Unicode es evitar que cada fabricante de hardware cree su propio encoding incompatible con los demás. Así, un fabricante en Europa que usa caracteres distintos al inglés puede compartir información con alguien en Asia o en América, evitando el caos de &lt;code&gt;M├®xico&lt;/code&gt; que vimos antes.&lt;/p&gt;

&lt;p&gt;Los códigos Unicode están definidos con un formato hexadecimal y se ven así:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzsxsxg7v84x8dquyv7b4.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzsxsxg7v84x8dquyv7b4.jpg" alt="Unicode codes" width="800" height="481"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Si ves esto y no sabes qué es hexadecimal, te dejo un link a un artículo: &lt;a href="https://en.wikipedia.org/wiki/Hexadecimal" rel="noopener noreferrer"&gt;https://en.wikipedia.org/wiki/Hexadecimal&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Listo. Ya conocemos Unicode y por qué es importante, pero esto solo nos da una pequeña porción del panorama completo. Recuerda que la computadora solo entiende bits, entonces, ¿cómo pasamos de estos códigos hexadecimales a bits? Aquí es donde entra UTF-8 🙌🏻&lt;/p&gt;
&lt;h2&gt;
  
  
  UTF-8 👾
&lt;/h2&gt;

&lt;p&gt;UTF-8 es un encoding creado por el consorcio Unicode (los mismos que crearon el estándar Unicode) y se encarga de transformar los códigos hexadecimales a bits que la computadora pueda entender. &lt;/p&gt;

&lt;p&gt;Algo muy inteligente de UTF-8 es que fue diseñado desde el inicio para ser compatible con ASCII. Los primeros 128 códigos tienen una traducción idéntica, es decir, se conservan los códigos ASCII. Por ejemplo, la letra &lt;code&gt;A&lt;/code&gt; en ASCII es 65 (en decimal) y en UTF-8 también es 65. &lt;/p&gt;

&lt;p&gt;Esto permitió que programas que ya usaban ASCII funcionaran automáticamente con UTF-8, lo que mejoró la adopción y ahora UTF-8 sea el encoding más popular en la web. &lt;/p&gt;

&lt;p&gt;UTF-8 utiliza una transformación dinámica a bits: caracteres simples ocupan solo 1 byte, mientras que caracteres más complejos —con múltiples formas, diacríticos, etc.— pueden ocupar hasta 4 bytes.&lt;/p&gt;

&lt;p&gt;Por ejemplo, este emoji 👾 ocupa 4 bytes completos, mientras que la letra &lt;code&gt;A&lt;/code&gt; solo necesita 1 byte:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvcbcmli0y3t37j6abk7s.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvcbcmli0y3t37j6abk7s.jpg" alt="Tamaño de emoji" width="554" height="182"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Charset y Encoding
&lt;/h2&gt;

&lt;p&gt;Perfecto. Ya sabes cómo funcionan ASCII, Unicode y UTF-8. Pero hay una distinción importante que te ayudará a entender todo el panorama: &lt;strong&gt;charset vs encoding.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Cuando trabajas con bases de datos o creas un documento HTML, seguro has visto una etiqueta o configuración llamada &lt;strong&gt;charset&lt;/strong&gt;. Esto se refiere al &lt;strong&gt;catálogo de caracteres&lt;/strong&gt; que puedes usar en ese documento y que se mostrarán correctamente en pantalla. Es decir, qué caracteres están “permitidos” o “disponibles”. &lt;/p&gt;

&lt;p&gt;El &lt;strong&gt;encoding,&lt;/strong&gt; por otro lado, es la forma en que esos caracteres se transforman a bits para ser almacenados o transmitidos. &lt;/p&gt;
&lt;h3&gt;
  
  
  ¿Por qué importa?
&lt;/h3&gt;

&lt;p&gt;Si no trabajas con el mismo charset en documentos compartidos, terminas con el problema que vimos antes: caracteres rotos, símbolos raros y texto ilegible. &lt;/p&gt;
&lt;h2&gt;
  
  
  Ejemplo práctico
&lt;/h2&gt;

&lt;p&gt;Imagina que creas un archivo de texto con este contenido:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;México
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Creamos el archivo en nuestra computadora y verificamos su encoding con el comando &lt;a href="https://man7.org/linux/man-pages/man1/file.1.html" rel="noopener noreferrer"&gt;file&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;~ &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"México"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; test.txt
~ file &lt;span class="nt"&gt;-I&lt;/span&gt; test.txt
test.txt: text/plain&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;charset&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;utf-8
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Perfecto, está en UTF-8. Ahora intentemos convertirlo a un encoding que no soporte acentos, como &lt;code&gt;ISO-8859-10&lt;/code&gt; (diseñado para idiomas nórdicos: sueco, noruego, danés).&lt;/p&gt;

&lt;p&gt;Usamos la herramienta &lt;a href="https://man7.org/linux/man-pages/man1/iconv.1.html" rel="noopener noreferrer"&gt;&lt;code&gt;iconv&lt;/code&gt;&lt;/a&gt; para transformar el encoding:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;~ iconv &lt;span class="nt"&gt;-f&lt;/span&gt; UTF-8 &lt;span class="nt"&gt;-t&lt;/span&gt; ISO-8859-10 test.txt &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; converted.txt

~ &lt;span class="nb"&gt;cat &lt;/span&gt;converted.txt
M�xico
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;¿Qué pasó? 😳 El archivo ahora contiene caracteres raros donde debería estar la “é”. La terminal no puede mostrarlo bien, pero un editor de texto sí revela el problema:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4pc3zjet3e62i3fsj4ad.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4pc3zjet3e62i3fsj4ad.jpg" alt="Transformación erronea" width="568" height="152"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nuestro archivo original estaba en UTF-8, donde la “é” tiene un código específico. Al convertirlo en ISO-8859-10, &lt;code&gt;iconv&lt;/code&gt; intentó encontrar un equivalente... pero no es lo mismo, por eso se ve raro.&lt;/p&gt;

&lt;p&gt;Ahora, si intentamos convertirlo a ASCII (que en teoría es compatible con UTF-8), vemos que directamente no puede manejar el acento porque en el charset ASCII no existen letras con acento como sí existen en Unicode:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;~ iconv &lt;span class="nt"&gt;-f&lt;/span&gt; UTF-8 &lt;span class="nt"&gt;-t&lt;/span&gt; ASCII &lt;span class="nt"&gt;-c&lt;/span&gt;  test.txt &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; converted.txt
iconv: warning: invalid characters: 1
~ &lt;span class="nb"&gt;cat &lt;/span&gt;converted.txt
Mxico
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Incluso si abres el editor, verás que no se logró transformar la segunda letra:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F54vvk8tmwe55iswg4msi.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F54vvk8tmwe55iswg4msi.jpg" alt="Transformación: elimina una letra" width="516" height="174"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;La letra “é” simplemente desapareció. Para verificar que el nuevo archivo tiene otro encoding, ejecutamos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;~ file &lt;span class="nt"&gt;-I&lt;/span&gt; converted.txt
converted.txt: text/plain&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;charset&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;us-ascii
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ahí está: ahora es &lt;code&gt;us-ascii&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ejemplo en programación
&lt;/h2&gt;

&lt;p&gt;Listo. Ya entendemos la diferencia entre charset y encoding. ¿Pero cómo nos ayuda esto al programar?&lt;br&gt;
Imagina este problema:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"Valida si una cadena de texto contiene únicamente caracteres A-Z y dígitos 0-9"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Para resolverlo, vamos a asumir que la cadena de texto es pequeña y trabajaremos con los códigos ASCII:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;containsOnlyLettersAndNumbers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;char&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;charCodeAt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Evaluating s[&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;]= &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;&lt;span class="s2"&gt; charcode=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;char&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;char&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;48&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;char&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;122&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;char&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;57&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;char&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;65&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;char&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;90&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;char&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;97&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;containsOnlyLettersAndNumbers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;AUDID3222&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;// TRUE&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;containsOnlyLettersAndNumbers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;D444E##RUURUJ&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;// FALSE&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;containsOnlyLettersAndNumbers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;asbueu3$&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;// FALSE&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;containsOnlyLettersAndNumbers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;asbueu3&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;// TRUE&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Este código puedes probarlo con herramientas como &lt;a href="https://runjs.app/play" rel="noopener noreferrer"&gt;RunJS&lt;/a&gt; o de una forma visual con un editor que te muestra el paso a paso que tiene soporte para Javascript: &lt;a href="https://pythontutor.com/visualize.html#mode=edit" rel="noopener noreferrer"&gt;PythonTutor&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusión
&lt;/h2&gt;

&lt;p&gt;Y así llegamos al final. En este artículo vimos cómo funcionan los encodings, por qué un emoji puede ocupar 4 bytes y ejemplos prácticos de transformaciones entre charsets.&lt;/p&gt;

&lt;p&gt;Reacciona:&lt;br&gt;
❤️ Sí, ya lo conocías&lt;br&gt;
🔥 Si te sorprendió algo&lt;br&gt;
💬 Y cuéntame qué fue lo que más te llamó la atención&lt;/p&gt;

&lt;p&gt;Si crees que me faltó algo importante, déjamelo en los comentarios. Te estaré leyendo. 👇&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>programming</category>
      <category>tutorial</category>
      <category>codenewbie</category>
    </item>
    <item>
      <title>Write better unit tests</title>
      <dc:creator>Axel Espinosa</dc:creator>
      <pubDate>Wed, 28 May 2025 18:31:11 +0000</pubDate>
      <link>https://dev.to/fromchiapasdev/10x-improvement-in-unit-tests-4g5j</link>
      <guid>https://dev.to/fromchiapasdev/10x-improvement-in-unit-tests-4g5j</guid>
      <description>&lt;p&gt;Hello, welcome to a new post!&lt;/p&gt;

&lt;p&gt;Today I want to talk about a very important topic that should never be missing in serious software development: unit tests.&lt;/p&gt;

&lt;p&gt;Unit tests are code we write to validate the logic of our program. These tests are characterized by evaluating small parts of the code, such as a function or a class.&lt;/p&gt;

&lt;p&gt;Additionally, unit tests are very useful when refactoring code in the future, as they help ensure that what previously worked correctly continues to do so.&lt;/p&gt;

&lt;p&gt;And really, I think we've all worked on a project where the team is afraid to change certain parts of the code, because we don't know if the changes will affect previously implemented business rules, causing strange behavior and those dreaded bugs.&lt;/p&gt;

&lt;p&gt;The goal of these tests is to give you confidence in what you write and help you deliver as few bugs as possible. However, sometimes projects already have unit tests—maybe even an extensive suite—but simply having them doesn't guarantee you're covered. This happens when tests are outdated or have just been patched with each change, written only to make them pass and keep the CI process quiet, allowing work to continue without interruption.&lt;/p&gt;

&lt;p&gt;This is a clear symptom that your unit tests have become a burden, and the whole team sees them that way. Writing tests becomes a tedious task with no reward. And in these cases, it's true: the tests just slow down development.&lt;/p&gt;

&lt;p&gt;We can avoid this situation by changing our perspective: unit tests are a part of the system and must be treated with the same care as the main codebase.&lt;/p&gt;

&lt;p&gt;Just because they don’t run in production doesn’t mean they should be forgotten after being written once. They must be maintained attentively, updated consciously—not just to keep the report green. For example, if you delete a method or class, you should remove the related tests. If a business rule changes, it's normal for tests to fail at first—but they must be updated to reflect the new logic. Don’t hide the real problem with hacks to make the test pass, and definitely don’t comment it out or delete it.&lt;/p&gt;

&lt;p&gt;Since unit tests are so important, here are some tips I've learned that can help you improve them and feel more confident in your code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Disclaimer: Unit tests alone don’t cover the whole system. It’s important to complement them with other types of tests like E2E, manual QA tests (if you have a QA team), and more. Still, unit tests are our first line of defense when making changes.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Tips
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Tools&lt;/li&gt;
&lt;li&gt;How to name your subject under test&lt;/li&gt;
&lt;li&gt;Write a clear message for your test&lt;/li&gt;
&lt;li&gt;How to avoid test fragility&lt;/li&gt;
&lt;li&gt;What are mocks and when to use them&lt;/li&gt;
&lt;li&gt;How much code coverage should I aim for?&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Tools
&lt;/h2&gt;

&lt;p&gt;In these examples, I'll use &lt;strong&gt;JavaScript&lt;/strong&gt;, but the concepts are language-agnostic. JavaScript is just a tool to communicate the ideas.&lt;/p&gt;

&lt;p&gt;JavaScript has popular libraries you can use to create tests. But first, it’s important to understand the difference between a &lt;strong&gt;Test Runner&lt;/strong&gt; and an &lt;strong&gt;Assertion Library&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;Test Runner&lt;/strong&gt; provides the infrastructure to execute tests in isolation (sometimes even in parallel), along with debugging utilities and more. Examples include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Jest&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mocha&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Assertion Libraries&lt;/strong&gt; may be included with the test runner (as with Jest) or installed separately. Examples include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Chai&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Assert Module&lt;/strong&gt; (built-in with Node.js ≥ v18)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These tools give you functions to validate whatever you need: an object’s content, a date, a string, etc.&lt;/p&gt;

&lt;p&gt;Here’s an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;assert&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node:assert/strict&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deepEqual&lt;/span&gt;&lt;span class="p"&gt;([[[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]],&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[[[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]],&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="c1"&gt;// AssertionError: Expected inputs to be strictly deep-equal:&lt;/span&gt;
&lt;span class="c1"&gt;// + actual - expected ...&lt;/span&gt;
&lt;span class="c1"&gt;// +     3&lt;/span&gt;
&lt;span class="c1"&gt;// -     '3'&lt;/span&gt;
&lt;span class="c1"&gt;// Example from Nodejs Docs https://nodejs.org/docs/latest-v22.x/api/assert.html#assert&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, we expect both arrays to have the same elements.&lt;/p&gt;

&lt;p&gt;You might ask, "Do I really need these libraries if I can do it manually?" And the answer is: yes and no. You could write your own validation methods, or you could save time by using a library that works out of the box.&lt;/p&gt;

&lt;p&gt;To get started, you’ll need to know how to configure these tools. It’s not difficult—the documentation is usually more than enough. Personally, I use &lt;strong&gt;Jest&lt;/strong&gt; in my projects because it comes by default with &lt;strong&gt;NestJS&lt;/strong&gt;, and it includes an assertion library.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Name Your Subject Under Test
&lt;/h2&gt;

&lt;p&gt;The subject under test is often referred to as the &lt;strong&gt;SUT&lt;/strong&gt; (&lt;em&gt;System Under Test&lt;/em&gt;). I liked this naming convention when I read about it in the book &lt;em&gt;Unit Testing&lt;/em&gt;, and I’ve adopted it ever since. It makes it clear what component is being tested and avoids confusion with other variables in the test.&lt;/p&gt;

&lt;p&gt;Of course, this is just a personal preference. You’re free to name it however you like, but always try to make it obvious which part of the system you’re testing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// sum.js&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Calculator&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// sum.spec.js&lt;/span&gt;
&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Calculator&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;SUT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// System Under Test&lt;/span&gt;

  &lt;span class="nf"&gt;beforeEach&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;SUT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Calculator&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nf"&gt;afterEach&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Write a Clear Message for Your Test
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EmailSender&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// validations&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;EmailSender&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;SUT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nf"&gt;beforeEach&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;SUT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;EmailSender&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nf"&gt;afterEach&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{});&lt;/span&gt;

  &lt;span class="c1"&gt;// ❌ Not descriptive&lt;/span&gt;
  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;test method send()&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{});&lt;/span&gt;

  &lt;span class="c1"&gt;// ✅ Clear descriptions&lt;/span&gt;
  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;send(): fails with invalid email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{});&lt;/span&gt;
  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;send(): fails with invalid content&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the example above, we see that we can name our tests however we want, but in the end, we’re the ones affected by poorly described messages—either us or our teammates.&lt;/p&gt;

&lt;p&gt;Imagine someone new joins the project, changes the &lt;code&gt;EmailSender&lt;/code&gt; class, and a test fails. The only message shown is: &lt;code&gt;test method send()&lt;/code&gt;. You’d pull your hair out trying to understand what it does and how to fix it.&lt;/p&gt;

&lt;p&gt;On the other hand, if tests are clearly described—as in the later examples—you quickly get an idea of what might have failed, making the debugging experience much more pleasant.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Avoid Fragility in Your Tests
&lt;/h2&gt;

&lt;p&gt;There’s an approach that can greatly improve your tests and help avoid fragility, false positives, and difficulties when refactoring.&lt;/p&gt;

&lt;p&gt;Often, writing tests reveals how well we’ve applied best practices. This is because when we test our code, we should aim to isolate that unit as much as possible from the rest of the system.&lt;/p&gt;

&lt;p&gt;What this means is: if your function or class relies on external resources like APIs or other classes—and you depend on concrete implementations instead of abstractions—you’re introducing fragility. Any updates to those dependencies might cause your tests to fail for reasons unrelated to the logic you’re actually testing. These false positives, if not addressed, make tests unsustainable.&lt;/p&gt;

&lt;p&gt;If you depend on abstractions instead, testing a component with dependencies becomes much simpler. You can replace those dependencies easily and focus on what really matters: your business rules, algorithms, and logic.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// BAD: Depends on a concrete class&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EmailSender&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;provider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;SNSAWSService&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// concrete class dependency&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// validations&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SNSServiceAws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// GOOD: Uses dependency inversion, easier to test&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EmailSender&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;provider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// abstraction&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// validations&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can solve this by using &lt;strong&gt;dependency injection&lt;/strong&gt; and applying the SOLID principle of &lt;strong&gt;Dependency Inversion&lt;/strong&gt;, which tells us to depend on abstractions—in this case, an interface.&lt;/p&gt;

&lt;p&gt;Another thing that helped me a lot is shifting my perspective: I now focus on &lt;strong&gt;testing what I want the code to do&lt;/strong&gt;, the &lt;strong&gt;outcome&lt;/strong&gt;, instead of worrying about &lt;strong&gt;how&lt;/strong&gt; it’s done.&lt;/p&gt;

&lt;p&gt;This change makes a big difference. It allows you to ignore implementation details (like exact algorithm steps) and focus on verifying that the &lt;strong&gt;desired result&lt;/strong&gt; is correct. When you reflect that in your tests, you achieve greater &lt;strong&gt;robustness&lt;/strong&gt; and &lt;strong&gt;resilience to change&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Don’t waste time testing implementation details that may change. Your goal is to ensure the system behaves as expected from a functional perspective. This leads to more stable and meaningful tests in the long term.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What Are Mocks and When to Use Them?
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Mocks&lt;/em&gt; are, colloquially, functions or classes that replace real dependencies in our tests. Their purpose is to help isolate the code and prevent the use of real services.&lt;/p&gt;

&lt;p&gt;Imagine you need to send an email, an SMS, etc. A good practice would be to &lt;strong&gt;avoid using the real services&lt;/strong&gt; for several reasons: cost, accidentally notifying real users, and because it’s much easier to replace them to have full control over what happens in your code.&lt;/p&gt;

&lt;p&gt;Without &lt;em&gt;mocks&lt;/em&gt;, tests would be too unpredictable, since they would depend on external components.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Jest&lt;/strong&gt; provides built-in methods to create &lt;em&gt;mocks&lt;/em&gt; and &lt;em&gt;spies&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The difference between them is that &lt;em&gt;spies&lt;/em&gt; allow you to track calls made to the &lt;em&gt;mock&lt;/em&gt;—you can check what arguments were passed, how many times it was called, in what order, and so on.&lt;/p&gt;

&lt;h3&gt;
  
  
  One Important Note Before the Example:
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;You don’t always need to make assertions on your mocks.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is because, in many cases, it's not relevant to the logic you're testing. Also, making unnecessary assertions can introduce fragility into your tests, since &lt;em&gt;mocks&lt;/em&gt; simulate external dependencies that may change over time.&lt;/p&gt;

&lt;p&gt;However, &lt;strong&gt;it does make sense to assert on mocks when they are relevant to business rules&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For example: if your application must send an email when a user is created, it's important to verify that the email service was called—and with the correct data.&lt;/p&gt;

&lt;p&gt;This helps you confirm that your code is truly executing the key actions that matter to your business.&lt;/p&gt;

&lt;p&gt;Now, let’s look at an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// notification.test.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;emailService&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./emailService.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;notifyNewUser&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./notification.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;beforeEach&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Restore original behavior&lt;/span&gt;
  &lt;span class="nx"&gt;spy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mockRestore&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;notifyNewUser: sends a welcome email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Spy on sendEmail and prevent real call&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;spy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;spyOn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;emailService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sendEmail&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mockResolvedValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;spy-ok&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;u@e.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Axel&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;SUT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;notifyNewUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Verify parameters and return value&lt;/span&gt;
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;spy&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toHaveBeenCalledWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;u@e.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Welcome!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hi Axel, thanks for joining.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;spy-ok&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Code Coverage
&lt;/h2&gt;

&lt;p&gt;Lastly, when it comes to code coverage, I believe having a test suite that covers around &lt;strong&gt;80% of your code&lt;/strong&gt; is a very good goal.&lt;/p&gt;

&lt;p&gt;But we must keep in mind that setting a number shouldn't distract us from what truly matters: &lt;strong&gt;taking care of the quality of our tests&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It's not about hitting or exceeding a specific percentage—it's about &lt;strong&gt;writing meaningful tests&lt;/strong&gt;. And as a natural consequence of doing so, you'll likely hit that coverage mark anyway, or get very close to it.&lt;/p&gt;

&lt;p&gt;It’s also important to listen to the team, understand their perspective, and find a way for everyone to feel comfortable. Because when a strict percentage is enforced, the team may focus solely on reaching it, writing tests that add little to no value.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;If you’ve made it this far, I hope you’ve taken something useful that you can start applying right away.&lt;/p&gt;

&lt;p&gt;Writing good unit tests takes &lt;strong&gt;practice and consistency&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Personally, I’m still learning how to improve my own tests, but applying the principles I shared here has definitely helped me improve the quality of my code and avoid many false positives.&lt;/p&gt;

&lt;p&gt;If you have any feedback or want to connect, feel free to reach out on &lt;a href="https://www.linkedin.com/in/axelespinosa/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;, &lt;a href="https://x.com/im_not_ajscoder" rel="noopener noreferrer"&gt;X (Twitter)&lt;/a&gt; as &lt;a href="https://x.com/im_not_ajscoder" rel="noopener noreferrer"&gt;@im_not_ajscoder&lt;/a&gt; or in the comments 🙌🏻&lt;/p&gt;

</description>
      <category>testing</category>
      <category>discuss</category>
      <category>javascript</category>
      <category>learning</category>
    </item>
    <item>
      <title>Mejora tus pruebas unitarias 10x</title>
      <dc:creator>Axel Espinosa</dc:creator>
      <pubDate>Tue, 27 May 2025 22:20:06 +0000</pubDate>
      <link>https://dev.to/fromchiapasdev/mejora-tus-pruebas-unitarias-10x-44ff</link>
      <guid>https://dev.to/fromchiapasdev/mejora-tus-pruebas-unitarias-10x-44ff</guid>
      <description>&lt;p&gt;Hola, bienvenido a un nuevo post!&lt;/p&gt;

&lt;p&gt;Hoy quiero hablar de un tema muy importante, que no puede faltar en un desarrollo serio de software: las pruebas unitarias.&lt;/p&gt;

&lt;p&gt;Las pruebas unitarias son código que escribimos para validar la lógica de nuestro programa. Estas pruebas se caracterizan por evaluar partes pequeñas del código, como una función o una clase.&lt;/p&gt;

&lt;p&gt;Además, las pruebas unitarias son muy útiles para realizar refactorizaciones a futuro sin temor a que, durante este proceso, deje de funcionar lo que ya teníamos correctamente.&lt;/p&gt;

&lt;p&gt;Y es que, en realidad, creo que todos hemos trabajado en algún proyecto donde el equipo tiene miedo de modificar ciertas partes del código, porque no sabemos si lo que vamos a cambiar afectará reglas de negocio ya implementadas, provocando comportamientos extraños y los temidos bugs.&lt;/p&gt;

&lt;p&gt;El objetivo de estas pruebas es que tengas confianza en lo que escribes y que entregues la menor cantidad posible de errores. Sin embargo, a veces los proyectos ya cuentan con pruebas unitarias, e incluso con una suite extensa, pero el simple hecho de tenerlas no garantiza que estés cubierto. Esto sucede porque las pruebas están desactualizadas o solo se han ido “parcheando” con cada cambio, buscando que pasen sin fallar y que el proceso de CI no se queje, lo que permite seguir con el flujo de trabajo sin más.&lt;/p&gt;

&lt;p&gt;Esto es un claro síntoma de que tus pruebas unitarias se han convertido en una carga, y todo el equipo las percibe de esa manera. Hacer pruebas se ve como una tarea ardua sin recompensa. Y en estos casos, es cierto: las pruebas solo ralentizan el desarrollo.&lt;/p&gt;

&lt;p&gt;Podemos evitar esta situación cambiando nuestra perspectiva: las pruebas unitarias son una parte más del sistema y deben recibir el mismo cuidado que el código principal.&lt;/p&gt;

&lt;p&gt;El hecho de que no se ejecuten en producción no significa que deban quedar olvidadas después de haberlas escrito una vez. Deben mantenerse con atención, actualizarse de forma consciente y no solo para que el reporte salga “en verde”. Por ejemplo, si eliminamos un método o clase, hay que eliminar las pruebas relacionadas; si cambia una regla de negocio, es normal que las pruebas fallen al principio, pero debemos corregirlas según la nueva lógica. No debemos ocultar el problema real con trucos para que las pruebas pasen, o peor aún, borrarlas o comentarlas.&lt;/p&gt;

&lt;p&gt;Y como las pruebas unitarias son importantes, aquí tengo algunos consejos que he aprendido y que pueden ayudarte a mejorarlas y a sentirte más seguro con tu código.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Disclaimer: Las pruebas unitarias por sí solas no prueban todo el sistema. Es importante complementar con otros métodos de prueba, como pruebas E2E, pruebas manuales con el equipo de QA (si cuentas con uno), entre otros. Sin embargo, las pruebas unitarias siempre serán nuestra primera red de protección ante los cambios.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Tips
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Herramientas&lt;/li&gt;
&lt;li&gt;¿Como nombrar nuestro sujeto de prueba?&lt;/li&gt;
&lt;li&gt;Escribe un buen mensaje para tu prueba&lt;/li&gt;
&lt;li&gt;¿Como evitar fragilidad en nuestros tests?&lt;/li&gt;
&lt;li&gt;¿Que son los mocks y cuando usarlos?&lt;/li&gt;
&lt;li&gt;¿Que porcentaje de cobertura debe tener mi código?&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Herramientas
&lt;/h2&gt;

&lt;p&gt;En estos ejemplos voy a utilizar &lt;strong&gt;JavaScript&lt;/strong&gt;, pero los conceptos son agnósticos, ya que JavaScript es solo una herramienta para comunicar las ideas.&lt;/p&gt;

&lt;p&gt;En JavaScript existen librerías populares con las que puedes crear pruebas para tu código. Sin embargo, es importante hacer una distinción entre un &lt;strong&gt;Test Runner&lt;/strong&gt; y una &lt;strong&gt;Assertion Library&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Un &lt;strong&gt;Test Runner&lt;/strong&gt; proporciona la infraestructura necesaria para ejecutar las pruebas de manera aislada, algunas incluso en paralelo. También incluye utilidades para hacer &lt;em&gt;debugging&lt;/em&gt;, entre otras características. Algunos ejemplos son:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Jest&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mocha&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Por otro lado, las &lt;strong&gt;librerías de assertions&lt;/strong&gt; pueden venir integradas dentro del &lt;em&gt;test runner&lt;/em&gt; (como ocurre con Jest) o ser externas, en cuyo caso deberás instalarlas por separado. Algunos ejemplos de estas son:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Chai&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Assert Module&lt;/strong&gt; (incluido en Node.js ≥ v18)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Estas herramientas te ofrecen un conjunto de funciones para validar lo que necesites: el contenido de un objeto, una fecha, una cadena de texto, etc.&lt;/p&gt;

&lt;p&gt;Te dejo un ejemplo de código:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;assert&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node:assert/strict&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deepEqual&lt;/span&gt;&lt;span class="p"&gt;([[[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]],&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[[[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]],&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="c1"&gt;// AssertionError: Expected inputs to be strictly deep-equal:&lt;/span&gt;
&lt;span class="c1"&gt;// + actual - expected ... Lines skipped&lt;/span&gt;
&lt;span class="c1"&gt;//&lt;/span&gt;
&lt;span class="c1"&gt;//   [&lt;/span&gt;
&lt;span class="c1"&gt;//     [&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="c1"&gt;//       2,&lt;/span&gt;
&lt;span class="c1"&gt;// +     3&lt;/span&gt;
&lt;span class="c1"&gt;// -     '3'&lt;/span&gt;
&lt;span class="c1"&gt;//     ],&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="c1"&gt;//     5&lt;/span&gt;
&lt;span class="c1"&gt;//   ]&lt;/span&gt;
&lt;span class="cm"&gt;/* Código tomado de la documentación de Nodejs https://nodejs.org/docs/latest-v22.x/api/assert.html#assert*/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En este ejemplo esperamos que el array de la izquierda tenga los mismos elementos que el de la derecha. &lt;/p&gt;

&lt;p&gt;Y te preguntarás, realmente necesito estas librerías si puedo realizarlo manualmente. Y la respuesta es que si y no, podrías hacer tus propios métodos para validar inputs, etc. O ahorrar tiempo y tener algo que funciona con una librería.&lt;/p&gt;

&lt;p&gt;Entonces, para iniciar necesitas conocer como configurar estas herramientas. No es difícil, con la  documentación es más que suficiente para guiarte. Yo utilizó Jest en los proyectos que realizo porque es el que viene por defecto en NestJS y ya no tienes que instalar librerías de assertion. &lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Cómo nombrar nuestro sujeto de prueba?
&lt;/h2&gt;

&lt;p&gt;Al sujeto de prueba también podemos llamarlo &lt;strong&gt;SUT&lt;/strong&gt; (&lt;em&gt;System Under Test&lt;/em&gt;). Es una forma de referirse a él que me gustó cuando leí el libro &lt;em&gt;Unit Testing&lt;/em&gt;, y desde entonces la adopté. Me parece que así queda claro quién está siendo probado y se evita confusión con otros nombres que puedan surgir en el test.&lt;/p&gt;

&lt;p&gt;Claro, esto es solo una preferencia personal. Tú eres libre de nombrarlo como prefieras, pero siempre trata de que sea evidente qué parte del sistema estás probando.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// sum.js&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Calculator&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// sum.spec.js&lt;/span&gt;
&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Calculator&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;SUT&lt;/span&gt; &lt;span class="c1"&gt;// System under test&lt;/span&gt;

    &lt;span class="nf"&gt;beforeEach&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;SUT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Calculator&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="nf"&gt;afterEach&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Escribe un buen mensaje para tu prueba
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EmailSender&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// validations&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;EmailSender&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;SUT&lt;/span&gt; &lt;span class="c1"&gt;// System under test&lt;/span&gt;

    &lt;span class="nf"&gt;beforeEach&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;SUT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;EmailSender&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="nf"&gt;afterEach&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt;

    &lt;span class="c1"&gt;// ❌ no muy descriptivo.&lt;/span&gt;
    &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;test method send()&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt;

    &lt;span class="c1"&gt;// ✅ Buena descripción&lt;/span&gt;
    &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;send(): falla por email invalido&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt;
    &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;send(): falla por contenido invalido&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En el ejemplo anterior nos damos cuenta de que podemos nombrar nuestros tests de cualquier manera, pero al final, quienes terminamos afectados por mensajes con descripciones pobres somos nosotros o nuestros compañeros.&lt;/p&gt;

&lt;p&gt;Imagina que alguien externo llega a trabajar en el proyecto y, al modificar la clase &lt;code&gt;EmailSender&lt;/code&gt;, algo falla. Entonces aparece en la terminal un test con un mensaje como: &lt;code&gt;test method send()&lt;/code&gt;. Yo me arrancaría el cabello tratando de entender, primero, para qué sirve ese test y, segundo, cómo arreglarlo.&lt;/p&gt;

&lt;p&gt;En cambio, si los tests tienen una buena descripción —como en los ejemplos que siguen— te das una idea rápida de qué pudo haber fallado, y haces que la experiencia de &lt;em&gt;debugging&lt;/em&gt; sea mucho más agradable.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Cómo evitar la fragilidad en nuestros tests?
&lt;/h2&gt;

&lt;p&gt;Existe un enfoque que te ayudará a mejorar mucho tus pruebas y a evitar que estas sean frágiles, que aparezcan falsos positivos o que sea difícil hacer refactorizaciones.&lt;/p&gt;

&lt;p&gt;Muchas veces, al escribir tests, nos damos cuenta de qué tan bien hemos aplicado buenas prácticas. Esto sucede porque, al probar nuestro código, debemos tratar de aislar lo más posible esa unidad de código del resto del sistema.&lt;/p&gt;

&lt;p&gt;Con esto me refiero a que, si nuestra función o clase utiliza recursos externos como APIs u otras clases, y no dependemos de abstracciones sino de clases concretas, estaremos agregando fragilidad a las pruebas. En cualquier momento en que se actualicen esas dependencias, los tests pueden fallar por razones que no corresponden al alcance de la prueba unitaria. Esto introduce falsos positivos que, si no se abordan a tiempo, hacen que las pruebas se vuelvan insostenibles.&lt;/p&gt;

&lt;p&gt;Cuando dependemos de abstracciones, escribir una prueba para un componente con dependencias se vuelve mucho más sencillo: podemos reemplazarlas fácilmente y enfocarnos en probar lo que realmente importa, como las reglas de negocio, la lógica o el algoritmo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// EJEMPLO: Depende de clase concreta&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EmailSender&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;provider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;SNSAWSService&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// depende de clase concreta&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// validations&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SNSServiceAws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// EJEMPLO: Utiliza Principio SOLID, facil testear&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EmailSender&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;EmailProviderInterface&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

    &lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// validations&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Este detalle lo podemos resolver mediante &lt;strong&gt;inyección de dependencias&lt;/strong&gt; y aplicando el principio SOLID de &lt;strong&gt;Inversión de Dependencias&lt;/strong&gt;, el cual nos indica que debemos depender de abstracciones. En este caso, eso se traduce en utilizar una interfaz.&lt;/p&gt;

&lt;p&gt;Además, algo que me ha servido mucho es cambiar la perspectiva de cómo escribo mis pruebas. Ahora me enfoco en &lt;strong&gt;probar lo que quiero que haga&lt;/strong&gt;, en el &lt;strong&gt;resultado&lt;/strong&gt;, y ya no me preocupo tanto por &lt;strong&gt;cómo&lt;/strong&gt; tiene que hacerlo.&lt;/p&gt;

&lt;p&gt;Existe una gran diferencia en este enfoque: al cambiar la perspectiva, dejamos de lado el detalle de la implementación —los pasos exactos del algoritmo— y nos centramos en que el &lt;strong&gt;resultado deseado sea correcto&lt;/strong&gt;. Al reflejar esto en nuestras pruebas, logramos una mayor &lt;strong&gt;robustez&lt;/strong&gt; y &lt;strong&gt;resistencia ante cambios&lt;/strong&gt; en el código.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;✅ No pierdas tiempo probando detalles de implementación que podrían cambiar con el tiempo. Tu objetivo debe ser asegurarte de que el sistema haga lo que se espera que haga desde el punto de vista funcional. Esto te permitirá mantener pruebas más estables y significativas a largo plazo.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Que son los mocks y cuando usarlos?
&lt;/h2&gt;

&lt;p&gt;Los &lt;em&gt;mocks&lt;/em&gt; son, de forma coloquial, funciones o clases que reemplazan las dependencias reales en nuestras pruebas. Su propósito es ayudar a aislar el código y evitar que se utilicen los servicios reales.&lt;/p&gt;

&lt;p&gt;Imagina que necesitas enviar un correo electrónico, un SMS, etc. Una buena práctica sería &lt;strong&gt;no usar los servicios reales&lt;/strong&gt; por varios motivos: costos, usuarios notificados erróneamente, y porque es mucho más sencillo reemplazarlos para tener control sobre lo que sucede con nuestro código.&lt;/p&gt;

&lt;p&gt;Sin &lt;em&gt;mocks&lt;/em&gt;, los tests serían demasiado impredecibles, ya que estarían dependiendo de componentes externos.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Jest&lt;/strong&gt; cuenta con sus propios métodos para crear &lt;em&gt;mocks&lt;/em&gt; y &lt;em&gt;spies&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;La diferencia entre ellos es que, con los &lt;em&gt;spies&lt;/em&gt;, puedes hacer un seguimiento de las llamadas al &lt;em&gt;mock&lt;/em&gt;: ver con qué datos se llamó, cuántas veces, en qué orden, etc.&lt;/p&gt;

&lt;h3&gt;
  
  
  Un detalle importante antes de pasar al ejemplo:
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;No siempre necesitas hacer asserts sobre los mocks.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Esto se debe a que, en muchos casos, no es relevante para la lógica que estás probando. Además, hacer asserts innecesarios puede introducir fragilidad en tus pruebas, ya que los &lt;em&gt;mocks&lt;/em&gt; simulan dependencias externas que pueden cambiar con el tiempo.&lt;/p&gt;

&lt;p&gt;Sin embargo, &lt;strong&gt;sí tiene sentido hacer asserts sobre los mocks cuando son relevantes para las reglas de negocio&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Por ejemplo: si tu aplicación debe enviar un correo electrónico cuando se crea un usuario, es importante verificar que el servicio de email se haya llamado, y con los datos correctos.&lt;/p&gt;

&lt;p&gt;Esto te ayuda a confirmar que tu código realmente ejecuta las acciones clave para tu negocio.&lt;/p&gt;

&lt;p&gt;Ahora sí, vamos con el ejemplo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// notification.test.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;emailService&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./emailService.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;notifyNewUser&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./notification.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;beforeEach&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Restauramos el comportamiento original&lt;/span&gt;
  &lt;span class="nx"&gt;spy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mockRestore&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;notifyNewUser: envia un correo de bienvenida&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Espiamos sendEmail y evitamos la llamada real&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;spy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;spyOn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;emailService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sendEmail&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mockResolvedValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;spy-ok&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;u@e.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Axel&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;notifyNewUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Verificamos parámetros y valor de retorno&lt;/span&gt;
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;spy&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toHaveBeenCalledWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;u@e.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;¡Bienvenido!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hola Axel, gracias por unirte.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;spy-ok&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Cobertura de código
&lt;/h2&gt;

&lt;p&gt;Por último, en cuanto a temas de cobertura de código, considero que tener una &lt;em&gt;suite&lt;/em&gt; que cubra alrededor del 80 % del código es algo muy bueno.&lt;/p&gt;

&lt;p&gt;Pero hay que tener en cuenta que, al imponer un número, no debemos olvidar lo más importante: &lt;strong&gt;cuidar la calidad de nuestros tests&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;No se trata de apuntar a un porcentaje específico o de superarlo, sino de &lt;strong&gt;enfocarnos en tener buenas pruebas&lt;/strong&gt;. Y como consecuencia de eso, de forma casi accidental, terminaremos alcanzando ese porcentaje o quedando muy cerca.&lt;/p&gt;

&lt;p&gt;Siempre es importante escuchar al equipo, conocer su opinión y buscar una forma en la que todos se sientan cómodos. Porque puede suceder que, al imponer un porcentaje mínimo, el equipo empiece a enfocarse únicamente en cumplirlo, escribiendo pruebas que no aportan valor real.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusión
&lt;/h2&gt;

&lt;p&gt;Espero que, si llegaste hasta aquí, te hayas llevado algo útil que puedas poner en práctica de inmediato.&lt;/p&gt;

&lt;p&gt;Crear buenas pruebas unitarias requiere práctica y constancia.&lt;/p&gt;

&lt;p&gt;Yo mismo puedo decir que todavía sigo aprendiendo a mejorar las mías, pero aplicar estos puntos sin duda me ha ayudado a mejorar muchísimo la calidad de mis tests y a evitar muchos falsos positivos.&lt;/p&gt;

&lt;p&gt;Si tienes algún comentario, con gusto podemos conectar en &lt;a href="https://www.linkedin.com/in/tu-perfil" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; o en &lt;a href="https://x.com/im_not_ajscoder" rel="noopener noreferrer"&gt;X (Twitter)&lt;/a&gt; como &lt;a href="https://x.com/im_not_ajscoder" rel="noopener noreferrer"&gt;@im_not_ajscoder&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>devtip</category>
      <category>testing</category>
      <category>node</category>
      <category>javascript</category>
    </item>
    <item>
      <title>How to Type the '_id' Field in TypeScript with Mongoose</title>
      <dc:creator>Axel Espinosa</dc:creator>
      <pubDate>Tue, 29 Apr 2025 03:13:54 +0000</pubDate>
      <link>https://dev.to/fromchiapasdev/how-to-type-the-id-field-in-typescript-with-mongoose-5dib</link>
      <guid>https://dev.to/fromchiapasdev/how-to-type-the-id-field-in-typescript-with-mongoose-5dib</guid>
      <description>&lt;p&gt;Hi everyone, let me start by thanking you for reading this post.&lt;/p&gt;

&lt;p&gt;I started this to practice my writing skills in English and to overcome my procrastination. Writing posts like this helps me gain a better understanding of things I'm learning. Let's dive into it.&lt;/p&gt;

&lt;p&gt;I encountered an issue while writing code in typescript using the popular Mongoose library when I tried to convert the field _id to a string.&lt;/p&gt;

&lt;p&gt;I have some example code here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Schema&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;timestamps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;products&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ProductModel&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;mongoose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ObjectId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Prop&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Prop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Prop&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Prop&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;stock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ProductModel&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// example of instance&lt;/span&gt;

&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// trying to convert my _id to a string&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I'm using Nestjs and its Mongoose integration. Instead of writing plain schemas like we traditionally  do, this library allow us to define models and their properties using Decorators (&lt;a class="mentioned-user" href="https://dev.to/prop"&gt;@prop&lt;/a&gt;) in a class, all within the same file. This class also serves as our model.&lt;/p&gt;

&lt;p&gt;There are 2 lines I want us to focus on:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ProductModel&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Specifically to the second line where we call &lt;code&gt;.toString()&lt;/code&gt;. It turns out that the way we declared the &lt;code&gt;_id&lt;/code&gt; property in our class causes incorrect typing. &lt;/p&gt;

&lt;p&gt;The library defines two types for &lt;code&gt;ObjectId&lt;/code&gt;: the first is implemented under &lt;code&gt;mongoose.Schema.Types.ObjectId&lt;/code&gt; , and the other is &lt;code&gt;mongoose.Types.ObjectId&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The difference between these types is that they aren't interchangeable, the latter is the declaration of an object which has serializable methods like &lt;code&gt;toString()&lt;/code&gt;, while the former doesn't.&lt;/p&gt;

&lt;p&gt;So I'll show you the error from the typescript linter if you use the former.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb1e69zi4ohlem7dy6xhg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb1e69zi4ohlem7dy6xhg.png" alt="Image of Visual Studio Code showing an error when trying to convert an ObjectId to a string" width="800" height="148"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Instead of writing something like this to silence the linter: (product._id as ObjectId).toString()&lt;/p&gt;

&lt;p&gt;Try using the correct type for your class, which is &lt;code&gt;mongoose.Types.ObjectId&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Schema&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;timestamps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;products&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ProductModel&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;mongoose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ObjectId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It doesn't matter if you are not using NestJS and Decorators. The type you need to import is the same. The example below use an interface and plain Mongoose.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Product&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;mongoose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ObjectId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myProductModel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mongoose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Schema&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Product&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="c1"&gt;// props })&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Bye
&lt;/h2&gt;

&lt;p&gt;Well, that's a short post, just in case someone else needs this, and for me because after one week without using Mongoose, I forget it XD. I think it would be interesting to investigate more about these 2 types and why they are written in that way, under different objects. &lt;/p&gt;

&lt;p&gt;In summary, we need to make sure we're typing our properties with the correct type before trying to bypass the Typescript compiler using type coercion or some other trick.  &lt;/p&gt;

&lt;p&gt;Thank you for reading ❤️&lt;/p&gt;

</description>
      <category>node</category>
      <category>mongodb</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Password managers for developers</title>
      <dc:creator>Axel Espinosa</dc:creator>
      <pubDate>Fri, 25 Aug 2023 01:44:13 +0000</pubDate>
      <link>https://dev.to/fromchiapasdev/password-managers-for-developers-52jo</link>
      <guid>https://dev.to/fromchiapasdev/password-managers-for-developers-52jo</guid>
      <description>&lt;p&gt;Hello, #readers! I hope you're having a fantastic day and staying properly hydrated. Just a quick reminder, though: coffee doesn't count towards staying hydrated, so keep that in mind! 🧐&lt;/p&gt;

&lt;p&gt;In today's post, I want to address a common issue that I think we've all experienced at some point: forgetting passwords and usernames for various websites, even our mobile banking apps!&lt;/p&gt;

&lt;h2&gt;
  
  
  The Facts
&lt;/h2&gt;

&lt;p&gt;Did you know this is more common than you might think? According to a study conducted by ExpressVPN, 52% of respondents in the United States reset their passwords at least once a month. Moreover, 21% admitted to resetting passwords more than once a week, and a surprising 14% even do it once a day! These stats reveal a significant number of people frequently forget their passwords.&lt;/p&gt;

&lt;p&gt;With this context, it's clear many of us have been through this situation, wasting valuable time trying to reset our passwords.&lt;br&gt;
But don't worry, in the next segment of this post, I'll share an effective solution to avoid these problems and make your digital life much simpler. Keep reading!&lt;/p&gt;

&lt;h2&gt;
  
  
  The Issues
&lt;/h2&gt;

&lt;p&gt;We've established the challenges of forgetting passwords, but have you realized the real consequences of these situations? Allow me to explain.&lt;/p&gt;

&lt;p&gt;One major problem is resorting to opening our notepads and jotting down passwords. While it may seem practical at the moment, it puts our privacy and security at risk. Imagine if someone gains access to that notepad—your confidential data would be exposed!&lt;/p&gt;

&lt;p&gt;But that's not all. Another common mistake is using the same password for all the apps and websites we use. This leads to a much bigger problem: the infamous data leaks. Unfortunately, we can't control the security of all the platforms we register on, and if any of them suffer a security breach, attackers can access our passwords and emails.&lt;/p&gt;

&lt;p&gt;Imagine this scenario: a data leak occurs on one of the sites where you use that common password (onedirection1234!). Cybercriminals gain access to your personal info, and now you have a vulnerability across all other sites where you used the same password. It's a risk we shouldn't underestimate.&lt;br&gt;
That's why it's crucial to take steps to protect our information.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution
&lt;/h2&gt;

&lt;p&gt;Did you know there are password managers that can greatly help with security and remembering passwords? They're essential for all your accounts! These managers generate automatic passwords and offer the option of using one-time codes, which is crucial nowadays.&lt;/p&gt;

&lt;p&gt;Personally, I've tried several password managers like Bitwarden, Dashlane, and 1Password. Of them, 1Password has brought a remarkable change in how I handle my accounts. I no longer need to remember any passwords, as the manager takes care of that. Plus, it generates highly secure passwords, even over 32 characters if needed. Goodbye to using my birthdate as a password!&lt;/p&gt;

&lt;p&gt;As a backend developer, a feature I find incredibly useful is the ability to securely store all my .env files and access them from my account. I no longer worry about copying and pasting files to an insecure location when switching computers. These files often contain database access info or external provider details. I simply store them in a secure note, and that's more than enough.&lt;/p&gt;

&lt;p&gt;Furthermore, 1Password recently added a feature to manage SSH keys, although I haven't used it yet, I'm sure it'll be incredibly helpful. I've noticed this company truly has us, developers, in mind to make their tool genuinely useful. I wholeheartedly recommend it, even if there are more budget-friendly alternatives out there, this one's my favorite.&lt;/p&gt;

&lt;p&gt;So, there you have it—use a password manager wherever possible! Don't forget to enable two-factor authentication on your accounts. If you use multiple AWS accounts, I promise it'll make your life so much easier.&lt;/p&gt;

&lt;p&gt;Hope you enjoyed this new post about something that helps me in my day-to-day. Thanks for reading! I'll leave you with a cheems.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpn97mexxjgtsqb956ery.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpn97mexxjgtsqb956ery.gif" alt="Cheems" width="360" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  References:
&lt;/h2&gt;

&lt;p&gt;P, M. (2022). Survey: How Much Time Do You Waste Resetting Passwords? Home of Internet Privacy. &lt;a href="https://www.expressvpn.com/es/blog/encuesta-cuanto-tiempo-desperdicia-restableciendo-contrasenas/" rel="noopener noreferrer"&gt;https://www.expressvpn.com/es/blog/encuesta-cuanto-tiempo-desperdicia-restableciendo-contrasenas/&lt;/a&gt;&lt;br&gt;
Peru, E. C. (2021, May 6). World Password Day: 56% of users never change their access codes. El Comercio Peru. &lt;a href="https://elcomercio.pe/tecnologia/actualidad/ciberseguridad-dia-mundial-de-las-contrasenas-el-56-de-usuarios-no-cambia-nunca-sus-claves-de-acceso-hackers-hackeo-noticia/" rel="noopener noreferrer"&gt;https://elcomercio.pe/tecnologia/actualidad/ciberseguridad-dia-mundial-de-las-contrasenas-el-56-de-usuarios-no-cambia-nunca-sus-claves-de-acceso-hackers-hackeo-noticia/&lt;/a&gt;&lt;br&gt;
Biggest Data Breaches in US History [Updated 2023] | UpGuard. (n.d.). &lt;a href="https://www.upguard.com/blog/biggest-data-breaches-us" rel="noopener noreferrer"&gt;https://www.upguard.com/blog/biggest-data-breaches-us&lt;/a&gt;&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>productivity</category>
      <category>security</category>
    </item>
    <item>
      <title>Decoding Developer Challenges: Balancing Code, Clients, and User Experience</title>
      <dc:creator>Axel Espinosa</dc:creator>
      <pubDate>Tue, 15 Aug 2023 19:22:14 +0000</pubDate>
      <link>https://dev.to/fromchiapasdev/decoding-developer-challenges-balancing-code-clients-and-user-experience-32n0</link>
      <guid>https://dev.to/fromchiapasdev/decoding-developer-challenges-balancing-code-clients-and-user-experience-32n0</guid>
      <description>&lt;p&gt;Hello #readers! I hope you're doing well. I've just come out of some extremely busy weeks at work where we've been developing a core service for our mobile app. By the way, you can download it on the &lt;a href="https://fintonic.mx/" rel="noopener noreferrer"&gt;App Store or Google Play.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Today, I wanted to share some wild ideas that struck me as I was about to start a small freelance gig for a client. I think they might be helpful to you. These are little insights I've gathered that assist me in completing tasks or even tackling new projects without facing that ever-present dilemma: whether to use one technology over another, or wondering if database X is better than another. You know, those everyday conundrums.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Software Beyond Code.&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;It's not just about writing the most optimized lines or strictly adhering to standards. It's about how we can make a real difference in people's lives. Every time we write code, we're crafting solutions. Never forget that.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The User's Perspective.&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;While we're deep into design patterns, testing, and architectures, at the end of the day, our users just want something that works. So, if you ever find yourself torn between going for the latest tech or ensuring something simply works for the user, you know what to choose.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Finding Balance with Your Clients.&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;We know it can be tricky sometimes. But, you know what? Neither you nor they are always right. The key is to find a middle ground where both parties are content.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The Peaks and Valleys of Being a Developer.&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;There are days when everything flows, and others when you might feel like throwing your computer out of the window. It's all part of the journey, and it's what makes our profession both unique and exhilarating.&lt;/p&gt;

&lt;p&gt;Well, I hope you enjoyed this short post. Do you have any other ideas that help you thrive? Catch me on Twitter(X) or in the comments 😃 &lt;a href="https://twitter.com/devfromchiapas" rel="noopener noreferrer"&gt;@fromchiapasdev.&lt;/a&gt;&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>discuss</category>
      <category>learning</category>
    </item>
    <item>
      <title>Reflexionando sobre el mundo del código</title>
      <dc:creator>Axel Espinosa</dc:creator>
      <pubDate>Sat, 12 Aug 2023 00:25:38 +0000</pubDate>
      <link>https://dev.to/fromchiapasdev/reflexionando-sobre-el-mundo-del-codigo-23fn</link>
      <guid>https://dev.to/fromchiapasdev/reflexionando-sobre-el-mundo-del-codigo-23fn</guid>
      <description>&lt;p&gt;Hola #readers, espero que estén muy bien, yo estoy saliendo de unas semanas muy atareadas del trabajo, en las que hemos estado creando un servicio core para nuestra aplicación móvil, &lt;a href="https://www.fintonic.mx/es-MX/inicio/" rel="noopener noreferrer"&gt;por cierto pueden bajarla en la App Store o Google Play.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;En esta ocasión vengo a escribir acerca de unas ideas locas que se me ocurrieron mientras estaba por empezar un pequeño freelance para un cliente y creo que te pueden ser útiles. Son pequeños puntos que recopilé que me ayudan a poder completar una tarea o incluso enfrentarme con un proyecto nuevo y no estar teniendo ese pequeño dilema de si usar una tecnología sobre otra, o que si la base de datos X es mejor que otra, ya saben dilemas de la vida.&lt;/p&gt;

&lt;h2&gt;
  
  
  Software más allá del código.
&lt;/h2&gt;

&lt;p&gt;No es solo escribir las líneas más optimizadas o seguir los estándares al pie de la letra. Es sobre cómo podemos hacer una diferencia real en la vida de las personas. Cada vez que escribimos código, estamos creando soluciones. Nunca olvides eso.&lt;/p&gt;

&lt;h2&gt;
  
  
  La perspectiva del usuario.
&lt;/h2&gt;

&lt;p&gt;Mientras estamos sumergidos en patrones de diseño, pruebas y arquitecturas, al final del día, nuestros usuarios solo quieren algo que funcione. Así que, si alguna vez te encuentras en el dilema de optar por la última versión de una tecnología o hacer que algo simplemente funcione para el usuario, ya sabes qué elegir.&lt;/p&gt;

&lt;h2&gt;
  
  
  Encuentra el balance con tus clientes.
&lt;/h2&gt;

&lt;p&gt;Sabemos que a veces puede ser complicado. Pero, ¿sabes? Ni tú ni ellos tienen siempre la razón. La clave está en encontrar un término medio donde ambos se sientan satisfechos.&lt;/p&gt;

&lt;h2&gt;
  
  
  Las montañas y valles de ser programador.
&lt;/h2&gt;

&lt;p&gt;Hay días en los que todo fluye, y hay otros en los que quisieras tirar tu computadora por la ventana. Es parte del viaje, y es lo que hace que nuestra profesión sea única y apasionante.&lt;/p&gt;

&lt;p&gt;Pues bueno, espero te haya gustado este pequeño post, ¿tienes otras ideas que te ayudan a ser mejor? Te veo en Twitter(X) o en los comentarios 😃 &lt;a href="https://twitter.com/devfromchiapas" rel="noopener noreferrer"&gt;@fromchiapasdev&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>productivity</category>
      <category>career</category>
    </item>
    <item>
      <title>Deja de olvidar las contraseñas</title>
      <dc:creator>Axel Espinosa</dc:creator>
      <pubDate>Fri, 14 Jul 2023 19:12:38 +0000</pubDate>
      <link>https://dev.to/fromchiapasdev/deja-de-olvidar-las-contrasenas-k4m</link>
      <guid>https://dev.to/fromchiapasdev/deja-de-olvidar-las-contrasenas-k4m</guid>
      <description>&lt;p&gt;¡Hola, #readers! Espero que estén teniendo un día genial y se estén hidratando adecuadamente. Recuerden que el café no cuenta para mantenernos hidratados, ojito 🧐&lt;/p&gt;

&lt;p&gt;En el post de hoy, quiero abordar un problema común que creo que todos hemos experimentado en algún momento: ¡perder contraseñas y olvidarnos de los usuarios con los que nos registramos en diferentes sitios web, incluso en nuestra banca móvil!&lt;/p&gt;

&lt;h2&gt;
  
  
  Datos
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;¿Sabías que esto es más común de lo que te imaginas? Según un estudio realizado por la compañía ExpressVPN, el 52% de los encuestados en Estados Unidos restablecen sus contraseñas al menos una vez al mes. Además, un 21% admitió restablecerlas más de una vez a la semana, ¡y un 14% incluso lo hace al menos una vez al día! Estos datos nos revelan que un porcentaje significativo de personas olvida sus contraseñas con frecuencia.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Con este contexto, es evidente que muchos de nosotros hemos pasado por esta situación y perdemos un tiempo valioso tratando de restablecer nuestras contraseñas.&lt;br&gt;
Pero no te preocupes, en el próximo segmento de este post compartiré contigo una solución efectiva para evitar estos problemas y hacer que tu vida digital sea mucho más sencilla. ¡Sigue leyendo!&lt;/p&gt;

&lt;h2&gt;
  
  
  Problemas
&lt;/h2&gt;

&lt;p&gt;Ya hemos entendido los problemas que enfrentamos al perder nuestras contraseñas. Pero, ¿te has dado cuenta de cuáles son las consecuencias reales de estas situaciones? Permíteme explicarte.&lt;/p&gt;

&lt;p&gt;Uno de los principales problemas es que solemos recurrir a abrir nuestro bloc de notas y anotar las contraseñas. Aunque parezca una solución práctica en el momento, puede poner en riesgo nuestra privacidad y seguridad. Imagina si alguien accede a ese bloc de notas, ¡todos tus datos confidenciales estarían al descubierto!&lt;/p&gt;

&lt;p&gt;Pero eso no es todo. Otro error común es utilizar la misma contraseña para todas las aplicaciones y sitios web que utilizamos. Esto nos lleva a un problema mucho más preocupante: los famosos data leaks, es decir, la filtración de información. Desafortunadamente, no podemos controlar la seguridad de todas las plataformas en las que nos registramos, y si alguna de ellas sufre un fallo de seguridad, los atacantes pueden obtener acceso a nuestras contraseñas y correos electrónicos.&lt;/p&gt;

&lt;p&gt;Imagina el escenario: un data leak ocurre en uno de los sitios en los que usas esa contraseña común (onedirection1234!). Los ciberdelincuentes obtienen acceso a tu información personal y ahora tienes una vulnerabilidad en todos los demás sitios en los que usaste esa misma contraseña. Es un riesgo que no debemos subestimar.&lt;br&gt;
Por eso es fundamental tomar medidas para proteger nuestra información.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solución
&lt;/h2&gt;

&lt;p&gt;¿Sabías que existen gestores de contraseñas que pueden ser de gran ayuda para mantener la seguridad y recordar tus contraseñas? ¡Son imprescindibles en todas tus cuentas! Estos gestores generan contraseñas automáticas y te ofrecen la posibilidad de utilizar códigos de un solo uso, algo fundamental en la actualidad.&lt;/p&gt;

&lt;p&gt;Personalmente, he probado varios gestores de contraseñas como Bitwarden, Dashlane y 1Password. De todos ellos, 1Password me ha brindado un cambio increíble en la forma en que manejo mis cuentas. Ya no tengo que recordar ninguna contraseña, ya que el gestor se encarga de ello. Además, genera contraseñas altamente seguras, incluso de más de 32 caracteres si es necesario. ¡Adiós al temor de utilizar mi fecha de cumpleaños como contraseña!&lt;/p&gt;

&lt;p&gt;Como desarrollador backend, una función que me resulta extremadamente útil es poder almacenar todos mis archivos con extensión .env de forma segura y acceder a ellos desde mi cuenta. Ya no tengo que preocuparme por copiar y pegar los archivos en un lugar inseguro cuando cambio de computadora. Estos archivos suelen contener información de acceso a bases de datos o proveedores externos. Simplemente los almaceno en una nota segura y eso es más que suficiente.&lt;/p&gt;

&lt;p&gt;Además, 1Password ha añadido recientemente una nueva función para gestionar llaves SSH, aunque aún no la he utilizado, estoy seguro de que será de gran utilidad. He observado que esta empresa realmente ha pensado en nosotros, los desarrolladores, para hacer de su herramienta algo realmente útil. La recomiendo al 100%, aunque existan alternativas más económicas en el mercado, esta es mi favorita.&lt;/p&gt;

&lt;p&gt;Entonces, ya lo sabes, ¡utiliza un gestor de contraseñas para todo lo posible! No olvides activar la autenticación de dos factores en tus cuentas. Si utilizas varias cuentas de AWS, te aseguro que te ayudará enormemente.&lt;/p&gt;

&lt;p&gt;Espero que les haya gustado este nuevo post sobre algo que me ayuda en mi día a día. ¡Gracias por leerme! Les dejo un cheems.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpn97mexxjgtsqb956ery.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpn97mexxjgtsqb956ery.gif" alt="Cheems" width="360" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Referencias:
&lt;/h2&gt;

&lt;p&gt;P, M. (2022). Encuesta: ¿Cuánto tiempo desperdicia restableciendo contraseñas? Home of Internet Privacy. &lt;a href="https://www.expressvpn.com/es/blog/encuesta-cuanto-tiempo-desperdicia-restableciendo-contrasenas/" rel="noopener noreferrer"&gt;https://www.expressvpn.com/es/blog/encuesta-cuanto-tiempo-desperdicia-restableciendo-contrasenas/&lt;/a&gt;&lt;br&gt;
Perú, E. C. (2021, May 6). Día Mundial de las Contraseñas: El 56% de usuarios no cambia nunca sus claves de acceso. El Comercio Perú. &lt;a href="https://elcomercio.pe/tecnologia/actualidad/ciberseguridad-dia-mundial-de-las-contrasenas-el-56-de-usuarios-no-cambia-nunca-sus-claves-de-acceso-hackers-hackeo-noticia/" rel="noopener noreferrer"&gt;https://elcomercio.pe/tecnologia/actualidad/ciberseguridad-dia-mundial-de-las-contrasenas-el-56-de-usuarios-no-cambia-nunca-sus-claves-de-acceso-hackers-hackeo-noticia/&lt;/a&gt;&lt;br&gt;
Biggest Data Breaches in US History [Updated 2023] | UpGuard. (n.d.). &lt;a href="https://www.upguard.com/blog/biggest-data-breaches-us" rel="noopener noreferrer"&gt;https://www.upguard.com/blog/biggest-data-breaches-us&lt;/a&gt;&lt;/p&gt;

</description>
      <category>tips</category>
      <category>security</category>
      <category>discuss</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
