Dónde caen los cortes: por qué la complejidad se decide antes del código
Le describes a una máquina el caso de uso que necesitas, iteras con ella un rato, y a los pocos minutos hay código que compila, corre y pasa los tests. El acto que durante medio siglo fue el centro del oficio, teclear las instrucciones, se automatizó casi por completo. Y sin embargo cualquiera que haya construido algo serio con estas herramientas sabe que el trabajo difícil no se fue. Cambió de lugar. Ahora se pelea antes de la primera línea, decidiendo qué se le pide a la máquina, y después, revisando si lo que produjo dice de verdad lo que el negocio necesitaba decir.
Ese desplazamiento es la mejor evidencia que tenemos de una tesis vieja. Si la dificultad del software hubiera vivido en escribir el código, la máquina que ahora lo escribe la habría disuelto. No la disolvió. La dejó a la vista.
Dónde caen los cortes
En un texto anterior sostuve que el entrelazamiento del código es real y señalable, pero que su costo no existe hasta que alguien intenta comprenderlo. Un pliegue que nadie lee no cuesta nada. Aquel ensayo terminaba en una idea que ahora hay que empujar más lejos. Todo el oficio, sea de Parnas o de Kay o de Hickey, se reduce a decidir dónde poner los cortes. Dónde termina una parte y empieza otra, qué queda oculto tras una frontera y qué se expone.
La pregunta que quedó sin responder es de qué material están hechos esos cortes. La tentación es contestar que se trazan en el código, entre archivos, entre clases, entre módulos. No es ahí. Cuando decides que el descuento y el impuesto son dos cosas separadas, o que el asiento contable es una unidad indivisible, no estás trazando una línea en el texto del programa. La estás trazando en tu comprensión del dominio. El código, después, la hereda. Repite en su estructura un corte que ya existía en el modelo.
Si eso es cierto, entonces el entrelazamiento que vemos en el código nunca nació ahí. El código es el síntoma. El origen está más arriba.
Naur y los programas muertos
Peter Naur lo había dicho en 1985, en un ensayo breve y desatendido que hoy se lee como un diagnóstico anticipado. En «Programming as Theory Building» sostiene que programar no consiste en producir un texto, sino en construir una teoría. Escribir un programa, dice, “primarily must be the programmers’ building up knowledge of a certain kind, knowledge taken to be basically the programmers’ immediate possession, any documentation being an auxiliary, secondary product”. El código y la documentación son producto secundario. Lo primario es el entendimiento que el programador construyó del problema y de por qué su solución tiene la forma que tiene.
Naur ofrece una prueba que no admite escapatoria. Un programa, dice, puede morir. “The death of a program happens when the programmer team possessing its theory is dissolved. A dead program may continue to be used for execution in a computer and to produce useful results. The actual state of death becomes visible when demands for modifications of the program cannot be intelligently answered.” El texto sigue ahí, intacto, ejecutándose sin un solo carácter cambiado. Y aun así el programa está muerto, porque nadie puede modificarlo de forma inteligente. Su teoría se perdió y no hay edición del texto que la reviva.
Piensa en lo que eso implica. Si la complejidad viviera en el código, el código muerto la conservaría igual que conserva su sintaxis, y bastaría con leerlo bien para curarla. Pero no basta. El texto completo, con toda su documentación, resulta insuficiente. Lo que se perdió con el equipo no estaba escrito en ninguna parte. Vivía en la teoría, en el modelo del problema que el equipo tenía en la cabeza. La complejidad se fue con ellos porque ahí era donde estaba.
La teoría se hereda trabajando
Hay una objeción evidente contra Naur, y conviene enfrentarla en vez de esquivarla. Si la teoría vive en la mente de quien la posee, suena a conocimiento privado, tácito, casi místico. Suena a que la comprensión es un estado mental encerrado en un cráneo, justo lo contrario de lo que defendí antes al decir que comprender es una práctica pública.
Pero Naur no dice eso. Dice algo más fino. Para que un programador nuevo llegue a poseer la teoría de un programa, escribe, no alcanza con que estudie el texto y la documentación. “What is required is that the new programmer has the opportunity to work in close contact with the programmers who already possess the theory.” La teoría no se transmite leyendo. Se hereda trabajando al lado de quien ya la tiene, participando de la práctica en la que esa teoría vive. Naur la compara con aprender a tocar un instrumento, algo que no se aprende leyendo la partitura sino ejecutándola bajo supervisión.
Eso disuelve la objeción. La teoría es privada como estado y pública como práctica. Se construye y se transmite en el uso compartido, entre personas, en el tiempo. Es exactamente lo que en otro lugar llamé lenguaje ubicuo. Cuando escribí que el lenguaje ubicuo no es un glosario, sino la forma en que el equipo piensa y modela el problema, estaba nombrando la misma cosa que Naur llama teoría. El modelo del dominio no es un documento ni un diagrama. Es un lenguaje compartido, y se extingue cuando el equipo que lo hablaba se dispersa. No queda nadie para sostenerlo.
Conceptos entrelazados, sistemas que emergen
Naur no estaba solo. Un año después, Fred Brooks publicó «No Silver Bullet» con un diagnóstico gemelo. La esencia del software, dice Brooks, es “a construct of interlocking concepts: data sets, relationships among data items, algorithms, and invocations of functions”. Conceptos entrelazados. La dificultad esencial no está en el lenguaje de programación ni en las herramientas, que Brooks llama accidente, sino en esa construcción conceptual. El código es el accidente, y ninguna herramienta que ataque el accidente toca la esencia.
Donella Meadows, en Thinking in Systems, agrega el principio que explica por qué. “The behavior of a system cannot be known just by knowing the elements of which the system is made.” El comportamiento de un sistema no se deduce de sus partes. Emerge de la estructura de relaciones entre ellas. En el software, las partes son las líneas de código. La estructura es el modelo. Refactorizar líneas es reordenar las partes, y el comportamiento del sistema, incluida su complejidad, nunca vivió en las partes. Vive en cómo se relacionan, que es una decisión del modelo, no del texto.
La anomalía
Si la complejidad estuvo siempre en el modelo, queda una pregunta incómoda. ¿Por qué tardamos tanto en verlo? Thomas Kuhn, en La estructura de las revoluciones científicas, describió cómo cambia lo que una comunidad es capaz de ver. Una disciplina opera bajo un paradigma, un conjunto de logros y supuestos que “for a time provide model problems and solutions to a community of practitioners”. Mientras el paradigma funciona, la comunidad hace lo que Kuhn llama ciencia normal, resolver problemas dentro de lo que el paradigma da por sentado, sin cuestionar el marco. El paradigma del software fue durante décadas el que pone el código en el centro. La dificultad estaba en escribirlo, leerlo, mantenerlo. Los patrones, las herramientas, las prácticas de refactor fueron los problemas resueltos dentro de ese marco.
Kuhn observa que el cambio empieza de un modo particular. “Discovery commences with the awareness of anomaly”, con el reconocimiento de un hecho que viola las expectativas que el paradigma había instalado. La IA que escribe el código es esa anomalía. Bajo el paradigma que pone el código en el centro, automatizar la escritura debería haber reducido la dificultad. No la redujo. La empujó hacia arriba, hacia la especificación y el modelo. Un hecho que el marco vigente no puede explicar, que es la definición kuhniana de anomalía.
Y aquí es donde mi lectura se aparta de Kuhn. Para él, cruzar al paradigma nuevo no descubre nada preexistente, porque no hay verdad neutral que la revolución pueda revelar. Con eso no puedo estar de acuerdo en este caso. La verdad estaba escrita desde 1985. Lo que cambió con la anomalía de la IA no fue el hecho, sino nuestra capacidad de verlo. Kuhn usaría el ejemplo del gestalt, el dibujo donde unos ven un pato y otros un conejo mirando exactamente lo mismo. Me quedo con la parte donde él admite que “what they look at has not changed”, que lo mirado no cambió. Cambió el ver. La complejidad estuvo siempre en el modelo. La IA solo corrió el velo que la hacía pasar por un problema de código.
Mathias Verraes, en «Software Design in the Agentic Age», recoge una frase de Sam Ruby que lo dice en clave presente, y sin necesidad de Kuhn. Cuando el agente escribe el código, “rigor doesn’t vanish when the agent writes the code — it migrates. Upstream into specifications, down into test suites treated as first-class artifacts, into type systems and constraints”. El rigor no se evapora. Se conserva y se muda río arriba, hacia la especificación y el modelo. Que es otra forma de decir que nunca había vivido en el tecleo del código.
El síntoma también importa
Queda una lectura torcida que hay que cerrar. Decir que el código es el síntoma no equivale a decir que el código da igual. En medicina el síntoma es precisamente lo que permite diagnosticar. Es lo que se ve, lo que se mide, donde se lee la gravedad de lo que pasa más adentro. Un modelo entrelazado se manifiesta en código entrelazado, y ese código es la única evidencia observable de que el modelo tiene un problema. Sin el síntoma nadie sabría que hay algo que curar.
Lo que la tesis afirma es otra cosa. Que tratar solo el síntoma es paliativo. Refactorizar el código sin tocar el modelo alivia sin curar, porque el entrelazamiento vuelve a manifestarse mientras su origen siga en pie. La cura está donde nace la complejidad, en la teoría del programa, en el modelo del dominio, en el lenguaje con que un equipo piensa su problema. Ahí es donde hay que trabajar, y ahí es donde la máquina todavía no puede reemplazarnos, porque construir esa teoría es hablar un lenguaje, y un lenguaje solo existe entre quienes lo usan.
Naur lo sabía cuando el software cabía en cintas y nadie soñaba con una máquina que escribiera el programa. Hizo falta que la máquina llegara y escribiera el código para que la profesión mirara, por fin, el lugar donde la dificultad había estado todo el tiempo.