Pídele a un modelo que responda en JSON y la mayoría de las veces json.loads() funciona sin problemas. Los fallos son los que te cuestan una sesión de debugging: un comentario de una línea dentro del objeto, un code fence de markdown envolviéndolo, una clave escrita userEmail cuando tu código espera user_email. Un prompt más estricto (“responde SOLO con el objeto JSON, sin ningún otro texto”) hace que estos casos sean más raros. No los hace imposibles, porque el modelo puede ignorar la petición igual. La salida estructurada elimina la petición de la ecuación: le entregas a la API un JSON Schema, y este restringe el muestreo de tokens del propio modelo para que la respuesta tenga que ajustarse a él. ...
Especificidad CSS Explicada: Cómo Decide la Cascada
Escribes .sidebar .card { color: blue; }, cargas la página y la tarjeta sigue en rojo por una regla que añadiste una hora antes: .card { color: red; }. Tu nueva regla va después en el archivo. Sigue perdiendo. El navegador compara los dos selectores con un sistema de puntos fijo, y .sidebar .card puntúa más alto que .card sin importar cuál escribiste al final. Ese sistema de puntos es la especificidad. En cuanto sabes calcularla a simple vista, “por qué no se aplica mi CSS” se vuelve aritmética. No tiene nada que ver con el layout: Grid o Flexbox decide dónde se coloca un elemento, y la especificidad decide qué regla fija su color o tamaño cuando dos reglas entran en conflicto. ...
¿Qué Es una Tabla Hash? Hashing y Colisiones Explicados
Buscar una clave en un dict de Python con diez entradas tarda lo mismo que buscarla en uno con diez millones. No es casualidad de un lenguaje rápido. El dict de Python, el HashMap de Java y el Map de JavaScript son tablas hash, y todo su diseño existe para que búsqueda, inserción y borrado funcionen en O(1) de media. La notación Big O llama a esa búsqueda “tiempo constante”. Este es el mecanismo que se lo gana. ...
Ownership y Borrowing en Rust Explicados
Un programa en C que libera un buffer y sigue leyéndolo compila sin problema. Luego corrompe la memoria, a veces de inmediato, a veces tres peticiones más tarde, en una parte del código que nunca tocó ese buffer. Rust rechaza ese programa ya en el cargo build, y no hay ningún garbage collector de por medio. El compilador rastrea quién posee cada valor y quién puede acceder a él. Ese rastreo es ownership y borrowing. ...
Mock, Stub, Fake y Spy: los Test Doubles Explicados
Un test para place_order necesita una pasarela de pago, un cliente de SMS y una calculadora de impuestos. Conecta las versiones reales y cada ejecución del test cobra una tarjeta y manda un SMS a un número real. Un test unitario tiene que correr en milisegundos y sin red, así que las tres dependencias hay que sustituirlas por otra cosa. Ese “otra cosa” llega en cinco variantes. Cada una resuelve un problema distinto, y tratarlas como intercambiables explica por qué las discusiones de “pon un mock y ya” en code review no llegan a ningún lado. ...
ESLint vs Prettier: Diferencias y Cómo Combinarlos
Guardas un archivo, Prettier lo reformatea, y ESLint marca de inmediato un error en la línea que Prettier acaba de tocar. Las dos herramientas están configuradas, las dos están activas, y en vez de ayudarte se pelean entre sí. Las dos herramientas hacen trabajos distintos. El problema es que ambas tienen una opinión sobre una sola cosa: cómo debe verse el código en la pantalla. Qué comprueba realmente ESLint ESLint analiza tu código en un árbol de sintaxis abstracta y ejecuta reglas sobre su estructura. La mayor parte de su valor viene de reglas que detectan bugs reales: una variable que nunca se define, un return inalcanzable después de otro return, un import que quedó sin usar tras una refactorización, una clave duplicada en un objeto que sobrescribe la primera en silencio. Son comprobaciones semánticas: ESLint lee lo que el código hace. ...
Transacciones en Bases de Datos: ACID y Aislamiento
Por qué una transferencia bancaria necesita más que dos UPDATE Mueve 50€ de una cuenta a otra y la versión naive son dos instrucciones: resta de la cuenta A, suma a la cuenta B. Ejecútalas por separado y, si el proceso falla o la conexión se cae entre las dos, el dinero desaparece de A y nunca llega a B. La base de datos hizo exactamente lo que se le pidió, dos veces. El negocio perdió 50€ igualmente. ...
Cómo Crear un LLM Eval: Probar Prompts Como Código
Por qué “parece correcto” no es una prueba para un prompt Ajustas el texto de un prompt que clasifica tickets, lo pruebas con los tres ejemplos que tienes abiertos en tu notebook de pruebas y lo despliegas. Una semana después, las quejas de facturación que antes caían en la cola correcta empiezan a caer en “pregunta”. No los tres casos que revisaste: los otros cuatrocientos que no revisaste. Nada falla. No hay ningún stack trace. El prompt, leído en voz alta, sigue sonando bien. ...
React useEffect Explicado: Dependencias y Cleanup
Un componente de chat reconecta su WebSocket cada vez que escribes una letra en un buscador que no tiene nada que ver con el chat. Otro componente se re-renderiza en bucle hasta que la pestaña se congela. Un tercero registra su useEffect dos veces al montarse, pero solo en desarrollo. Ninguno de estos es un bug de React. Los dos primeros son el array de dependencias haciendo exactamente lo que le pediste, y el tercero es Strict Mode comprobando que tu efecto sabe limpiar después de sí mismo. ...
Expresiones Regulares Explicadas: Cómo Funciona el Regex
<.+> contra <b>bold</b> and <i>italic</i> no encuentra <b>. Encuentra toda la cadena, desde el primer < hasta el último >. No hay ningún error. Eso es justo lo que debe hacer un cuantificador greedy, y también es el bug más común de “el regex está matcheando de más”. Una vez que sabes qué hace el motor mientras lee tu patrón, este bug y la mayoría de sus parientes dejan de ser un misterio. ...