Cómo funcionaba el software que alunizó: el sistema operativo del Apolo, explicado con su código fuente

El rostro de Margaret Hamilton, desenfocado, al fondo de la portada, junto al título «Cómo funcionaba el software que alunizó» y una DSKY dibujada con el código 1202

Del software del Apolo se repiten siempre las mismas dos frases: que cabía en menos memoria que una foto del móvil y que una alarma estuvo a punto de abortar el alunizaje. Las dos son ciertas y ninguna explica nada. Lo interesante es cómo estaba hecho por dentro, y lo bueno es que se puede mirar: el código fuente de la misión está publicado, línea a línea, con los comentarios que escribieron sus autores en 1969.

La máquina con la que había que apañarse

El ordenador de guiado del Apolo —el AGC— no era pequeño para la época: era pequeño a secas.

El AGCPara comparar
Memoria de trabajo2.048 palabras de núcleos de ferritaunos 4 KB
Programa36.864 palabras de memoria fijaunos 72 KB, y no se podía cambiar
Palabra15 bits más uno de paridadhoy, 64
Reloj2,048 MHzunas mil veces menos que un móvil
Peso y consumo32 kg y 55 Wuna bombilla

Y el programa no estaba grabado: estaba tejido. Cada uno y cada cero era un cable que pasaba por dentro o por fuera de un anillo de ferrita, a mano, y la memoria entera llevaba semanas de telar. Una vez tejida no se podía corregir ni una coma. Eso cambia por completo lo que significa «equivocarse».

Y el programa no podía pararse nunca. A la vez, y sin descanso, tenía que hacer todo esto: leer los acelerómetros, ir sumando esas lecturas para saber dónde estaba la nave, mover los motores que orientan la plataforma de navegación, atender al radar, llevar la cuenta del tiempo, refrescar los números de la pantalla y, por si fuera poco, hacer caso a un astronauta que teclea. Todo eso, con un solo procesador. No había un segundo núcleo al que mandarle la mitad.

La respuesta a ese problema es lo que hoy llamaríamos un sistema operativo de tiempo real, y es la aportación de fondo del equipo que dirigía Margaret Hamilton. Tiene cuatro ideas, y las cuatro se siguen usando.

Idea 1: una cola con prioridades, no una lista de tareas

Lo intuitivo, y lo que hacía casi todo el mundo entonces, es un ciclo mayor: haz A, luego B, luego C, vuelve a empezar. Funciona mientras todo dure lo previsto. El problema es que nada dura lo previsto, y cuando A se alarga, C llega tarde aunque C sea lo único que de verdad importa.

El Executive del AGC no hace eso. Cada unidad de trabajo —un job— se registra con un número de prioridad, y el sistema ejecuta siempre el de prioridad más alta que esté listo. Si mientras corre uno aparece otro más urgente, el primero se suspende a medias y se retoma después.

EXECUTIVE.agc, Luminary 1A (Apolo 11)# TO ENTER A JOB REQUEST REQUIRING NO VAC AREA:

NOVAC		INHINT
		AD	FAKEPRET	# LOC(MPAC +6) - LOC(QPRET)
		TS	NEWPRIO		# PRIORITY OF NEW JOB + NOVAC C(FIXLOC)

Y esta es la decisión de «¿me cambio de trabajo o sigo con este?», tal cual está escrita:

EXECUTIVE.agc		INDEX	NEWJOB		# THIS INDEX INSTRUCTION INSURES THAT THE
		CS	PRIORITY	# HIGHEST ACTIVE PRIORITY WILL BE COMPARED
		AD	NEWPRIO		# WITH THE NEW PRIORITY TO SEE IF NEWJOB
		EXTEND			# SHOULD BE SET TO SIGNAL A SWITCH.
		BZMF	ENDFIND

Si no has visto nunca ensamblador del AGC, no te pelees con las siglas: lo que hacen esas cinco líneas es una resta. Coge la prioridad del trabajo que está corriendo, le resta la del recién llegado y mira el signo. Si sale negativo, el nuevo manda y hay cambio; si no, el de ahora sigue. Eso es todo el «planificador»: una resta y un salto según el signo.

Las mayúsculas de los comentarios no las hemos puesto nosotros: el AGC se programaba con un juego de caracteres que no tenía minúsculas. Todos los listados de esta página están copiados tal cual del fuente de la misión, erratas incluidas: unas líneas más abajo, en ese mismo archivo, pone REQUIREING.

Ocho bandejas y cinco cuadernos

Si vas a interrumpir un trabajo a medias y retomarlo luego, tienes que apuntar en algún sitio por dónde iba: sus cuentas a medio hacer, en qué línea estaba, con qué trozo de memoria trabajaba. Piensa en una mesa con varias bandejas: cada trabajo que se aparta deja su papeleo en una bandeja y la mesa queda libre para el siguiente. Esa bandeja es lo que ellos llamaban core set.

Y aquí está el problema: cada bandeja ocupa memoria, y había 2.048 palabras en total para todo. Así que las bandejas se contaron y se repartieron de antemano, una por una:

ERASABLE_ASSIGNMENTS.agc# DYNAMICALLY ALLOCATED CORE SETS FOR JOBS	(84D)

MPAC		ERASE	+6		# MULTI-PURPOSE ACCUMULATOR.
MODE		ERASE			# +1 FOR TP, +0 FOR DP, OR -1 FOR VECTOR.
LOC		ERASE			# LOCATION ASSOCIATED WITH JOB.
BANKSET		ERASE			# USUALLY CONTAINS BBANK SETTING.
PUSHLOC		ERASE			# WORD OF PACKED INTERPRETIVE PARAMETERS.
PRIORITY	ERASE			# PRIORITY OF PRESENT JOB AND WORK AREA.

		ERASE	+83D		# EIGHT SETS OF 12 REGISTERS EACH

Ocho. Ocho bandejas. Ocho trabajos como mucho a la vez en toda la nave, y ni uno más.

Hay un segundo cupo. Los trabajos que hacen cuentas con vectores necesitan además un cuaderno de borrador bastante más grande, 43 palabras, para ir dejando los resultados intermedios. A ese cuaderno lo llamaban área VAC, y de esos había cinco. De ahí que en el fuente haya dos puertas de entrada distintas: NOVAC para el trabajo que no necesita cuaderno y FINDVAC para el que sí.

ERASABLE_ASSIGNMENTS.agc# VAC AREAS. -- BE CAREFUL OF PLACEMENT --	(220D)

VAC1USE		ERASE
VAC1		ERASE	+42D
VAC2USE		ERASE
VAC2		ERASE	+42D

¿Y si alguien pide bandeja o cuaderno y no queda ninguno libre? Pues pasa lo que todo el mundo ha oído contar mil veces sin saber qué era. Las dos alarmas famosas del alunizaje son literalmente eso: «no me quedan cuadernos» y «no me quedan bandejas». Están escritas ahí, en el mismo archivo, una debajo de la otra:

EXECUTIVE.agc — la alarma 1201		CCS	VAC5USE
		TCF	VACFOUND
		LXCH	EXECTEM1
		CA	Q
		TC	BAILOUT1
		OCT	1201		# NO VAC AREAS.
EXECUTIVE.agc — la alarma 1202NEXTCORE	CAF	COREINC
		ADS	LOCCTR
		CCS	EXECTEM2
		TCF	NOVAC3
		LXCH	EXECTEM1
		CA	Q
		TC	BAILOUT1	# NO CORE SETS AVAILABLE.
		OCT	1202
Esto conviene leerlo despacio. El 1202 no es un fallo del programa ni un error de nadie: es el mensaje que el sistema emite a propósito cuando pide una bandeja y no queda ninguna. Es una condición prevista, con su código, su rutina y su documentación. La diferencia entre un sistema que se cuelga y uno que avisa está, casi siempre, en si alguien se molestó en escribir estas seis líneas.

Idea 2: las tareas con reloj

El Executive responde a «esto es importante». Falta quien responda a «esto es a tal hora», que no es lo mismo: leer el acelerómetro dentro de 10 milisegundos, apagar el motor dentro de 4 segundos. De eso se encarga el segundo planificador, el Waitlist, y lo que gestiona no se llama trabajo sino tarea: un encargo corto que entra, hace lo suyo y sale sin que nadie lo interrumpa.

WAITLIST.agc# FUNCTIONAL DESCRIPTION --
#	PART OF A SECTION OF PROGRAMS -- WAITLIST, TASKOVER, T3RUPT, USED TO CALL A PROGRAM (CALLED A TASK),
#	WHICH IS TO BEGIN IN C(A) CENTISECONDS.
#
# WARNINGS --
#	1)	1 <= C(A) <= 16250D (1 CENTISECOND TO 162.5 SEC)
#	2)	9 TASKS MAXIMUM
#	3)	TASKS CALLED UNDER INTERRUPT INHIBITED
#	4)	TASKS END BY TC TASKOVER

Nueve tareas, hasta 162,5 segundos de plazo, resolución de una centésima de segundo. La división es la misma que hoy: tareas cortas y puntuales que no pueden interrumpirse, y trabajos largos que sí. Una tarea que necesita hacer algo lento no lo hace: encola un trabajo y se va.

Idea 3: reiniciar sin perder nada

Aquí está, seguramente, lo más elegante del diseño. Un ordenador de 1969 hecho de núcleos de ferrita y transistores sueltos, metido en una nave llena de vibraciones y radiación, se iba a reiniciar tarde o temprano. Hacer como si eso no fuera a pasar no era una opción; impedirlo, tampoco. Así que lo convirtieron en algo normal.

El truco son los puntos de control: la misma idea que guardar la partida en un videojuego. A lo largo de cada operación delicada, el programa va dejando constancia de por dónde va con una llamada a PHASCHNG:

PHASE_TABLE_MAINTENANCE.agc# PHASCHNG IS THE MAIN WAY OF MAKING PHASE CHANGES FOR RESTARTS.  THERE ARE THREE FORMS OF PHASCHNG, KNOWN AS TYPE
# A, TYPE B, AND TYPE C.  THEY ARE ALL CALLED AS FOLLOWS, WHERE OCT XXXXX CONTAINS THE PHASE INFORMATION,
#		TC	PHASCHNG
#		OCT	XXXXX

Y el código se escribe de manera que volver al último punto anunciado sea inofensivo. Don Eyles, que programó el descenso, lo resume en tres líneas:

el patrónNEW_X = X + 1
    registrar el punto de control
X = NEW_X

Parece una tontería y no lo es. Primero se calcula el valor nuevo aparte, sin tocar el bueno; luego se marca el punto de control; y solo entonces se guarda. Mira los dos casos posibles: si el ordenador se reinicia antes de la marca, al volver repite el cálculo y listo, porque no había llegado a cambiar nada. Si se reinicia después, el valor ya está guardado y tampoco hay que hacer nada. No existe ningún instante intermedio en el que el corte te deje las cosas a medio hacer.

Si esto te suena, es porque lo usas sin pensarlo: es exactamente lo que hay detrás de una transacción de base de datos, de un commit y de que una API se pueda reintentar sin duplicar nada. Lo escribieron veinte años antes de que a nadie le hiciera falta ponerle esos nombres.

Al arrancar de nuevo, la rutina RESTARTS recorre la tabla de fases y vuelve a poner en marcha cada cosa que estaba pendiente, desde su último punto de control. El programa en curso sigue, la pantalla se repinta y el astronauta ve, como mucho, un parpadeo.

Hay un registro en la memoria que se llama REDOCTR y cuyo comentario en el fuente dice CONTAINS NUMBER OF RESTARTS: un contador de reinicios. No era una excepción, era una estadística.

Idea 4: una máquina virtual, para que el código cupiera

El guiado es matemática de vectores: productos escalares, productos vectoriales, matrices de rotación, raíces, todo en doble precisión. Escribir eso en el ensamblador del AGC —que trabaja con palabras de 15 bits y tiene una aritmética mínima— ocupa una barbaridad de memoria.

Así que hicieron algo que suena a herejía y es de puro sentido común: se inventaron un segundo idioma. Un idioma en el que «multiplica estos dos vectores» se dice con una sola palabra, en vez de con las decenas de instrucciones que hacen falta en el idioma de la máquina. Y escribieron un programa, el intérprete, que lee ese idioma y lo va traduciendo sobre la marcha.

Es, literalmente, una máquina virtual metida dentro del AGC, con su propio juego de instrucciones. Lo mismo que hace Java con su bytecode, pero en 1969 y por un motivo muy concreto: que el programa cupiera.

INTERPRETER.agc — la tabla de saltoINDJUMP		TCF	VLOAD		# 00 -- LOAD MPAC WITH A VECTOR.
		TCF	TAD		# 01 -- TRIPLE PRECISION ADD TO MPAC.
		TCF	SIGN		# 02 -- COMPLEMENT MPAC (V OR SC) IF X NEG.
		TCF	VXSC		# 03 -- VECTOR TIMES SCALAR.
		...
		TCF	VAD		# 24 -- VECTOR ADD.
		TCF	VSU		# 25 -- VECTOR SUBTRACT.
		TCF	BVSU		# 26 -- VECTOR SUBTRACT FROM.
		TCF	DOT		# 27 -- VECTOR DOT PRODUCT.
		TCF	VXV		# 30 -- VECTOR CROSS PRODUCT.
		TCF	VPROJ		# 31 -- VECTOR PROJECTION.

Las tablas de salto del intérprete suman más de setenta operaciones: cargar un vector, multiplicarlo por un escalar, producto escalar, producto vectorial, matriz por vector, raíz cuadrada, seno, arcoseno, vector unitario. Un programa interpretado es entre cinco y diez veces más lento que el equivalente escrito a mano, y a cambio ocupa una fracción del espacio. Cuando tienes 36.864 palabras y una misión entera que meter dentro, ese cambio no se discute: se firma.

Las dos capas conviven en el mismo archivo y se distinguen a simple vista. Esto es un trozo del programa del alunizaje: las primeras líneas son instrucciones interpretadas, y EXIT es la que devuelve el control al ensamblador de la máquina.

THE_LUNAR_LANDING.agcP63SPOT2	VLOAD	UNIT		# INITIALIZE KALCMANU FOR BURN ATTITUDE
			R60VSAVE
		STOVL	POINTVSM
			UNITX
		STORE	SCAXIS
		EXIT

		CAF	EBANK7
		TS	EBANK

20 de julio de 1969: todo esto, a la vez

Con las cuatro piezas sobre la mesa, lo que pasó en el descenso se explica solo.

Empieza con un interruptor. El radar de encuentro —el que sirve para volver a acoplarse con el módulo de mando al final, no para alunizar— se había quedado en una posición que lo dejaba despierto. No estorbaba a nadie, en principio.

El detalle está en cómo le cuenta ese radar al ordenador hacia dónde apunta. Los dos aparatos se sincronizan con una señal eléctrica de 800 Hz, y el documento que describía esa conexión exigía que las dos señales tuvieran la misma frecuencia… pero no decía nada de que tuvieran que ir a compás. Era una línea que faltaba en el documento, y nadie la echó de menos hasta ese día.

Aquel día no iban a compás: estaban desfasadas casi un cuarto de onda. Y con ese desfase, la electrónica del radar se volvía loca midiendo: creía ver que la antena se movía todo el rato, y le mandaba al ordenador 6.400 avisos por segundo por cada uno de los dos ángulos, cuando la antena en realidad estaba quieta.

Aquí está la parte que hay que entender. Atender cada aviso no era «ejecutar un programa»: el hardware del AGC paraba el procesador un instante, le quitaba un ciclo para actualizar el contador, y lo devolvía. Nada en el software se enteraba. Simplemente, el ordenador iba más lento sin que nadie supiera por qué. Eyles lo mide:

«Moviéndose a su velocidad máxima, los contadores del radar de encuentro consumían aproximadamente el 15 % del tiempo de cálculo disponible. En su momento, siendo conservadores, supusimos que la pérdida de tiempo (que llamábamos TLOSS) era de un 13 %.»Don Eyles, Tales from the Lunar Module Guidance Computer (2004). Grumman midió después un máximo del 13,36 %.

Un 13 % no suena a catástrofe. Y no lo habría sido si el ordenador hubiera ido holgado, pero iba al límite. Aquí es donde se juntan las cuatro ideas.

El trabajo gordo del descenso se llama SERVICER: es el que lee los sensores, calcula dónde está la nave y decide qué hacer con el motor. Se lanza cada dos segundos y tiene que haber terminado antes de que le toque otra vez. Con el radar robando ciclos, dejó de llegar a tiempo.

Y el reloj no espera a nadie. Cada dos segundos encolaba un SERVICER nuevo, aunque el anterior siguiera a medias. Cada copia se llevaba su bandeja y su cuaderno. Dos copias, tres, cuatro… y las bandejas eran ocho.

1 · Descenso normalSERVICERP63pantallaradarlibrelibrelibrelibre4 de 8 bandejas ocupadasCuatro trabajos en la cola. SERVICER terminadentro de su ciclo de 2 segundos y liberasu bandeja antes de que llegue el siguiente.2 · El radar roba el 13 % del tiempoSERVICERSERVICERSERVICERSERVICERP63pantallaradarradar8 de 8 bandejas ocupadasALARMA 1202SERVICER ya no acaba a tiempo, pero el relojsigue encolando una copia nueva cada dossegundos. Las ocho bandejas se agotan.3 · Tras el reinicioSERVICERP63pantallalibrelibrelibrelibrelibre3 de 8 bandejas ocupadasEl reinicio revive solo la copia más recientede cada trabajo desde su último punto decontrol. La cola queda limpia y el descenso sigue.

Cuando se agotaron, el Executive hizo exactamente lo que estaba escrito que hiciera: BAILOUT1, código 1202, y reinicio. Hasta aquí es una historia de un ordenador que se satura. Lo que la convierte en otra cosa es lo que pasó al reiniciar.

El reinicio no solo recuperaba el estado: tiraba el atasco. Al revivir desde la tabla de fases, de cada trabajo duplicado solo se restauraba la copia más reciente. Las copias a medias de SERVICER que se habían ido amontonando desaparecían de golpe, y el ordenador se encontraba otra vez con la cola despejada y tiempo de sobra para lo importante: el guiado, los motores y la pantalla.

«Un sistema de protección ante reinicios motivado sobre todo por la posibilidad de fallos del hardware proporcionó, por sinergia, una manera de soltar carga de cálculo ante un atasco de software causado por el TLOSS.»Don Eyles, en el mismo texto

Dicho de otro modo: el ordenador se atragantó, escupió lo que le sobraba y siguió. Pero eso, desde Houston y con el módulo lunar bajando hacia la superficie, no se ve. Lo único que se ve es una luz de aviso encendida y un número en la pantalla.

Steve Bales y Jack Garman tenían que decidir, en cuestión de segundos, si aquel 1202 quería decir «me estoy muriendo» o «me he atragantado y ya lo he resuelto». Sabían que era lo segundo porque lo habían visto en los simuladores unas semanas antes. Garman dijo «go», y detrás fueron Bales, Kranz y Duke.

Durante el descenso saltaron cinco alarmas de esas: primero 1202, «no quedan bandejas», y más tarde 1201, «no quedan cuadernos». El alunizaje no se interrumpió ni una sola vez.

Lo que de aquello seguimos haciendo

En el AGCHoy se llama
Trabajos con prioridad que se expulsanplanificador apropiativo por prioridades
Soltar lo secundario al saturarsedegradación elegante, backpressure
Puntos de control antes de cada paso críticotransacciones, commit, idempotencia
Reiniciar como mecanismo normal de recuperacióncrash-only software, reinicio supervisado
Un intérprete para que el código ocupe menosuna máquina virtual, un bytecode
Un código numérico por cada condición previstacódigos de error y observabilidad

La lista no es una analogía forzada: son las mismas decisiones, tomadas por las mismas razones y casi siempre antes. Y hay una séptima que no cabe en la tabla, que es la que Hamilton defendió cuando le dijeron que los astronautas no se equivocan: que el programa tiene que hacerse cargo de lo que puede salir mal, incluida la persona que está al otro lado.

Margaret Hamilton sonriendo, tumbada en el asiento de la maqueta del módulo de mando del Apolo, con el brazo levantado hacia el panel de mandos lleno de interruptores
Margaret Hamilton en la maqueta del módulo de mando del Apolo, en noviembre de 1969. El panel que tiene encima es el otro extremo de todo lo que cuenta esta página: los interruptores y la DSKY por los que un astronauta hablaba con los ocho trabajos, las nueve tareas y los puntos de control. Foto de la NASA, en dominio público.

Dónde mirarlo tú mismo

Todo lo citado en esta página sale de archivos que puedes abrir ahora mismo.

QuéDónde
El fuente del Apolo 11, módulo lunar y de mandogithub.com/chrislgarry/Apollo-11
El proyecto que lo transcribió, con los escaneos originales y un emuladorVirtual AGC
El relato de quien programó el descenso«Tales from the Lunar Module Guidance Computer»
El ordenador por dentroApollo Guidance Computer

Si abres el repositorio, empieza por Luminary099/EXECUTIVE.agc: son quinientas líneas y es el corazón de todo lo que cuenta esta página. Y si quieres el momento exacto, THE_LUNAR_LANDING.agc, que son trescientas treinta y cinco.

Las cifras de esta página —ocho core sets de 12 registros, cinco áreas VAC de 43, nueve tareas, las operaciones del intérprete, los códigos 1201 y 1202— están comprobadas una a una en el fuente de Luminary 1A build 099, que es el que voló en el Apolo 11, y coinciden con lo que cuenta Don Eyles. Los listados están copiados literalmente, con sus comentarios y sus erratas. Sobre Margaret Hamilton y su equipo escribimos cuando murió, el 30 de septiembre de 2026.

Cómo se construye el pensamiento lógico para programar: lo que dice la investigación

Una escalera de cuatro peldaños —conocer, trazar, explicar, escribir— junto al título del artículo

«Es que yo no tengo cabeza para esto.» Lo dice mucha gente que empieza a programar y se atasca, y detrás hay una creencia muy extendida: que existe un tipo de mente lógica, que unos la tienen y otros no, y que sin ella no hay nada que hacer. Resulta que esa pregunta se ha estudiado bastante, y lo que ha salido no se parece casi nada a lo que se repite.

Primero: el «gen del programador» no existe, y quien lo propuso se retractó

En 2006 circuló un artículo con un título que hizo fortuna: The camel has two humps, «el camello tiene dos jorobas». Sostenía que los estudiantes de programación no se reparten en una campana de Gauss sino en dos grupos separados —los que lo pillan y los que no lo pillarán nunca— y que un test sencillo podía distinguirlos antes de empezar el curso. La idea se citó durante años.

En julio de 2014, su autor, Richard Bornat, publicó una retractación. No una matización: una retractación.

«Dehnadi no descubrió un test de aptitud para programar. No encontró una manera de separar a las ovejas programadoras de las cabras no programadoras. No habíamos demostrado que la naturaleza gane a la crianza.»Richard Bornat, Camels and humps: a retraction, 24 de julio de 2014

El texto es insólito por lo franco. Bornat explica que escribió el artículo original mientras un antidepresivo le había provocado un episodio maníaco —se describe a sí mismo como «grandioso, extremadamente autojustificado y muy combativo»— y que las réplicas posteriores no sostuvieron sus afirmaciones. Un estudio en Toronto pasó el test a 59 estudiantes y no encontró diferencia con los no evaluados; otro no halló correlación entre los resultados del test y varias medidas de rendimiento en el curso.

Pero hay un matiz que suele perderse, y es la parte interesante. Bornat mantiene que su doctorando sí había encontrado algo:

Lo que Saeed Dehnadi observó fue que, al preguntar a estudiantes novatos qué hacía un programa de tres o cuatro líneas, muchos respondían como si ya tuvieran un modelo mental de lo que pasaba. No eran los modelos correctos. Eran, en palabras de Bornat, «reconociblemente racionales». Y los que respondían de forma consistente —aplicando siempre el mismo modelo, aunque fuera equivocado— acababan el curso mejor que los que iban cambiando de criterio pregunta a pregunta.

Si eso se sostiene, cambia el consejo. Lo que separaría no es tener el modelo correcto, sino tener un modelo y aplicarlo con coherencia. Es decir: leer un trozo de código y poder decir, equivocándote si hace falta, «esto hace esto y luego esto». Lo que mata no es equivocarse, es no tener ninguna hipótesis.

La pregunta del test, y qué medía en realidad

Merece la pena verla, porque la retractación de Bornat la incluye en su apéndice y explica el asunto mejor que cualquier resumen. Esta es, literalmente, una de las preguntas que se pasaba a estudiantes que nunca habían programado:

int a = 5;
int b = 3;
int c = 7;

c = b;
b = a;
a = c;

Debajo venía una lista de posibles valores finales de a, b y c para marcar. La respuesta correcta es esta:

ejecutadoa=3  b=5  c=3

Ahora viene lo interesante. Las opciones equivocadas de la lista no eran ruido: cada una es el resultado de aplicar, con total coherencia, un modelo mental distinto de lo que hace el signo igual. Programé los tres más comunes para comprobarlo:

Qué cree quien respondeA qué respuesta lleva¿Estaba en la lista?
Lo correcto: cada línea copia el valor de la derecha en la variable de la izquierda, y el cambio se arrastraa=3 b=5 c=3Sí
Que se lee al revés: c = b significa «b recibe c»a=7 b=7 c=7Sí
Que cada asignación intercambia los dos valoresa=3 b=5 c=7Sí
Que no se arrastra: cada línea usa siempre los valores de partidaa=7 b=5 c=3Sí

Las cuatro figuran entre las opciones del cuestionario original. No es casualidad: el test estaba construido así a propósito. Y de ahí sale lo que de verdad medía, que no era acertar.

Quien marcaba a=7 b=7 c=7 en todas las preguntas del test estaba equivocado, pero estaba aplicando una regla y aplicándola siempre igual. Quien marcaba una respuesta por un criterio en la primera pregunta y otro distinto en la tercera no tenía ninguna regla: estaba adivinando. Según los datos de Dehnadi, los primeros acababan el curso mejor que los segundos.

La moraleja práctica. Cuando leas código y no lo entiendas, lo peor que puedes hacer es encogerte de hombros. Lo que hay que hacer es comprometerse con una predicción: «yo creo que esto deja a en 7». Si ejecutas y sale 3, acabas de localizar exactamente qué parte de tu modelo está mal, y eso se arregla. Si no predijiste nada, no has aprendido nada aunque veas el resultado correcto.

Qué predice de verdad aprender a programar

En 2020, un equipo de la Universidad de Washington publicó en Scientific Reports el estudio más directo que conozco sobre la pregunta. Midieron a 36 personas sin experiencia previa en una batería de pruebas —aptitud para los idiomas, razonamiento fluido, memoria de trabajo, aritmética y actividad cerebral en reposo— y después las pusieron a aprender Python en diez sesiones de 45 minutos, midiendo cuánto avanzaba cada una.

Qué predice aprender a programar, según Prat et al. 2020Qué explica lo que una persona avanza aprendiendo a programarVarianza explicada, promedio de las tres medidas de resultado. Prat et al. (2020), 36 participantesRazonamiento fluido y memoria de trabajoRazonamiento fluido y memoria de trabajo: 34 %34 %Aptitud para los idiomasAptitud para los idiomas: 17 %17 %Actividad cerebral en reposoActividad cerebral en reposo: 10 %10 %AritméticaAritmética: 2 %2 %Los modelos explican entre el 50 % y el 72 % del resultado. El resto no lo explica ninguna de estas cuatro cosasMirando solo la velocidad de aprendizaje, la aptitud para los idiomas sube al 43 %

La aritmética explica el 2 %. No es que no sirva de nada; es que, frente a lo que casi todo el mundo da por supuesto, no es ni de lejos lo que marca la diferencia. Los propios autores lo dicen en el resumen: «la importancia de la aritmética puede estar sobrevalorada en los entornos modernos de educación en programación».

Lo que sí pesa es la combinación de razonamiento fluido y memoria de trabajo —la capacidad de sostener varias cosas en la cabeza y relacionarlas— y, de manera llamativa, la aptitud para aprender idiomas. La hipótesis del estudio era precisamente esa: que aprender un lenguaje de programación de adulto se parece más a aprender un segundo idioma que a hacer cuentas.

Cuidado con cómo se ha contado esto. Verás titulares del tipo «los idiomas predicen más que las matemáticas». Esa versión sale de mirar solo una de las tres medidas, la velocidad de aprendizaje, donde la aptitud lingüística llega al 43 % según la nota de prensa de la propia universidad. En el promedio de las tres medidas, que es lo que publica el artículo, el primer puesto lo ocupan el razonamiento fluido y la memoria de trabajo. Y son 36 personas: es un estudio pequeño, sugerente, no una ley.

La escalera: trazar y explicar van antes que escribir

La segunda línea de investigación útil no mira lo que traes de casa, sino el orden en que se adquieren las habilidades. En 2008, un grupo analizó las respuestas de 38 estudiantes a un examen de final de primer semestre y buscó qué tipos de pregunta predecían el resultado en la parte de escribir código.

La escalera de habilidades antes de escribir códigoLa escalera: lo que hay que saber hacer antes de escribir códigoConocer las piezasqué hace un if, qué hace un bucleTrazarseguir el código a mano y decir qué vale cada cosaExplicardecir en una frase para qué sirve el conjuntoEscribirproducir código propio que funcioneCuánto predice cada unaTrazar, por sí solo15 %Explicar, por sí solo7 %Las dos juntas46 %de lo que varía al escribir códigoLopez et al. (2008), 38 estudiantes. Una réplica de 2022 con más de 600 halló otras ordenaciones igual de válidas

El resultado es el que da nombre a la idea de una escalera. Saber trazar código —seguirlo a mano, línea a línea, y decir qué vale cada variable— explicaba por sí solo el 15 % de lo que variaba al escribir. Saber explicar en una frase para qué sirve un fragmento explicaba un 7 %. Pero las dos juntas explicaban el 46 %: casi la mitad.

La lectura práctica es bastante clara, y es lo contrario de lo que hace casi todo el mundo cuando empieza: antes de ponerte a escribir, acostúmbrate a coger código ajeno y responder dos preguntas. Qué vale cada cosa después de cada línea. Y para qué sirve el conjunto, dicho en una frase, sin repetir el código con palabras.

Y aquí el escepticismo obligatorio. Ese estudio tenía 38 estudiantes. Una réplica de 2009 lo encontró «en líneas generales consistente», pero avisó de que la fuerza de la relación entre explicar y escribir «es particularmente sensible a las preguntas concretas que se hagan». Y una réplica de 2022 con más de 600 estudiantes concluyó que la jerarquía original no aparece entre los modelos que mejor encajan, aunque sí otros parecidos; y añadió algo importante: estos análisis muestran correlaciones entre habilidades, no en qué orden conviene enseñarlas.

¿Y programar enseña a pensar?

La pregunta del revés también se ha estudiado, y mucho. La promesa de «enseñar a programar a los niños para que aprendan a pensar» se apoya en la idea de que la habilidad se transfiere a otros terrenos. En 2019, un metaanálisis reunió 105 estudios y 539 tamaños de efecto para comprobarlo.

TransferenciaEfecto (g de Hedges)Qué significa
Global0,49Moderada. Intervalo de confianza del 95 %: 0,37 a 0,61
Cercana0,75Fuerte, pero con mucha incertidumbre: 0,39 a 1,11
Lejana0,47Moderada: 0,35 a 0,59

Dicho en claro: sí, aprender a programar deja algo fuera de la programación. Donde más se notó fue en pensamiento creativo, habilidades matemáticas y metacognición —pensar sobre el propio pensamiento—, seguidas de las habilidades espaciales y el razonamiento. Donde menos, en el rendimiento escolar general y en la lectoescritura.

Dos avisos que vienen en el propio metaanálisis, y que explican por qué no conviene agitar el 0,49 como bandera. El primero: los efectos eran significativamente mayores en los estudios cuyo grupo de control no hacía nada que en los que lo comparaban con otra actividad. Parte de la mejora puede ser simplemente «hacer algo exigente» en vez de «programar». El segundo: los estudios publicados daban efectos mayores que los no publicados, que es la firma clásica del sesgo de publicación.

Entonces, ¿cómo se entrena?

Juntando las tres líneas sale un programa bastante concreto, y ninguna de sus piezas es «ser bueno en matemáticas».

1. Ten un modelo de la máquina, aunque sea tosco

Es la lección que queda en pie del episodio del camello. Antes de escribir, hay que poder decir qué está pasando: dónde se guardan las cosas, cuándo cambian, en qué orden se ejecutan las líneas. Coge un programa de cinco líneas y predice el resultado antes de ejecutarlo. Si aciertas, bien. Si fallas, mejor todavía: acabas de encontrar dónde tu modelo no coincide con la realidad, que es exactamente lo que había que encontrar.

Y conviene saber qué modelo usa el lenguaje que estás aprendiendo, porque no todos funcionan igual. El caso que más desconcierta a los principiantes es este:

x = [1, 2, 3]
y = x
y.append(4)

print(x)
print(y)
salida[1, 2, 3, 4]
[1, 2, 3, 4]

Casi todo el mundo espera que x siga valiendo [1, 2, 3], porque arrastra de las matemáticas del colegio la idea de que una variable es una caja con un valor dentro. En Python no es así, y el modelo correcto explica la salida sin esfuerzo:

El modelo de cajas frente al modelo de etiquetas para las variablesDos modelos de qué es una variable. Solo uno explica lo que pasa de verdadEl modelo de cajascada nombre guarda su copiax[1, 2, 3]y[1, 2, 3, 4]Predice que x sigue valiendo [1, 2, 3]y eso NO es lo que ocurreEl modelo de etiquetaslos nombres apuntan al mismo objeto[1, 2, 3, 4]xyx e y son dos nombres de una sola listatocar una es tocar la otray = x no copia nada: le pone otra etiqueta al mismo objeto. Para copiar hay que pedirlo: y = x[:]Tener claro cuál de los dos modelos usa tu lenguaje evita una familia entera de errores

La prueba está en el propio lenguaje: x is y devuelve True, porque no hay dos listas, hay una con dos nombres. Si lo que quieres es una copia de verdad, hay que pedirla:

u = [1, 2, 3]
v = u[:]          # ahora sí, una copia
v.append(4)

print(u, v, u is v)
salida[1, 2, 3] [1, 2, 3, 4] False

No hace falta aprenderse esto de memoria. Hace falta tener un modelo de qué pasa al escribir y = x, y ponerlo a prueba en cuanto algo no cuadre.

2. Traza a mano antes de escribir

Papel y lápiz, una tabla con una columna por variable, y una fila por cada vuelta del bucle. Es lento y es aburrido, y es lo que más correlaciona con llegar a escribir código que funcione. También es lo primero que la gente se salta.

Veámoslo con un caso concreto. ¿Qué devuelve esto?

def misterio(nums):
    tope = nums[0]
    for n in nums:
        if n > tope:
            tope = n
    return tope

misterio([3, 9, 4, 1, 7])

La tentación es ejecutarlo y ver qué sale. El ejercicio es el contrario: rellenar esta tabla a mano, una fila por vuelta, antes de tocar el teclado.

Vueltann > topetope al terminar
antes de empezar——3
1.ª3no3
2.ª9sí9
3.ª4no9
4.ª1no9
5.ª7no9

Devuelve 9. Lo valioso no es el número: es que al rellenar la tabla has tenido que decidir, en cada fila, qué valía cada cosa. Si te equivocas en una fila, esa casilla te señala el punto exacto donde tu modelo falla. Es un depurador de papel, y funciona igual de bien en cualquier lenguaje.

Dos preguntas que conviene hacerse siempre al acabar la tabla: ¿qué pasa si la lista está vacía? ¿Y si todos los números son iguales? Ahí es donde aparecen la mitad de los errores de verdad.

3. Explica en una frase

Después de entender un fragmento, resúmelo sin describirlo línea a línea: no «recorre el array y compara cada elemento con el siguiente», sino «comprueba si está ordenado». Esa diferencia —ver el bosque y no solo los árboles— es la que distinguía en los estudios a quien iba bien de quien iba regular.

Un ejemplo. Este fragmento:

def otro(nums):
    for i in range(len(nums) - 1):
        if nums[i] > nums[i + 1]:
            return False
    return True
Tipo de respuestaQué se dice
Línea a línea«Recorre los índices hasta el penúltimo, compara cada elemento con el siguiente y, si uno es mayor, devuelve falso; si acaba el bucle, devuelve verdadero.»
En una frase«Comprueba si la lista está ordenada de menor a mayor.»

La primera no está mal: es correcta y completa. Pero es una traducción del código a castellano, no una comprensión. La segunda exige haber visto para qué sirve el conjunto, que es la habilidad que en los estudios aparecía como escalón intermedio.

Hay una manera limpia de comprobar si de verdad lo has entendido: ponerle nombre. Si tu frase es buena, se convierte en el nombre de la función casi sola. Aquí otro pasaría a llamarse esta_ordenada, y el código deja de necesitar explicación.

4. Ponte a prueba en vez de releer

Aquí no hay que inventar nada: hay un informe de 2013 que revisó las técnicas de estudio más usadas y las puntuó por utilidad real. Las dos mejor valoradas fueron ponerse a prueba —intentar recuperar lo aprendido sin mirar— y repartir el estudio en el tiempo en vez de concentrarlo. Entre las peor valoradas: releer, subrayar y resumir, que son justo las tres que hace todo el mundo.

Llevado a programar: cerrar el tutorial y rehacer el ejercicio de memoria vale más que volver a leerlo tres veces. Y veinte minutos al día durante dos semanas valen más que una tarde entera de sábado.

5. Acepta la carga y redúcela

Si lo que más pesa es la memoria de trabajo, la consecuencia práctica es que hay que dejar de pedirle cosas. Nombres de variable que se entiendan sin recordar nada. Funciones cortas. Un problema a la vez. No es estilo: es quitarle peso a la parte de tu cabeza que resultó ser la más limitante.

Lo que no sabemos

Conviene terminar por aquí, porque la literatura es más modesta de lo que parecen sus titulares. Los estudios son pequeños —36 personas, 38 estudiantes—, las réplicas matizan o no confirman, y el metaanálisis grande viene con problemas de diseño reconocidos. Nadie ha demostrado qué orden de enseñanza es el mejor; se han demostrado correlaciones entre habilidades, que no es lo mismo.

Lo que sí se puede afirmar con cierta tranquilidad es lo que no hay: no hay evidencia de un don innato que reparta a la gente en dos grupos, y lo más parecido que se publicó acabó retractado por su propio autor. Lo que hay son habilidades que se entrenan, un par de ellas identificadas con bastante consistencia, y una creencia muy cara —«no tengo cabeza para esto»— que no se sostiene en los datos.

Si lo que buscas es la versión práctica y aplicada al día a día, con la IA ya de por medio, está en los diez consejos para quien empieza.

Las fuentes, de un vistazo

EstudioQué midióTamañoQué hay que tener en cuenta
Prat et al. (2020), Scientific ReportsQué predice aprender Python36Muestra pequeña; los titulares usan solo una de las tres medidas
Bornat (2014), retractaciónRetira el «test de aptitud» de 2006—El autor mantiene que hay un fenómeno real sin explicar
Lopez et al. (2008)Trazar y explicar frente a escribir38Réplica de 2022 con 600+: la jerarquía original no es la que mejor encaja
Scherer et al. (2019), J. Educ. Psychol.Si programar transfiere a otras capacidades105 estudiosGrupos de control pasivos y sesgo de publicación inflan el efecto
Dunlosky et al. (2013)Qué técnicas de estudio funcionanrevisiónNo es específico de programación

Todas las cifras se comprobaron contra la fuente original, no contra resúmenes: Prat, Madhyastha, Mottarella y Kuo (2020); la retractación de Bornat; el metaanálisis de Scherer, Siddiq y Sánchez Viveros; la réplica de Fowler et al. (2022), y el informe de Dunlosky, Rawson, Marsh, Nathan y Willingham en Psychological Science in the Public Interest. Los datos de Lopez et al. (2008) se tomaron de la réplica de Venables, Tan y Lister (2009), que los reproduce y los discute.

Aprender a programar cuando la IA ya escribe el código: diez consejos para quien empieza

Una persona señalando una lección de programación en la pantalla de su portátil

En 2013 publicamos aquí diez consejos para programadores que empiezan. Casi todos siguen valiendo: lee mucho, prueba tu código, no acumules malas prácticas, diviértete. Lo que ha cambiado en estos trece años no es la lista, es una cosa concreta: ahora puedes producir código que funciona sin haber entendido nada. Eso es nuevo, y cambia por dónde hay que tener cuidado.

El problema de fondo, en cuatro cifras

No hace falta opinar sobre si la IA es buena o mala para aprender. Hay datos, y apuntan todos en la misma dirección: la herramienta se ha vuelto universal y la confianza en ella ha bajado.

DatoCifraDe dónde sale
Programadores que usan o van a usar IA84 %Encuesta de Stack Overflow, 2025
Que confían en que acierta33 %Solo un 3,1 % confía «mucho»
Que se topan con respuestas «casi bien, pero no»66 %Su queja número uno
Que tardan más en depurar código generado45 %Su queja número dos

Y hay un dato más incómodo. En 2025, METR hizo un experimento con dieciséis programadores veteranos trabajando sobre sus propios proyectos, 246 tareas reales repartidas al azar entre «con IA» y «sin IA». Esperaban ir un 24 % más rápido con ella. Tardaron un 19 % más. Y lo más llamativo: al terminar seguían creyendo que habían ido un 20 % más rápido.

Cuidado con lo que ese estudio dice y lo que no. Los propios autores advierten de que no prueba que la IA frene a la mayoría de programadores: eran dieciséis veteranos, en repositorios enormes que conocían de memoria y con un listón de calidad alto. El dato que sí importa para quien empieza no es el 19 %, es el otro: la diferencia entre lo que creían y lo que medían. La sensación de ir rápido no es fiable, y es justo la sensación que engancha.

Los dos bucles

Dos maneras de usar la IA al aprender a programarLos dos bucles. Los dos producen código que funciona; solo uno enseñaEl bucle que no enseñadescribes el problemapegas lo que te danfuncionapasas al siguienteAl mes siguiente no sabesqué hace tu propio proyectoEl bucle que enseñalo intentas tú primerote atascas y preguntascomparas con lo tuyolo ejecutas y lo rompesTardas más hoy y muchomenos dentro de tres mesesLa diferencia no está en usar o no usar la IA: está en si llegas a ella con una pregunta o sin ella

Aquí está todo el asunto. Los dos bucles producen código que funciona. En el primero el proyecto avanza y tú no; en el segundo avanzan los dos. La diferencia no es usar o no usar la IA, sino si llegas a ella con una pregunta formada o sin ella.

Diez consejos

1. Escribe a mano hasta que el patrón te salga solo

Un bucle, una condición, abrir un archivo, recorrer una lista. Mientras eso no te salga sin pensar, escríbelo tú aunque tardes diez veces más. No es masoquismo: es que lo que no has escrito nunca tampoco sabrás leerlo después, y vas a pasarte la vida leyendo código. Cuando el patrón ya sea aburrido, delégalo sin remordimiento.

2. Pide explicaciones, no soluciones

«Escríbeme una función que ordene esta lista» te deja donde estabas. «Explícame por qué mi función devuelve la lista vacía» te deja mejor. Es la misma herramienta y el mismo minuto, y el resultado para ti es completamente distinto.

Un truco que funciona muy bien: pídele que critique tu código en lugar de escribirlo. «¿Qué le ves mal a esto?» suele dar más que cualquier cosa que te genere de cero.

3. Ejecuta todo. Siempre. Sin excepción

Que el código tenga buen aspecto no significa nada. Esta guía misma sale de un sitio donde todo lo que se publica se compila y se ejecuta antes, y esa costumbre ha pillado cosas que ninguna lectura habría pillado.

Un caso real de esta casa. Preparando un artículo sobre medir el rendimiento en Rust, un programa de prueba sumaba tres millones de cuadrados y daba un tiempo de 40 nanosegundos. Era imposible, y la explicación no era un error de medición: el compilador se había dado cuenta de que el resultado se podía calcular con una fórmula cerrada y había eliminado el bucle entero. El código era correcto y la medición no medía nada. Leyéndolo no se veía; ejecutándolo y desconfiando del número, sí.

4. Desconfía de las versiones y de los nombres

Es el fallo más frecuente y el más silencioso: la IA te da una versión de biblioteca o un nombre de función que suena perfectamente razonable y no existe, o existía hace dos años. No miente a propósito; reproduce lo que vio.

Otro caso de aquí: en una lección de Rust apareció una dependencia con la versión 0.9.2. Parecía correcta. La versión real era la 0.10.3, y en medio había una función que se había mudado de sitio, así que el ejemplo no compilaba. La regla que salió de ahí es sencilla: las versiones se preguntan a la herramienta del lenguaje —cargo add, npm view, pip index—, nunca de memoria. Ni de la tuya ni de la suya.

5. Aprende a depurar, que es lo que peor hace

Un 45 % de los programadores dice que depurar código generado le lleva más tiempo, y tiene sentido: para arreglar algo hay que tener un modelo mental de cómo funciona, y si el código no lo escribiste tú, no lo tienes.

Depurar no es pedirle a la IA que arregle el error. Es leer el mensaje entero —entero, no la primera línea—, reducir el problema hasta el caso más pequeño que falla, e imprimir valores hasta encontrar dónde deja de ser lo que creías. Esa habilidad es la que separa a quien avanza de quien se queda bloqueado, y es la única de esta lista que no se puede delegar.

6. Aprende la terminal y Git antes que ningún framework

Toda herramienta de IA da por hecho que sabes moverte por un sistema de archivos, leer un error en una consola y deshacer un cambio. Si no, cada sugerencia te deja más perdido que antes. Son dos tardes de inversión y valen para el resto de tu carrera: aquí tienes los comandos de Linux que de verdad se usan y las órdenes de Git.

Lo de Git tiene un motivo extra ahora: si vas a aceptar código que no escribiste, más te vale poder volver atrás con una orden.

7. El contexto lo pones tú

La IA sabe de código; de tu problema no sabe nada. No sabe qué datos vas a recibir de verdad, qué pasa si el usuario deja el campo vacío, ni por qué en tu empresa las fechas se guardan así. Cuando le pides algo sin contarle eso, rellena los huecos con lo más común, que casi nunca es tu caso.

De ahí sale el consejo práctico: antes de pedir nada, escribe en una frase qué entra, qué tiene que salir y qué pasa cuando algo va mal. Si no sabes escribir esa frase, el problema no es la herramienta.

8. No aceptes nada que no sabrías defender

La prueba es sencilla: si alguien te preguntara por qué esa línea está ahí, ¿sabrías contestar? Si no, no la publiques. No porque esté mal —puede estar perfecta—, sino porque el día que falle vas a estar tú delante y no vas a tener por dónde empezar.

Qué conviene delegar a la IA mientras se aprende y qué noQué puedes delegar mientras aprendes, y qué te tienes que quedardelega sin miedono lo deleguesDelegalo repetitivo que ya sabes escribirbuscar en la documentacióntraducir un error a lenguaje llanogenerar datos de pruebaRevisacódigo que no sabrías escribirnombres de funciones y versioneslo que toque archivos o la redsus explicaciones: suenan segurasHazlo túdecidir qué problema resuelvesejecutar y comprobar que sirvedepurar cuando fallaentender lo que vas a publicar

9. Termina cosas, aunque sean pequeñas

Con la IA es facilísimo empezar diez proyectos ambiciosos y no acabar ninguno, porque los primeros pasos salen gratis y los últimos no. Y lo que de verdad enseña está al final: el caso raro, el despliegue, el error que solo aparece con datos reales, la parte aburrida de dejarlo presentable.

Un programa pequeño y terminado enseña más que tres grandes a medias. Esto no es nuevo: ya estaba en la lista de 2013 y sigue siendo verdad.

10. Lee código que no sea tuyo

Entra en un proyecto de código abierto que uses y lee cómo está hecho. Verás decisiones que no se te habrían ocurrido y, sobre todo, verás cómo se organiza algo que lleva años vivo, que es exactamente lo que ninguna herramienta te va a enseñar de un tirón.

Aquí la IA sí ayuda mucho, y de la forma correcta: como lector infinito al que puedes preguntarle «¿qué hace este archivo?» sin que se canse.

Lo que está pasando con el código de todos

Hay una razón para insistir tanto en entender lo que se acepta, y no es moral: se está midiendo en los repositorios reales. La empresa GitClear analizó 623 millones de cambios de código entre 2023 y 2026, y el patrón es consistente.

Qué mide20232026
Bloques de código duplicados (por millón de líneas)40,373,0
Copiar y pegar dentro de un mismo commit9,4 %15,7 %
Líneas movidas, es decir, refactorizadas13 %3,8 %
Llamadas a funciones de otros archivos (reutilización)343223

Se duplica más y se reordena mucho menos. Los propios autores piden no leerlo como «la IA escribe mal»: lo que dicen es que el flujo de trabajo habitual con IA premia lo inmediato y lo visible, mientras «grava en silencio lo invisible y lo aplazado». Reordenar código que ya funciona es trabajo invisible, y es el primero que desaparece cuando generar una versión nueva cuesta diez segundos.

Para alguien que empieza esto se traduce en algo muy concreto: la habilidad que va a escasear no es escribir código, es ordenarlo.

Lo que no ha cambiado

Conviene cerrar por donde empezamos. De aquella lista de 2013, lo que sigue intacto es casi todo: leer mucho, no adoptar una tecnología solo porque es nueva pero probarlas igualmente, compartir lo que aprendes, cuidarte y pasarlo bien. Nada de eso depende de qué herramienta tengas abierta.

Y hay algo que la irrupción de la IA ha puesto más claro todavía: el trabajo nunca fue teclear. Era entender un problema lo bastante bien como para explicárselo a una máquina sin ambigüedades. Eso es lo que estás aprendiendo cuando aprendes a programar, y es exactamente lo que no se delega, porque es lo único que hay que saber para poder delegar el resto.

Sobre la imagen de portada. Es un montaje sobre la fotografía «Learning to Code», de Preply.com Images, bajo licencia CC BY 2.0, vía Wikimedia Commons.

Las cifras de este artículo están comprobadas contra sus fuentes originales: la encuesta a desarrolladores de Stack Overflow de 2025 (33 662 respuestas en la pregunta sobre confianza), el experimento de METR con programadores veteranos y el informe de GitClear sobre mantenibilidad. Los dos ejemplos de errores reales salen de artículos publicados en este sitio, donde todo el código se ejecuta antes de publicarse. Si quieres el otro lado del asunto, está qué cambia en el oficio cuando escribir código deja de ser el centro.

Cómo dirigir a Codex, el agente de programación de OpenAI

Portada con las tres capas para dirigir a Codex: los comandos, el archivo AGENTS.md y el encargo, sobre fondo verde claro

Codex es el agente de programación de OpenAI: trabaja en la terminal sobre tu proyecto real. Puede recorrer un repositorio, entender cómo está organizado, modificar archivos, ejecutar comandos, escribir pruebas e investigar errores. Esa es la diferencia con pegarle código a un chatbot: aquí el agente actúa sobre lo que tienes en disco.

Por eso aprender a usarlo no consiste en memorizar comandos. La herramienta tiene cerca de sesenta, y con media docena se cubre el trabajo diario. Lo que de verdad cambia el resultado es otra cosa: enseñarle cómo está organizado el proyecto, acotar qué puede tocar y decirle cómo comprobar que lo que hizo funciona.

Las tres capas

Conviene pensar el trabajo con Codex en tres niveles. Están ordenados de menos a más influencia sobre el resultado, y casi todo el mundo empieza por el que menos importa.

Las tres capas para dirigir a Codex 1 Los comandos Controlan la sesión y el entorno. Se aprenden en una tarde 2 AGENTS.md Las reglas permanentes del proyecto. Se escriben una vez y valen siempre 3 El encargo Objetivo, contexto, alcance y cómo se verifica. Aquí se gana o se pierde
Las barras de la derecha representan cuánto influye cada capa en la calidad del resultado.

Empezar en un proyecto

Codex se lanza desde el directorio del proyecto, porque es ahí donde va a trabajar:

cd mi-proyecto
codex

Antes de pedirle cambios de peso conviene comprobar dónde estás parado, sobre todo si trabajas con varios repositorios a la vez:

pwd
git status

Dentro de la sesión, el primer comando útil es /init, cuya descripción oficial es literalmente «crear un archivo AGENTS.md con instrucciones para Codex». Analiza el repositorio y redacta un primer borrador de las reglas.

No des por bueno lo que genere. El archivo de /init es un punto de partida, no un resultado. Revísalo y recórtalo: debe contener las reglas que de verdad importan, no un inventario de todo lo que hay en el repositorio.

AGENTS.md: las reglas del proyecto

Este archivo es el mecanismo más importante para personalizar el comportamiento de Codex, porque se lee en cada sesión sin que tengas que repetirlo. Una versión mínima y útil:

# AGENTS.md

## Objetivo
Qué hace este proyecto, en dos líneas.

## Arquitectura
- Backend: Python
- Frontend: React
- Base de datos: PostgreSQL

## Comandos
- Instalar: pip install -r requirements.txt
- Pruebas: pytest
- Lint: ruff check .
- Build: docker compose build

## Reglas
- Mantener los cambios dentro del alcance pedido.
- Ejecutar las pruebas después de modificar código.
- No introducir dependencias sin justificarlo.
- No guardar secretos en el repositorio.

## Seguridad
- Validar las entradas externas.
- No registrar contraseñas ni tokens.
- No desactivar la autenticación para resolver un error.

Lo más valioso de esa plantilla es la sección de comandos: si Codex sabe cómo se ejecutan las pruebas y el lint de tu proyecto, puede verificar su propio trabajo sin que se lo pidas cada vez.

Puede haber más de uno

En proyectos grandes, los archivos se acumulan por niveles: el de la raíz fija lo general y los de cada carpeta añaden lo específico. Lo más cercano al archivo que se está tocando manda.

Jerarquía de archivos AGENTS.md proyecto/AGENTS.md reglas generales: seguridad, estilo, proceso backend/AGENTS.md convenciones de Python y de la API frontend/AGENTS.md convenciones de React y estilos infra/AGENTS.md Docker, despliegue, variables Cuanto más cerca del archivo que se edita, más manda
Las reglas específicas complementan o sustituyen a las generales según la carpeta en la que Codex esté trabajando.
El error más común: convertirlo en un manual. Todo lo que metas ahí se lee en cada sesión y ocupa contexto. Guarda solo lo que aplique a casi cualquier tarea, sea propio de este repositorio, sea difícil de deducir mirando el código y deba respetarse siempre. Lo obvio solo añade ruido.

Los comandos que de verdad usarás

La CLI tiene cerca de sesenta comandos slash; escribir / en el prompt los lista todos. Estos son los que aparecen en el trabajo diario, con la descripción que trae la propia herramienta.

ComandoQué hace
/initCrea el AGENTS.md con las instrucciones del proyecto
/planCambia al modo plan: piensa y propone antes de tocar nada
/reviewRevisa los cambios actuales y busca problemas
/diffMuestra el git diff, incluidos los archivos sin seguimiento
/statusConfiguración de la sesión y consumo de tokens
/usageUso de la cuenta y límites
/permissionsDefine qué tiene permitido hacer Codex
/modelElige modelo y nivel de razonamiento
/compactResume la conversación para no agotar el contexto
/forkBifurca la conversación actual
/worktreeTrabaja en un worktree de git aparte
/skillsUsa skills para mejorar tareas concretas
/mcpLista y gestiona las herramientas MCP conectadas

Y desde la terminal, fuera de la sesión:

ComandoPara qué
codexAbre la sesión interactiva en el directorio actual
codex execEjecuta una tarea sin sesión interactiva, para scripts y CI
codex reviewRevisa cambios desde la línea de comandos
codex resume · codex forkRetoma o bifurca una conversación guardada
codex doctorDiagnostica problemas de instalación o configuración
codex sandboxEjecuta un comando bajo la política de aislamiento
codex mcp · codex pluginAdministra servidores MCP y plugins

Qué puede hacer sin preguntar

Este es el punto que más conviene entender antes de dejarlo trabajar solo, y funciona con dos perillas independientes: dónde puede escribir y cuándo pide permiso.

Políticas de aislamiento de Codex ◀ MÁS SEGURO MÁS RIESGO ▶ read-only Solo lee. Puede explorar y explicar, pero no modifica nada Para auditar código ajeno o pedir un análisis workspace-write Escribe dentro del directorio de trabajo, no fuera El punto de equilibrio para el día a día danger-full-access Sin restricciones. Solo dentro de un contenedor o máquina virtual El nombre ya avisa
La segunda perilla son las aprobaciones: --ask-for-approval on-request consulta antes de actuar, never no pregunta nunca.

Cómo pedir una tarea

Un buen encargo tiene cinco piezas: objetivo, contexto, restricciones, criterios de aceptación y forma de verificar. La diferencia se ve mejor con un ejemplo. En lugar de esto:

Haz login con JWT.

Esto otro:

Implementa autenticación con JWT.

Primero analiza la arquitectura actual y no hagas cambios.

Identifica:
- dónde está hoy la autenticación;
- qué componentes habría que modificar;
- qué dependencias harían falta;
- qué riesgos de seguridad aparecen.

Después presenta un plan.
No implementes nada hasta que el plan esté aprobado.

La segunda versión evita el problema más habitual: que el agente empiece a editar archivos antes de haber entendido el proyecto.

Plan, implementar, probar, revisar

Para cualquier tarea que no sea trivial, este es el ciclo que mejor funciona. Cada fase termina con algo que puedes mirar antes de dar paso a la siguiente.

Ciclo Plan, implementar, probar, revisar PLANIFICAR analiza sin tocar nada y propone IMPLEMENTAR solo lo acordado, sin salirse PROBAR pruebas, lint y compilación REVISAR git diff y efectos colaterales → un plan escrito → archivos modificados → pruebas en verde → informe de cambios Cada flecha es un punto donde puedes parar, mirar y corregir el rumbo
El valor del ciclo no está en las fases, sino en los cortes entre ellas.

En tareas largas ayuda mantener el plan en un archivo del repositorio, por ejemplo PLAN.md, con el objetivo, el estado actual, los archivos afectados, las fases, los criterios de aceptación y los riesgos. Así el plan sobrevive aunque la conversación se corte o se compacte.

Acotar el alcance

Un agente que explora encuentra problemas por el camino. Eso no significa que deba arreglarlos todos, y sin una instrucción explícita suele intentarlo:

Corrige únicamente el problema de autenticación.

Si encuentras otros problemas:
- no los toques;
- anótalos al final;
- sigue con la tarea original.

Esta regla de tres líneas evita que un arreglo pequeño acabe tocando medio proyecto.

Usarlo también para revisar

Codex sirve igual de bien como segundo par de ojos. Dos encargos que conviene tener a mano:

Haz una revisión de seguridad de los cambios actuales.

Busca: secretos expuestos, autenticación o autorización
insuficiente, validación de entradas, inyección SQL o de
comandos, manejo de archivos, datos sensibles en los logs
y dependencias inseguras.

No modifiques ningún archivo.
Devuelve los hallazgos ordenados por gravedad.
Revisa la arquitectura actual sin modificar código.

Analiza separación de responsabilidades, dependencias,
acoplamiento, escalabilidad, mantenibilidad y puntos
únicos de fallo.

Propón mejoras, pero no las implementes.

La plantilla que sirve para casi todo

Si tuvieras que quedarte con una sola cosa de esta guía, que sea esta estructura:

OBJETIVO      Qué quiero conseguir.
CONTEXTO      Qué necesita saber Codex del proyecto.
ALCANCE       Qué archivos o carpetas puede tocar.
RESTRICCIONES Qué no debe hacer bajo ningún concepto.
PROCESO       Qué pasos seguir y en qué orden.
VERIFICACIÓN  Cómo sabremos que terminó bien.
RESULTADO     Qué debe informarme al acabar.

Rellenarla cuesta un minuto y ahorra la mitad de las idas y venidas. Y como cada proyecto verifica de forma distinta, deja los comandos concretos en el AGENTS.md: pytest y ruff en Python, npm test y npm run build en JavaScript, go test ./... en Go, cargo test en Rust, mvn verify en Java.

Lo que no conviene delegar

La forma menos productiva de usar un agente es entregarle el proyecto y decirle «hazlo todo». Funciona mejor como colaborador que explora rápido una base de código, propone soluciones, implementa, ejecuta pruebas y documenta lo hecho, mientras tú sigues decidiendo los objetivos, las restricciones y qué se considera terminado.

Al final, dirigir a Codex se parece bastante a dirigir a alguien que acaba de entrar al equipo: es muy capaz, no conoce las costumbres de la casa y agradece que le digas dónde están los límites. Escribe eso una vez en AGENTS.md, acota cada encargo y pide siempre una forma de comprobar el resultado. El resto son comandos, y los comandos se aprenden solos.

Fuentes: repositorio oficial de Codex y la documentación para desarrolladores de OpenAI, consultadas el 30 de septiembre de 2026.

Cómo encajan los comandos de Claude Code

Portada titulada Guía de comandos, con una terminal clara que muestra cómo el primer carácter del mensaje decide si lo lee Claude, la CLI o la shell

Claude Code se usa desde la terminal y, al principio, parece que todo se reduce a escribirle lo que quieres. Pero debajo hay una superficie de comandos bastante amplia: cerca de ochenta comandos slash, una treintena de banderas de arranque, prefijos especiales, modos de permisos y varios archivos de configuración que se cargan solos. Aprenderlos de una lista alfabética no sirve de mucho, porque lo que cuesta entender no es cada comando por separado, sino cómo encajan.

Esta guía los ordena en cuatro esquemas: qué puedes escribir en el prompt, cómo se gobierna una sesión, qué permite cada modo de permisos y dónde vive la configuración.

1. Qué puedes escribir en el prompt

El primer carácter de tu mensaje decide quién lo procesa. Esa es la regla que ordena todo lo demás.

Qué puedes escribir en el prompt de Claude Code Lo que escribes en el prompt texto normal Instrucción para Claude: lee, escribe y ejecuta según tus permisos /comando Lo atiende la propia CLI: comandos y skills. Solo «/» abre el menú !comando Shell directo, sin pasar por Claude; la salida sí entra al contexto @ruta/archivo Referencia a un archivo, con autocompletado de rutas :emoji: Atajo de emoji: «:heart:» se convierte en el símbolo
El primer carácter determina si tu mensaje lo interpreta Claude, la CLI o la shell.

La distinción entre / y ! es la que más confusión causa. Con / le hablas al programa; con ! le hablas a tu shell y Claude solo observa el resultado, que queda en el contexto para que pueda comentarlo.

2. Cómo se gobierna una sesión

Una sesión de Claude Code no es una ventana que se abre y se cierra: se puede continuar, reanudar por nombre, ramificar, retroceder a un punto anterior y mandar a segundo plano. Este es el ciclo completo.

Ciclo de vida de una sesión de Claude Code ARRANCAR claude sesión nueva claude -c continúa la más reciente claude -r «nombre» reanuda una concreta Sesión en curso el contexto se va llenando a medida que trabajas DURANTE /context cuánto llevas usado /compact resume y libera /rewind vuelve atrás /branch bifurca aquí /clear empieza de cero SACAR DEL TERMINAL /background sigue sola en segundo plano /export guarda la conversación como texto
Una sesión se arranca de tres formas, se gobierna con media docena de comandos y puede sobrevivirte cerrando la terminal.

El comando que más rendimiento da al principio es /context: muestra cuánto del contexto llevas consumido. Cuando se llena, /compact lo resume para seguir trabajando sin perder el hilo, y /clear arranca de cero conservando la memoria del proyecto. /rewind es la red de seguridad: retrocede a un punto anterior de la conversación si algo salió mal.

3. Los comandos slash que de verdad usarás

Aquí conviene ser honesto: hay alrededor de ochenta comandos slash, y esta tabla recoge menos de una cuarta parte. Son los que aparecen en el trabajo diario, agrupados por lo que quieres conseguir. El resto son variantes y herramientas más específicas —para diseño, presentaciones, investigación, control remoto, tareas programadas— que tiene poco sentido memorizar: aparecen solas cuando escribes / en el prompt, y /help las lista todas para la versión que tengas instalada.

Quiero…ComandoQué hace
Ordenar el trabajo/initGenera el CLAUDE.md inicial analizando el proyecto
/planModo plan: explora y propone antes de tocar archivos
/diffMuestra los cambios hechos hasta ahora
/verifyComprueba que el cambio realmente funciona
Revisar código/code-reviewBusca errores; admite niveles de low a max
/security-reviewAnálisis de vulnerabilidades sobre los cambios
/simplifyPropone limpiezas y simplificaciones, sin cazar bugs
Ajustar la sesión/modelCambia el modelo en caliente
/configPanel de configuración: tema, modelo, estilo de salida
/permissionsReglas de qué puede hacer sin preguntar
Saber qué pasa/statusVersión, modelo, cuenta y conectividad
/usageCosto de la sesión y límites del plan
/doctorDiagnóstico de la instalación y la configuración
Trabajar en paralelo/subtaskManda una tarea a un subagente en segundo plano
/tasksMuestra todo lo que corre en paralelo
/loopRepite un prompt cada cierto intervalo
Extender la herramienta/memoryEdita el CLAUDE.md y gestiona la memoria automática
/mcpServidores MCP: conectar, autenticar, reconectar
/skillsLista las skills disponibles en este proyecto

4. Desde la terminal, antes de entrar

Buena parte del control se ejerce en el momento de arrancar. El modo -p es el que convierte a Claude Code en una pieza de scripting: ejecuta la tarea, imprime el resultado y sale, sin sesión interactiva.

ComandoPara qué
claude "arregla el test roto"Sesión interactiva con una tarea inicial
claude -p "resume este log"No interactivo: responde y sale. Admite entrada por tubería
claude -cContinúa la sesión más reciente de este directorio
claude -r "nombre"Reanuda una sesión concreta por nombre o identificador
claude -w ramaArranca en un worktree de git aislado
claude --model sonnetFija el modelo de arranque
claude --permission-mode planArranca directamente en un modo de permisos
claude --max-budget-usd 5Corta la sesión al llegar a ese gasto
claude update · claude doctorActualizar la herramienta y diagnosticar problemas
claude mcp · claude pluginAdministrar servidores MCP y plugins

5. Los modos de permisos

Este es el concepto que más conviene entender bien, porque decide cuánto pregunta Claude antes de actuar. Se cicla en cualquier momento con Shift+Tab, o se fija al arrancar con --permission-mode.

Modos de permisos de Claude Code ◀ PREGUNTA MÁS PREGUNTA MENOS ▶ default Solo lee sin preguntar. Todo lo demás pide confirmación plan Explora y propone; avisa antes de cualquier cambio de peso acceptEdits Edita archivos sin preguntar. Útil al iterar sobre código propio dontAsk Solo lo pre-aprobado; lo demás se deniega sin preguntar. Para CI auto Actúa con revisión automática de seguridad. Es el modo por defecto bypassPermissions Sin ninguna comprobación. Solo dentro de un contenedor o máquina virtual
Los seis modos, del más cauto al más permisivo. Shift+Tab los cicla durante la sesión.
Sobre el último modo. bypassPermissions —y su equivalente en la línea de comandos, --dangerously-skip-permissions— desactiva todas las comprobaciones. La propia documentación lo restringe a entornos aislados: un contenedor o una máquina virtual donde un comando equivocado no pueda causar daño real. En tu máquina de trabajo no compensa.

6. Dónde vive la configuración

Lo último que hace falta para tener el mapa completo es saber qué cosas influyen en el comportamiento de Claude sin que tú las pidas en cada mensaje. Hay dos grandes familias: lo que está siempre presente y lo que se carga solo cuando hace falta.

Dónde vive la configuración de Claude Code PLUGINS · empaquetan todo lo de abajo y lo distribuyen de golpe SIEMPRE EN CONTEXTO CLAUDE.md Reglas del proyecto: convenciones, arquitectura, estilo Memoria automática Notas que Claude guarda solo: preferencias y correcciones BAJO DEMANDA Skills Instrucciones que solo se cargan al invocarlas Subagentes · MCP Contextos aparte y herramientas externas conectadas POR EVENTOS Hooks Comandos de shell que se disparan solos: antes de usar una herramienta, al guardar un archivo, al abrir la sesión
Lo que está siempre cargado, lo que se trae cuando hace falta y lo que se dispara por eventos.

La diferencia entre CLAUDE.md y las skills es la que más se malinterpreta. El primero se lee entero en cada sesión, así que todo lo que metas ahí consume contexto siempre; una skill no cuesta nada hasta que se invoca. La regla práctica: en CLAUDE.md, lo que aplica a todo el proyecto; en una skill, lo que solo hace falta en cierto tipo de tarea.

7. Atajos que ahorran tiempo

AtajoQué hace
Shift+TabCicla entre modos de permisos
EscapeInterrumpe a Claude a media respuesta
Escape dos vecesLimpia la entrada o abre el retroceso de la conversación
Ctrl+CInterrumpe o limpia; dos veces seguidas, sale
Ctrl+RBúsqueda inversa en el historial de prompts
Ctrl+OMuestra u oculta el detalle de las llamadas a herramientas
Ctrl+BManda el trabajo actual a segundo plano
Ctrl+GAbre el prompt en tu editor
Ctrl+J o \+EnterSalto de línea sin enviar el mensaje

La forma corta de recordarlo

Si hubiera que quedarse con lo mínimo: el primer carácter decide quién lee tu mensaje; la sesión se puede continuar, ramificar y retroceder, así que no hace falta acertar a la primera; el modo de permisos es la perilla que gradúa cuánto pregunta; y la configuración se reparte entre lo que está siempre cargado y lo que aparece cuando hace falta.

El resto se descubre sobre la marcha. /help lista todo lo disponible en tu versión, y /doctor es el primer sitio al que ir cuando algo no responde como esperabas.

Fuente: documentación oficial de Claude Code, consultada el 30 de septiembre de 2026. Algunos comandos requieren versiones recientes de la herramienta.

El Zen de Python: los 19 principios que explican cómo piensa el lenguaje

Terminal oscura mostrando el comando import this y las primeras líneas del Zen de Python

El Zen de Python es la declaración de principios del lenguaje: una lista de aforismos que resumen cómo debería diseñarse y escribirse el código en Python. Los redactó Tim Peters, uno de los desarrolladores veteranos del proyecto, y desde 2004 están recogidos en la PEP 20, uno de los documentos oficiales de diseño del lenguaje.

Hay un detalle que suele pasarse por alto: la propia PEP 20 dice que Peters condensó los principios rectores de Python en veinte aforismos, «de los cuales solo diecinueve han sido escritos». El vigésimo nunca apareció, y esa ausencia terminó siendo parte de la broma.

Cómo mostrar el Zen de Python

Una de las curiosidades del lenguaje es que el Zen viene incluido en él. Basta con importarlo desde el intérprete:

import this

O ejecutarlo directamente desde la terminal:

python -m this

El módulo que lo imprime es, a su vez, otro chiste: el archivo this.py guarda el texto cifrado con ROT13 y lo descifra con una expresión enrevesada. Es decir, el código que predica la claridad incumple alegremente varios de sus propios principios.

El texto original

The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren’t special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one– and preferably only one –obvious way to do it.
Although that way may not be obvious at first unless you’re Dutch.
Now is better than never.
Although never is often better than right now.
If the implementation is hard to explain, it’s a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea — let’s do more of those!

Los 19 principios, uno por uno

1. Beautiful is better than ugly

Lo bello es mejor que lo feo.

El código no debería limitarse a funcionar: también debería tener una estructura limpia y coherente. Buena parte de esa belleza está en los nombres.

# Funciona, pero no dice nada
x = [i for i in range(100) if i % 2 == 0]

# Comunica la intención
numeros_pares = [
    numero for numero in range(100)
    if numero % 2 == 0
]

Las dos versiones producen el mismo resultado, pero solo la segunda explica qué contiene la lista sin obligar a leer la condición.

2. Explicit is better than implicit

Lo explícito es mejor que lo implícito.

Python prefiere que el comportamiento de un programa se entienda leyéndolo, sin reglas ocultas que haya que adivinar.

# Implícito: ¿de dónde sale sqrt?
from math import *
resultado = sqrt(16)

# Explícito: el origen de cada nombre está a la vista
import math
resultado = math.sqrt(16)

El segundo bloque además evita que una importación con asterisco pise sin avisar una función que ya existía con ese nombre.

3. Simple is better than complex

Lo simple es mejor que lo complejo.

Si un problema se resuelve de forma directa, rara vez hace falta añadir maquinaria.

# Innecesariamente elaborado
from functools import reduce
total = reduce(lambda a, b: a + b, precios)

# Directo
total = sum(precios)

Ambos suman la misma lista, pero el segundo se entiende de un vistazo y no obliga a importar nada.

4. Complex is better than complicated

Lo complejo es mejor que lo complicado.

Algunos problemas son complejos por naturaleza: procesar pagos, autenticar usuarios o sincronizar información entre servidores exige cierta complejidad, y no hay forma de evitarla.

Lo que sí se puede evitar es la complicación: capas, indirecciones y abstracciones que no responden al problema, sino a la forma en que se fue escribiendo el código.

5. Flat is better than nested

Lo plano es mejor que lo anidado.

Cada nivel de anidamiento obliga a recordar una condición más. Salir temprano de la función suele leerse mejor.

if not usuario:
    return

if not usuario.activo:
    return

if not usuario.tiene_permiso:
    return

hacer_algo()

La alternativa —tres if encajados uno dentro de otro— deja la línea importante escondida al fondo de la escalera.

6. Sparse is better than dense

Lo espaciado es mejor que lo denso.

No se trata de añadir líneas en blanco, sino de no amontonar varios pasos conceptuales en una sola expresión.

# Denso: filtrado, acceso y formateo en un solo renglón
usuarios = [u["nombre"].strip().title() for u in datos if u.get("activo") and u.get("nombre")]

# Espaciado: cada paso se lee por separado
activos = [u for u in datos if u.get("activo") and u.get("nombre")]
usuarios = [u["nombre"].strip().title() for u in activos]

7. Readability counts

La legibilidad importa.

Este es el principio que sostiene a los demás. El código debería ser comprensible para quien lo herede, y también para uno mismo dentro de seis meses.

if edad >= 18:
    permitir_acceso()

La idea de fondo es sencilla: el código se escribe una vez, pero se lee muchas veces.

8. Special cases aren’t special enough to break the rules

Los casos especiales no son lo bastante especiales como para romper las reglas.

Una biblioteca o una API deberían comportarse de forma consistente. Cada excepción que se añade «solo para este caso» es una regla más que quien la use tendrá que memorizar.

9. Although practicality beats purity

Aunque la practicidad le gana a la pureza.

Los principios anteriores no son leyes. Si la solución teóricamente impecable resulta incómoda de usar o de mantener, la solución práctica gana.

Este aforismo es, en el fondo, el permiso explícito para no aplicar los otros de forma dogmática.

10. Errors should never pass silently

Los errores nunca deberían pasar silenciosamente.

Cuando algo falla, casi siempre queremos enterarnos. Tragarse las excepciones convierte un error visible en un comportamiento extraño que aparecerá mucho después y en otro sitio.

# Peligroso: oculta cualquier fallo, incluidos los que no esperábamos
try:
    procesar_datos()
except Exception:
    pass

Lo razonable es capturar solo el error que sabemos manejar y dejar constancia del resto:

import logging

try:
    procesar_datos()
except ValueError as error:
    logging.error("No se pudieron procesar los datos: %s", error)
    raise

11. Unless explicitly silenced

A menos que hayan sido silenciados explícitamente.

La contraparte del anterior. A veces ignorar un error es exactamente lo correcto, siempre que se diga cuál y por qué.

import os

try:
    os.remove("archivo_temporal.txt")
except FileNotFoundError:
    pass  # si ya no está, el objetivo se cumplió igual

La diferencia con el ejemplo anterior es el alcance: aquí se silencia un error concreto y previsto, no todos.

12. In the face of ambiguity, refuse the temptation to guess

Ante la ambigüedad, rechaza la tentación de adivinar.

Cuando hay varias interpretaciones posibles, conviene fijar la intención en lugar de dejar que el programa decida por su cuenta.

# Ambiguo: la codificación depende de la máquina donde se ejecute
with open("datos.txt") as archivo:
    contenido = archivo.read()

# Explícito: el resultado es el mismo en cualquier sistema
with open("datos.txt", encoding="utf-8") as archivo:
    contenido = archivo.read()

13. There should be one — and preferably only one — obvious way to do it

Debería existir una, y preferiblemente solo una, manera obvia de hacerlo.

Python intenta ofrecer una forma natural de resolver cada tarea habitual, en lugar de media docena de alternativas equivalentes.

for elemento in elementos:
    print(elemento)

Cualquiera que conozca el lenguaje reconoce esta construcción de inmediato, y esa previsibilidad es justamente la ventaja.

14. Although that way may not be obvious at first unless you’re Dutch

Aunque esa manera quizá no sea obvia al principio, a menos que seas holandés.

La broma alude a Guido van Rossum, creador de Python y neerlandés. Debajo del chiste hay una observación cierta: una solución parece «obvia» solo después de conocer las convenciones del lenguaje.

15. Now is better than never

Ahora es mejor que nunca.

Esperar indefinidamente a la solución perfecta tiene un costo. Una implementación razonable que existe suele valer más que una ideal que nunca se termina.

16. Although never is often better than right now

Aunque muchas veces «nunca» es mejor que «ahora mismo».

El contrapeso irónico del anterior. No todo tiene que resolverse de inmediato: una decisión precipitada puede costar más que la demora que evitó.

17. If the implementation is hard to explain, it’s a bad idea

Si la implementación es difícil de explicar, es una mala idea.

Si hace falta un discurso largo para justificar por qué algo funciona, suele haber complejidad accidental de por medio: la que agregó el diseño, no la que traía el problema.

18. If the implementation is easy to explain, it may be a good idea

Si la implementación es fácil de explicar, puede ser una buena idea.

Conviene reparar en el puede. Que algo se explique fácil no garantiza que sea correcto ni suficiente; la simplicidad es una buena señal, no una prueba.

19. Namespaces are one honking great idea — let’s do more of those!

Los espacios de nombres son una idea extraordinariamente buena; ¡hagamos más de ellos!

Un espacio de nombres agrupa nombres y los mantiene separados de los demás, de modo que dos cosas puedan llamarse igual sin estorbarse.

import math

print(math.pi)
print(math.sqrt(25))

Aquí pi y sqrt viven dentro de math, así que no chocan con variables o funciones propias que se llamen igual. En un programa grande, esa separación es lo que mantiene el código navegable:

import json
from datetime import datetime

datos = json.loads('{"usuario": "ana"}')
ahora = datetime.now()

La idea central

Si hubiera que comprimir los 19 aforismos en una lista corta, quedaría algo así:

  1. Código legible.
  2. Código explícito.
  3. Código sencillo.
  4. Código mantenible.
  5. Código fácil de explicar.

El Zen no pide escribir menos código, sino escribir código que otras personas puedan entender y mantener. Por eso insiste tanto en la claridad y la legibilidad: son las cualidades que sobreviven al paso del tiempo y al cambio de equipo.

Conclusión

El Zen de Python funciona como una brújula, no como un reglamento. Casi ninguna decisión de diseño tiene una única respuesta correcta, pero estos principios ayudan a distinguir cuándo una solución está añadiendo complejidad innecesaria y cuándo está haciendo el programa más claro.

Al final todo se reduce a una idea: escribe código que sea fácil de leer, entender, explicar y mantener. Y si quieres leerlo en su versión original, ya sabes dónde está:

import this

Referencia: PEP 20 — The Zen of Python.

Programar con IA: qué cambia cuando escribir código deja de ser el centro

Portada con etiquetas que contrastan el trabajo que disminuye (escribir cada línea) con el que crece (especificar, integrar, verificar, mantener)

Durante mucho tiempo, la imagen del programador fue la de alguien frente a una pantalla, escribiendo línea tras línea hasta conseguir que una máquina hiciera lo que se le pedía. Esa imagen no ha desaparecido, pero se está quedando corta. Hoy, una parte del código puede surgir de una instrucción en lenguaje natural, una sugerencia del editor o un agente que explora un proyecto y propone cambios.

Eso cambia el trabajo. No lo vuelve automáticamente más sencillo ni elimina la necesidad de saber programar. La IA puede producir código con rapidez, pero alguien tiene que decidir qué problema vale la pena resolver, comprobar que la solución funciona en el contexto real y hacerse responsable de sus efectos.

La adopción ya es amplia, aunque la confianza sigue siendo cautelosa. En la encuesta de Stack Overflow de 2025, el 84% de quienes respondieron dijo que usa o planea usar herramientas de IA en su trabajo; al mismo tiempo, más personas desconfiaban de la precisión de sus resultados que las que confiaban en ella. El informe DORA de ese año ofrece una lectura útil: la IA tiende a amplificar lo que una organización ya hace bien y también sus problemas. Una herramienta más rápida no compensa requisitos confusos, sistemas difíciles de mantener ni una cultura que no deja tiempo para revisar.Fuentes: Stack Overflow, encuesta de 2025 · DORA, informe de 2025

Lo que empieza a delegarse

La IA puede encargarse de una primera versión de tareas acotadas y repetitivas. Por ejemplo:

  • Escribir funciones sencillas, estructuras iniciales y código repetitivo.
  • Proponer pruebas unitarias a partir de un comportamiento descrito.
  • Explicar qué hace una función o resumir partes de un código desconocido.
  • Sugerir documentación, comentarios, consultas o ejemplos de uso.
  • Ayudar a localizar errores probables y ofrecer opciones para corregirlos.
  • Convertir datos entre formatos o adaptar código siguiendo un patrón existente.
  • Explorar un repositorio y proponer cambios en varios archivos, cuando la herramienta tiene ese alcance.

Delegar aquí significa pedir una propuesta, no entregar el control. La IA puede entender mal una regla de negocio, usar una biblioteca de forma incorrecta o pasar por alto un caso límite. Incluso cuando el resultado parece convincente, hay que integrarlo, probarlo y revisarlo. La encuesta de Stack Overflow refleja esa tensión: muchos desarrolladores encuentran utilidad en estas herramientas, pero persisten dudas sobre la exactitud de lo que generan.Fuente: Stack Overflow, sección sobre IA

El criterio humano gana peso

Cuanto más fácil resulta generar código, más importante es decidir si ese código debe existir. El programador sigue teniendo que entender las necesidades de las personas, conversar con quienes conocen el problema y convertir pedidos vagos en requisitos que puedan verificarse.

También conserva tareas difíciles de reducir a una instrucción breve: elegir cómo se organiza un sistema, decidir qué riesgos son aceptables, preservar la privacidad, manejar información sensible y pensar cómo se mantendrá el producto con el tiempo. Una solución que compila puede ser insegura, costosa de operar o inadecuada para quienes la usarán.

Por eso, la revisión deja de ser el último trámite antes de entregar y se convierte en una actividad central. Revisar código generado implica preguntar: ¿hace lo que necesitamos?, ¿qué supuestos está haciendo?, ¿qué pasa cuando falla?, ¿expone datos?, ¿será comprensible para el próximo equipo? La respuesta no está siempre en el código mismo: también requiere conocer el producto, la organización y sus usuarios.

Nuevas actividades en el oficio

Dar contexto a las herramientas

Para obtener ayuda útil, el desarrollador debe reunir los requisitos, las convenciones del proyecto y las restricciones relevantes. Pedir «hazme una aplicación» suele producir algo superficial; plantear una tarea concreta, proporcionar ejemplos y definir cómo se comprobará el resultado mejora la colaboración.

Diseñar comprobaciones

Las pruebas automáticas, los analizadores, las revisiones de seguridad y la integración continua ayudan a comprobar cambios con rapidez. El desarrollador necesita diseñar esas barreras, interpretar sus resultados y detectar lo que todavía no cubren.

Coordinar agentes y cambios

Algunas herramientas pueden trabajar con varios archivos, ejecutar comandos o preparar cambios completos. Eso introduce trabajo de supervisión: dividir el encargo, limitar el alcance, revisar qué hizo la herramienta y decidir si sus cambios encajan con los de otras personas.

Administrar el riesgo y los datos

No todo código puede compartirse con cualquier servicio. Los equipos deben establecer qué información se puede enviar, qué herramientas están autorizadas y quién valida los resultados antes de usarlos en producción.

Aprender y enseñar de otra manera

La IA puede explicar tecnologías desconocidas o crear ejemplos para estudiar. Pero aprender a programar sigue requiriendo comprender fundamentos, depurar por cuenta propia y reconocer cuándo una explicación está equivocada. Para quienes empiezan, existe un riesgo especial: aceptar una solución que todavía no saben evaluar.

Qué no conviene entregar por completo

Hay decisiones que necesitan una persona con autoridad y conocimiento del contexto. No conviene delegar sin supervisión:

  • La definición final de los requisitos del producto.
  • La aceptación de riesgos de seguridad, privacidad o cumplimiento.
  • La aprobación de cambios que afectan datos, dinero o sistemas críticos.
  • La evaluación de si una solución es accesible, justa y apropiada para sus usuarios.
  • La responsabilidad frente a un error o un daño causado por el software.

La herramienta puede contribuir a esas tareas —por ejemplo, señalando riesgos potenciales—, pero no asume la responsabilidad profesional, legal o ética de quien la utiliza ni de la organización que publica el sistema.

Una profesión menos centrada en teclear

Esto no significa que escribir código vaya a dejar de importar. Entender estructuras de datos, redes, bases de datos, pruebas, seguridad y arquitectura ayuda a detectar errores y a orientar mejor a la IA. Lo que cambia es la proporción del tiempo: menos esfuerzo en producir cada línea desde cero, y más en especificar, integrar, verificar y mantener una solución completa.

Tampoco todos los equipos obtendrán el mismo beneficio. Si la documentación está desactualizada, el código es difícil de probar o nadie sabe quién revisa los cambios, generar más código puede aumentar el trabajo pendiente. DORA lo plantea como un efecto de amplificación: los resultados dependen tanto de las prácticas y las condiciones del equipo como de la herramienta.Fuente: DORA, informe de 2025

Para las personas programadoras, la oportunidad está en usar la automatización para quitarse trabajo mecánico y dedicar más atención a comprender problemas, conversar con usuarios y construir sistemas confiables. El peligro está en confundir velocidad con progreso: entregar antes algo que nadie entiende ni puede mantener no es una mejora.

La pregunta, entonces, no es solo cuántas líneas puede escribir la IA. Es qué hacemos las personas con el tiempo que libera, qué decisiones seguimos tomando y cómo comprobamos que el software realmente sirve. En ese futuro, programar no será únicamente decirle a la computadora qué hacer. Será saber qué pedir, qué aceptar, qué corregir y cuándo detenerse.

Fuentes: Stack Overflow Developer Survey 2025 y DORA, State of AI-assisted Software Development 2025.

Accesos directos en Visual Studio Code

Los accesos directos o shortcuts te permiten ser más productivo. Es por eso que te enlistamos algunos de los Accesos directos en Visual Studio Code, al menos algunos de los más útiles. si estás comenzando a desarrollar es bueno que te familiarices con ellos desde el inicio.

Ctrl + P – Muestra la barra de búsqueda para buscar archivos

En Mac es: Cmd + P

Con este acceso directo navegarás entre archivos todo el tiempo. Puedes escribir el nombre del archivo y abrirlo presionando Enter.

Ctrl + Shift + P – Muestra la paleta de comandos

En Mac es: Cmd + Mayús + P

Te muestra la paleta de comandos donde puedes buscar una acción.

Ctrl + B – Alternar la barra lateral

En Mac es: Cmd + B

Muestra u oculta la barra lateral donde puedes navegar por el explorador.

Ctrl + Shift + E – Ir a la ventana del Explorador

En Mac es: Cmd + Mayús + E

Va a la ventana del Explorador donde tiene su árbol de archivos y puede navegar usando las teclas de flecha.

Ctrl + Shift + M – Muestra rápidamente errores y advertencias

En Mac es: Cmd + Mayús + M

A todo el mundo le gusta el código libre de errores. Este comando muestra el panel de problemas donde puede ver los errores y advertencias identificados.

Ctrl + Shift + L – Selección multi cursor

En Mac es: Cmd + Mayús + L

Agregue cursores adicionales para editar todas las apariciones de la selección actual. Por lo general, es menos propenso a errores que buscar y reemplazar todo.

Ctrl + D – Selección uno por uno

En Mac es: Cmd + D

Similar al anterior, pero usa Ctrl + D si deseas agregar las ocurrencias de la selección actual una por una. Cada vez que presionas la combinación de teclas, agregas una nueva aparición a la selección.

Ctrl + / – alternar comentario de línea

En Mac es: Cmd + /

Alternar entre comportamiento de línea comentado y no comentado.

Ctrl + Shift + I – formatea todo el archivo

En Mac es: Mayús + Opt + F

En Windows: Mayús + Alt + F de Windows

Formatea todo el archivo activo o le solicita que instale una extensión de formateador. Puedes usar la extensión Prettier para formatear el código JS, por ejemplo.

Alt + Arriba o Alt + Abajo – Mover línea

En Mac es: Opt + Down u Opt + Up

Muy claro. Mueva la línea hacia arriba y hacia abajo.

Ctrl + Espacio – Mostrar sugerencias

Muestra sugerencias para completar rápidamente propiedades y otras cosas.

Y uno de mis favoritos:

Shift + Alt + Abajo o Shift + Alt + Arriba – Duplica la línea de código

En Mac es Mayus + Opt + Arriba o Mayus + Opt + Abajo

Este acceso directo te facilita duplicar el contenido de una línea de código hacia por debajo o arriba.

Accesos directos en Visual Studio Code

Estos son algunos de los accesos directos más útiles para Visual Studio Code, pero desde luego hay más y los puedes consultar en los siguientes enlaces:

Windows: https://code.visualstudio.com/shortcuts/keyboard-shortcuts-windows.pdf

Mac : https://code.visualstudio.com/shortcuts/keyboard-shortcuts-windows.pdf

Linux: https://code.visualstudio.com/shortcuts/keyboard-shortcuts-linux.pdf

Una de las mejores presentaciones de Machine Learning

El empleado de Google Jason Mayes, ingeniero creativo senior, ha publicado unas de las mejores presentaciones sobre Machine Learning. El trabajo es el resultado de dos años de experiencia, es gratuito y se puede descargar o visualizar en línea. Los únicos requisitos según su creador son los siguientes:

  • Dos horas de estudio y atención continuas.
  • Cerrar clientes de correo y aplicaciones de mensajería.
  • Buscar un lugar adecuado para su estudio, porque no por nada se trata del estudio de «deep learning».
  • Leer más de una vez las letras en negritas.

El único inconveniente, está en inglés, pero es más o menos fácil de entender.
El enlace directo: https://docs.google.com/presentation/

Linus Torvals, la mente detrás de Linux

Linus Torvalds transformó la tecnología dos veces: primero con el núcleo de Linux, que es uno de los soportes fundamentales de Internet, y lo hizo nuevamente con Git, el sistema de administración de código fuente utilizado por desarrolladores de todo el mundo. En una rara entrevista con el Curador de TED, Chris Anderson, Torvalds discute con gran apertura los rasgos de personalidad que impulsaron su filosofía de trabajo, su ingeniería y su vida.

Puedes activar los subtítulos en español.