El promedio de la industria del software en la década de 1980 era de 30 a 60 defectos por mil líneas de código. El equipo Cleanroom de IBM entregó un incremento de compiler de 20.000 líneas con 53 defectos encontrados en pruebas. Eso es 2,6 por KLOC. Algunos incrementos individuales de 10.000 líneas llegaron a pruebas de sistema sin defectos encontrados.

¿La parte más extraña? A los programadores se les prohibía ejecutar su propio código.

Qué significa realmente Cleanroom software engineering

Cleanroom software engineering, desarrollado por el matemático Harlan Mills en IBM en la década de 1980, es un proceso basado en teoría que se apoya en formal specification, structured design y mathematical correctness verification en lugar de Unit Testing y debugging. El nombre proviene de la fabricación de semiconductores. En una fábrica de chips, no introduces polvo para luego limpiarlo. Previenes la contaminación desde el principio.

En Cleanroom, los desarrolladores no hacen Unit Testing. No debuggean. Verifican.

El proceso divide el software en incrementos, típicamente de 5.000 a 15.000 líneas de código. Cada incremento se especifica, diseña, verifica y luego se prueba estadísticamente como una unidad completa. Los desarrolladores escriben el código, pero no se les permite compilarlo ni ejecutarlo durante el desarrollo. La primera vez que el código corre es durante las pruebas de sistema formales.

Cómo box structure verification reemplaza al debugging

El mecanismo central es la box structure specification. Cada componente se define en tres niveles.

La black box especifica el comportamiento externo. Define estímulos y respuestas sin mencionar el estado interno.

La state box agrega las variables de estado interno y la función de transición de estado.

La clear box es la implementación real, que debe ser un refinamiento estructurado de la state box.

Esta jerarquía importa porque te permite verificar la corrección en cada nivel independientemente. Demuestras que la state box implementa la black box, y que la clear box implementa la state box.

Así se ve en la práctica para una función con un correctness argument no trivial:

from typing import Optional

def binary_search(arr: list[int], target: int) -> Optional[int]:
    """
    Black box spec:
      Pre:  arr is sorted in non-decreasing order.
      Post: Returns index i such that arr[i] == target,
            or None if target is not present.
    """
    low, high = 0, len(arr) - 1

    while low <= high:
        mid = (low + high) // 2

        if arr[mid] == target:
            return mid
        elif arr[mid] < target:
            low = mid + 1
        else:
            high = mid - 1

    return None

El verification argument del ciclo es lo que importa. El equipo revisa esto juntos y confirma tres hechos. Primero, si arr[mid] == target, la postcondition se satisface inmediatamente. Segundo, si arr[mid] < target, el target solo puede existir en indexes mayores que mid, así que establecer low = mid + 1 preserva la invariante de que el target está en arr[low:high+1] si es que existe. Tercero, si arr[mid] > target, el argumento simétrico se cumple para high = mid - 1.

Esto no es un Code Review donde alguien pregunta si pensaste en arrays vacíos. Es una prueba grupal estructurada de que cada entrada posible produce la salida especificada.

Los números de IBM detrás de la afirmación de cero defectos

IBM aplicó Cleanroom a tres proyectos importantes a finales de la década de 1980 y principios de 1990: la COBOL Structuring Facility (40.000 líneas), un programa de vuelo de helicóptero de la Fuerza Aérea (35.000 líneas) y un sistema de planificación de transporte espacial de la NASA (45.000 líneas).

Los datos de COBOL/SF son los más detallados. El primer incremento de 20.000 líneas se desarrolló con formal specifications, box structure design y correctness verification grupal. No se permitió a los desarrolladores compilar ni ejecutar sus modules durante el desarrollo. El código fue directo a pruebas de sistema.

Resultado: 53 defectos encontrados durante las pruebas. Más del 90 % de todos los defectos fueron capturados durante la fase de verificación antes de que el código se ejecutara.

Para comparar, los proyectos convencionales de IBM de la época encontraban cerca del 60 % de los defectos antes de la ejecución. Cleanroom invirtió la proporción.

Algunos incrementos, particularmente los más pequeños de menos de 10.000 líneas, reportaron cero defectos encontrados en pruebas de sistema. De aquí proviene la afirmación de “10.000 líneas con cero defectos”. Sucedió. No fue universal, pero fue lo suficientemente reproducible como para que IBM lo convirtiera en un benchmark estándar.

Por qué no ejecutar tu propio código produce menos bugs

Esta es la parte que les rompe el cerebro a los desarrolladores. ¿Cómo puede no probar producir mejor código?

La respuesta es cognitiva, no técnica. Cuando sabes que no puedes ejecutar el código para verificar tu trabajo, diseñas con más cuidado. Escribes funciones más pequeñas. Piensas en Edge Cases antes de escribir. Te apoyas en el Type System y la programación estructurada porque no tienes red de seguridad.

Es la misma razón por la que los cirujanos usan listas de verificación. La restricción fuerza un modo mental diferente.

También hay una capa de control de calidad estadística. Cleanroom usa statistical usage testing basado en un operational profile. Los casos de prueba se extraen de la distribución de probabilidad del comportamiento real del usuario, no de la suposición del desarrollador sobre dónde están los bugs. Esto significa que estás midiendo confiabilidad, no solo cazando bugs.

Los trade-offs que mantuvieron a Cleanroom en un nicho

Cleanroom no conquistó el mundo. Hay razones.

Primero, la barrera de entrenamiento es severa. Necesitas equipos que puedan escribir formal specifications y construir mathematical correctness arguments. La mayoría de los graduados en CS en 2025 nunca han hecho una prueba formal de una función no trivial.

Segundo, el costo de diseño inicial es alto. IBM reportó que el texto de specification excedió al texto de diseño cuatro a uno en el proyecto COBOL/SF. Estás intercambiando tiempo de diseño por tiempo de pruebas. Eso funciona para compilers y software de vuelo. No funciona para una aplicación CRUD con requisitos de pivote semanales.

Tercero, la afirmación de cero defectos se refiere a defect density, no a la ausencia de todos los bugs. Un incremento Cleanroom aún puede tener specification errors. Si la black box está mal, la clear box verificada también está mal, solo que por construcción.

Cómo robar la disciplina Cleanroom sin la burocracia

Probablemente no puedas adoptar Cleanroom completo. Tu Product Manager no esperará una relación de especificación a código de cuatro a uno. Pero puedes robar las piezas de mayor valor.

1. Escribe el contract antes de la implementación.

Usa preconditions, postconditions e invariants para definir tu black box. Incluso comentarios informales te fuerzan a pensar en los límites antes de optimizar.

from typing import List, Tuple

def partition(nums: List[int], pivot: int) -> Tuple[List[int], List[int]]:
    """
    Black box spec:
      Pre:  True (any list of integers is valid).
      Post: left contains exactly the elements of nums where x <= pivot.
            right contains exactly the elements of nums where x > pivot.
            len(left) + len(right) == len(nums).
    """
    left = [x for x in nums if x <= pivot]
    right = [x for x in nums if x > pivot]

    # Runtime checks act as lightweight verification witnesses.
    assert all(x <= pivot for x in left)
    assert all(x > pivot for x in right)
    assert len(left) + len(right) == len(nums)

    return left, right

2. Reemplaza algunos Unit Tests con verification arguments.

Antes de escribir la prueba, escribe un argumento de una oración sobre por qué el código es correcto. Si no puedes construir esa oración, el diseño es demasiado complejo. Esta es la práctica Cleanroom más efectiva para equipos modernos.

3. Usa property-based testing como statistical usage testing.

Herramientas como Hypothesis en Python o fast-check en JavaScript generan entradas desde una distribución. Esto es espiritualmente más cercano al statistical testing de Cleanroom que las Unit Tests basadas en ejemplos.

4. Separa la compilación de la verificación.

Si habitualmente escribes una línea, compilas, corriges el typo, escribes otra línea, estás debuggeando por reflejo de espasmo. Intenta escribir una unidad lógica completa antes de ejecutarla. La incomodidad es el punto.

Preguntas frecuentes

¿Se usa Cleanroom hoy en día?

Sobrevive en dominios de misión crítica y seguridad crítica. La NASA, la FAA y algunos fabricantes de dispositivos médicos usan variantes del proceso. Es raro en software comercial.

¿Realmente puedo entregar código sin Unit Testing?

Solo si lo reemplazas con algo igualmente riguroso. Los equipos Cleanroom pasaron más horas en verificación que la mayoría de los equipos en testing. El tiempo no desapareció. Se movió a la izquierda.

¿Garantiza Cleanroom cero bugs?

No. Garantiza que la implementación coincide con la specification con alta probabilidad. Si la specification es incorrecta, el bug se conserva perfectamente.

¿Cuál fue el impacto en la productividad?

IBM reportó una productividad de más de 400 líneas de código por persona-mes en el proyecto COBOL/SF, en gran parte porque el tiempo de pruebas drásticamente reducido compensó el esfuerzo de diseño aumentado.

Conclusión

La próxima vez que alguien afirme que una metodología entrega software zero-defect, pide los datos del proyecto. Los números de Cleanroom de IBM son reales, pero provinieron de un contexto específico: equipos experimentados, entrenamiento formal, entrega incremental y la disposición de verificar en lugar de debuggear.

El incremento de 10.000 líneas con cero defectos es alcanzable. Solo cuesta más previsión de lo que la mayoría de las organizaciones está dispuesta a pagar.