Por Qué 0.1 + 0.2 No Es 0.3: la Coma Flotante Explicada

Ejecuta 0.1 + 0.2 en una shell de Python y no obtienes 0.3. Obtienes 0.30000000000000004. Pruébalo en JavaScript, Java, Go, C o Rust y te sale la misma cola de dieciséis cifras. Cada uno de esos lenguajes hace exactamente lo que marca el estándar del hardware. Un número que necesita infinitos dígitos binarios se comprime en 64 bits, y algo tiene que ceder. Por qué 0.1 no se puede guardar de forma exacta en binario Los ordenadores guardan los números en coma flotante en base 2. En base 2, la fracción 1/10 tiene un desarrollo periódico, igual que 1/3 se repite sin fin en base 10 (0.3333...). Escrito entero, 0.1 en binario empieza así: ...

6 de octubre de 2026 · 6 min · 1222 palabras · SpaghettiCoder

LocalStorage, SessionStorage y Cookies: Cuál Usar

Un endpoint de login te devuelve un JWT, y tienes tres lugares donde guardarlo: una cookie, localStorage o sessionStorage. Si eliges mal, un bug de XSS se lleva el token, o el token nunca llega a tu API. Las tres opciones guardan strings en el navegador. Se diferencian en quién puede leerlas, cuánto duran y si el servidor llega a verlas. En qué se diferencian localStorage, sessionStorage y las cookies localStorage y sessionStorage son la misma API, la interfaz Storage: setItem, getItem, removeItem, clear, claves string y valores string. La diferencia está en la duración. localStorage sobrevive a cerrar el navegador y reiniciar la máquina, y se queda hasta que algo lo borra. Safari es la excepción: con la prevención de rastreo activada, borra el almacenamiento escrito por script de un sitio con el que el usuario no ha interactuado en siete días. sessionStorage pertenece a una pestaña y muere cuando esa pestaña se cierra. Si escribes la misma URL en una segunda pestaña obtienes un sessionStorage nuevo y vacío; solo “Duplicar pestaña” lo copia. ...

5 de octubre de 2026 · 8 min · 1538 palabras · SpaghettiCoder

Notación Big O Explicada con Ejemplos de Código

Una búsqueda en un diccionario de Python tarda unos 100 nanosegundos, tanto si el diccionario tiene 1.000 claves como 1.000.000. Un bucle anidado que busca duplicados en una lista tarda medio milisegundo con 200 elementos y 136 milisegundos con 3.200. Dieciséis veces la entrada, casi 280 veces la espera. Misma máquina, mismo Python. La notación Big O es el nombre de esa diferencia. Qué mide la notación Big O Big O describe cómo crece el tiempo de ejecución (o el uso de memoria) de un fragmento de código a medida que la entrada se hace más grande. No es una lectura de cronómetro y no le importa si tu portátil es rápido o lento. Le importa la forma de la curva de crecimiento: al duplicar la entrada, ¿el tiempo se duplica, se cuadruplica o apenas se mueve? ...

4 de octubre de 2026 · 9 min · 1762 palabras · SpaghettiCoder

Git Reset vs Revert vs Restore: Cómo Deshacer Cambios

Ejecuta git reset --hard sobre un commit que tu equipo ya bajó y acabas de dejar tu historial en desacuerdo con el suyo. Ejecuta git revert sobre un typo que no has subido y añades un commit innecesario al log. Git tiene cuatro comandos para deshacer cambios, restore, reset, commit --amend y revert, y no son intercambiables. Elige el equivocado y el resultado es que no pasa nada, o pasa mucho más de lo que querías. ...

3 de octubre de 2026 · 7 min · 1368 palabras · SpaghettiCoder

Tipos de JOIN en SQL Explicados con Ejemplos

Un JOIN mal escrito no lanza un error. Se ejecuta, devuelve un resultado, y las filas están mal: faltan clientes, los totales están inflados, hay registros huérfanos ocultos. Casi siempre la consulta pidió exactamente lo que obtuvo, y quien la escribió eligió el tipo de join equivocado, o filtró en el lugar equivocado. Un join combina filas de dos tablas según una condición que tú escribes. Qué filas sobreviven depende del tipo de join, y los seis tipos que siguen dan seis respuestas distintas a partir de las mismas dos tablas. ...

2 de octubre de 2026 · 10 min · 1956 palabras · SpaghettiCoder

Qué Es la Dependency Injection (con Ejemplos)

Aquí tienes una clase que no puedes probar con un unit test sin una base de datos real y un servidor SMTP funcionando: 1 2 3 4 5 6 7 8 9 10 11 public class OrderService { private readonly SqlOrderRepository _repository = new SqlOrderRepository("Server=prod-db;Database=Orders;..."); private readonly SmtpEmailSender _emailSender = new SmtpEmailSender("smtp.company.com"); public void PlaceOrder(Order order) { _repository.Save(order); _emailSender.Send(order.CustomerEmail, "Order confirmed"); } } OrderService construye su propio SqlOrderRepository y SmtpEmailSender con new, con la connection string incluida. Cada test que toca PlaceOrder necesita una base de datos Orders real y un servidor de correo real, o falla antes de que se ejecute tu assertion. La lógica que quieres probar son dos líneas: guardar el pedido, enviar la confirmación. Está soldada a dos clases concretas que no puedes cambiar. ...

1 de octubre de 2026 · 8 min · 1615 palabras · SpaghettiCoder

Entornos Virtuales de Python: venv, pip y uv

Instala dos proyectos de Python en la misma máquina y el segundo puede romper el primero. Uno necesita requests==2.28, el otro necesita requests==2.32, y pip tiene exactamente un directorio site-packages global en el que escribir. Gana la última instalación, en silencio. Te enteras cuando el otro proyecto empieza a lanzar errores que no tienen nada que ver con el código que acabas de cambiar. Un entorno virtual le da a cada proyecto su propio site-packages. No se toca nada global, y dos proyectos pueden depender de versiones incompatibles de la misma librería sin que ninguno se entere. ...

30 de septiembre de 2026 · 7 min · 1456 palabras · SpaghettiCoder

Pruebas Unitarias vs de Integración vs End-to-End

Una función puede tener el 100% de cobertura de pruebas unitarias y la página que la llama puede seguir devolviendo un 500 en producción. No es una contradicción. Las pruebas unitarias, de integración y end-to-end comprueban cosas distintas, y una suite cargada en una y floja en otra tiene un hueco específico y predecible. Qué comprueban las pruebas unitarias, de integración y end-to-end Toma una funcionalidad de registro: una función valida la entrada, escribe una fila en una base de datos y envía un correo de bienvenida. Tres pruebas pueden cubrirla, y cada una responde una pregunta distinta. ...

29 de septiembre de 2026 · 11 min · 2291 palabras · SpaghettiCoder

Async/Await y el Event Loop de JavaScript Explicados

Ejecuta esto en Node o en la consola del navegador: 1 2 3 4 console.log("1"); setTimeout(() => console.log("2"), 0); Promise.resolve().then(() => console.log("3")); console.log("4"); El resultado es 1 4 3 2. Un setTimeout con un delay de 0ms igual se ejecuta después del callback de la promise, y ambos esperan a que termine cada línea de código síncrono que tienen debajo. async/await está construido sobre este orden, no es un mecanismo nuevo. La mayoría del comportamiento sorprendente en JavaScript async viene de escribir await como si pausara todo el programa, cuando en realidad solo pausa la función en la que está. ...

28 de septiembre de 2026 · 8 min · 1703 palabras · SpaghettiCoder

Índices de Base de Datos: Cómo Funcionan y Cuándo Usarlos

En una tabla de un millón de filas, la misma SELECT puede tardar cincuenta milisegundos o bastante menos de uno. La única diferencia es si la base de datos lee cada fila para encontrar las que pediste, o salta directamente a ellas. Un índice es lo que le permite saltar, y lo pagas en cada escritura. En concreto, un índice es una segunda copia ordenada de una o más columnas, guardada junto a la tabla y actualizada automáticamente cada vez que la tabla cambia. La base de datos la usa para llegar a las filas que coinciden sin tocar el resto. ...

27 de septiembre de 2026 · 9 min · 1860 palabras · SpaghettiCoder