La Bala de Plata

Descargar como pdf o txt
Descargar como pdf o txt
Está en la página 1de 21

La bala de plata

Esencia y Accidentes de la Ingeniería de Software


De todos los monstruos que llenan las pesadillas de nuestro folclore, nadie se asusta
más que los hombres lobo, porque se transforman inesperadamente de lo familiar en
horrores. Para estos, uno busca balas de plata que pueden ponerlas mágicamente a
descansar.

El proyecto de software familiar, al menos tal como lo ve el gerente no técnico, tiene


algo de este carácter; suele ser inocente y sencillo, pero es capaz de convertirse en
un monstruo de horarios perdidos, presupuestos malgastados y productos
defectuosos. Así que oímos gritos desesperados por una bala de plata, algo que haga
que los costos de software disminuyan tan rápido como lo hacen los costos de
hardware de computadoras.

Pero, mientras miramos hacia el horizonte de una década, no vemos ninguna bala de
plata. No hay un desarrollo único, ni en la tecnología ni en la técnica de gestión, que
por sí solo prometa una mejora de la productividad, en la fiabilidad, en la
simplicidad. En este artículo, intentaré demostrar por qué, examinando tanto la
naturaleza del problema del software como las propiedades de las balas propuestas.

Sin embargo, el escepticismo no es pesimismo. Aunque no vemos avances


sorprendentes, y de hecho, creo que son inconsistentes con la naturaleza del
software, muchas innovaciones alentadoras están en marcha. Un esfuerzo
disciplinado y constante para desarrollar, propagar y explotar estas innovaciones
debería producir una mejora en el orden de magnitud. No hay camino real, pero sí
un camino.

El primer paso hacia el manejo de la enfermedad fue reemplazar las teorías


demoníacas y las teorías del humor por la teoría germinal. Ese mismo paso, el
comienzo de la esperanza, en sí mismo defraudó todas las esperanzas de soluciones
mágicas. Les dijo a los trabajadores que el progreso se haría paso a paso, con gran
esfuerzo, y que se tendría que pagar un cuidado persistente e incesante a una
disciplina de limpieza. Así es con la ingeniería de software hoy en día.
¿Tiene que ser difícil? Dificultades Esenciales
No sólo no hay ahora ninguna bala de plata a la vista, la naturaleza misma del
software hace que sea poco probable que haya invenciones que sirvan para la
productividad, confiabilidad y simplicidad del software lo que la electrónica, los
transistores y la integración a gran escala hicieron para el hardware informático. No
podemos esperar nunca que se produzcan dos aumentos cada dos años.

Primero, uno debe observar que la anomalía no es que el progreso del software sea
tan lento, sino que el progreso del hardware de la computadora es tan rápido.
Ninguna otra tecnología desde que comenzó la civilización ha visto seis órdenes de
magnitud en el aumento del precio de rendimiento en 30 años. En ninguna otra
tecnología se puede elegir tomar la ganancia en la mejora del rendimiento o en la
reducción de costes. Estas ganancias fluyen de la transformación de la fabricación
de computadoras de una industria de ensamblaje a una industria de proceso.

En segundo lugar, para ver el ritmo de progreso que se puede esperar en la


tecnología del software, examinemos las dificultades de esa tecnología. Siguiendo a
Aristóteles, los divido en esencia, las dificultades inherentes a la naturaleza del
software, y los accidentes, esas dificultades que hoy en día asisten a su producción
pero no son inherentes.

La esencia de una entidad de software es una construcción de conceptos


interrelacionados: conjuntos de datos, relaciones entre elementos de datos,
algoritmos e invocaciones de funciones. Esta esencia es abstracta en el sentido de
que tal construcción conceptual es la misma bajo muchas representaciones
diferentes. No obstante, es muy preciso y rico en detalles.

Creo que la parte difícil de construir software es la especificación, diseño y prueba


de esta construcción conceptual, no el trabajo de representarla y probar la fidelidad
de la representación. Todavía cometemos errores de sintaxis, para estar seguros;
pero son borrosos comparados con los errores conceptuales en la mayoría de los
sistemas.

Si esto es cierto, construir software siempre será difícil. No hay una bala de plata
intrínseca.

Consideremos las propiedades inherentes a esta esencia irreducible de los sistemas


de software modernos: complejidad, conformidad, cambiabilidad e invisibilidad.
Complejidad. Las entidades de software son más complejas por su tamaño que
cualquier otra construcción humana porque no hay dos partes iguales (al menos por
encima del nivel de declaración). Si lo son, hacemos las dos partes similares en
subrutina -abierta o cerrada. En este sentido, los sistemas de software difieren
profundamente de las computadoras, edificios o automóviles, donde abundan los
elementos repetitivos.

Las computadoras digitales son en sí mismas más complejas que la mayoría de las
cosas que la gente construye: tienen un gran número de estados. Esto hace que
concebir, describir y probarlas sea difícil. Los sistemas de software tienen órdenes
de magnitud de más estados que las computadoras.

Del mismo modo, la ampliación de una entidad de software no es simplemente una


repetición de los mismos elementos en tamaños más grandes, sino que es
necesariamente un aumento en el número de diferentes elementos. En la mayoría de
los casos, los elementos interactúan entre sí de manera no lineal, y la complejidad
del conjunto aumenta mucho más que linealmente.

La complejidad del software es una propiedad esencial, no accidental. Por lo tanto,


las descripciones de una entidad de software que abstrae su complejidad a menudo
abstraen su esencia. Durante tres siglos, las matemáticas y las ciencias físicas dieron
grandes pasos al construir modelos simplificados de fenómenos complejos,
derivando propiedades de los modelos y verificando esas propiedades mediante
experimentos. Este paradigma funcionó porque las complejidades ignoradas en los
modelos no eran las propiedades esenciales de los fenómenos. No funciona cuando
las complejidades son la esencia.

Muchos de los problemas clásicos del desarrollo de productos de software derivan


de esta complejidad esencial y sus aumentos no lineales con el tamaño. De la
complejidad viene la dificultad de comunicación entre los miembros del equipo, lo
que lleva a fallas del producto, sobrecostes, retrasos en la programación. De la
complejidad viene la dificultad de enumerar, mucho menos entender, todos los
estados posibles del programa, y de eso viene la falta de fiabilidad. De la
complejidad de la función viene la dificultad de invocar la función, lo que dificulta
el uso de los programas. De la complejidad de la estructura viene la dificultad de
extender los programas a nuevas funciones sin crear efectos secundarios. De la
complejidad de la estructura vienen los estados no visualizados que constituyen
trampas de seguridad.
No sólo los problemas técnicos, sino también los de gestión se deben a la
complejidad. Hace que la visión de conjunto sea difícil, impidiendo así la integridad
conceptual. Hace difícil encontrar y controlar todos los cabos sueltos. Esto crea la
tremenda carga de aprendizaje y comprensión que hace que la rotación del personal
sea un desastre.

Conformidad. La gente de software no es la única que enfrenta la complejidad. La


física se ocupa de objetos terriblemente complejos incluso a nivel de partículas
"fundamentales". El físico trabaja, sin embargo, en una fe firme de que hay
principios unificadores que se pueden encontrar, ya sea en quarks o en teorías
unificadas de campo. Einstein argumentó que debe haber explicaciones
simplificadas de la naturaleza, porque Dios no es caprichoso ni arbitrario.

Tal fe no conforta al ingeniero de software. Gran parte de la complejidad que debe


dominar es arbitrariamente compleja, forzada sin rima ni razón por las muchas
instituciones y sistemas humanos a los que deben ajustarse sus interfaces. Estos
difieren de interfaz en interfaz, y de vez en cuando, no por necesidad sino sólo
porque fueron diseñados por diferentes personas, en vez de por Dios.

En muchos casos, el software debe conformarse porque es la llegada más reciente en


la escena. En otros, debe conformarse porque es percibido como el más confortable.
Pero en todos los casos, mucha complejidad viene de la conformación a otras
interfaces; esta complejidad no puede ser simplificada por cualquier rediseño del
software solamente.

Cambiabilidad. La entidad de software está constantemente sujeta a presiones de


cambio. Por supuesto, también lo son los edificios, coches, ordenadores. Pero las
cosas fabricadas se cambian con poca frecuencia después de su fabricación; son
reemplazadas por modelos posteriores, o se incorporan cambios esenciales en copias
de números de serie posteriores del mismo diseño básico. Call-backs de automóviles
son realmente bastante infrecuentes; los cambios de campo de las computadoras
algo menos frecuentes. Ambos son mucho menos frecuentes que las modificaciones
al software de campo.

En parte, esto es así porque el software de un sistema encarna su función, y la


función es la parte que más siente las presiones del cambio. En parte se debe a que el
software se puede cambiar más fácilmente: es puro pensamiento, infinitamente
maleable. De hecho, los edificios se cambian, pero los altos costos del cambio,
entendidos por todos, sirven para amortiguar los caprichos de los cambiadores.
Todo el software exitoso cambia. Hay dos procesos en marcha. En primer lugar,
como se encuentra que un producto de software es útil, la gente lo prueba en nuevos
casos en el borde o más allá del dominio original. Las presiones para la función
extendida provienen principalmente de usuarios a los que les gusta la función básica
e inventan nuevos usos para ella.

En segundo lugar, el software exitoso sobrevive más allá de la vida útil normal del
vehículo de la máquina para el cual fue escrito por primera vez. Si no hay
computadoras nuevas, entonces al menos nuevos discos, pantallas y nuevas
impresoras nuevas aparecen; y el software debe ajustarse a sus nuevos vehículos de
oportunidad.

En resumen, el producto de software está integrado en una matriz cultural de


aplicaciones, usuarios, leyes y vehículos de máquina. Todo esto cambia
continuamente, y sus cambios obligan inexorablemente a cambiar el producto de
software.

Invisibilidad. El software es invisible e invisualizable. Las abstracciones


geométricas son herramientas poderosas. El plano de planta de un edificio ayuda
tanto al arquitecto como al cliente a evaluar espacios, flujos de tráfico y vistas. Las
contradicciones y omisiones se hacen evidentes. Dibujos a escala de piezas
mecánicas y modelos de moléculas con figuras de palillo, aunque abstracciones,
sirven para el mismo propósito. Una realidad geométrica es capturada en una
abstracción geométrica.

La realidad del software no está inherentemente incrustada en el espacio. Por lo


tanto, no tiene una representación geométrica lista en la forma en que la tierra tiene
mapas, los chips de silicio tienen diagramas, las computadoras tienen esquemas de
conectividad. Tan pronto como intentamos diagramar la estructura del software,
encontramos que no constituye una, sino varios gráficos dirigidos generales
superpuestos uno sobre otro. Los varios gráficos pueden representar el flujo de
control, el flujo de datos, patrones de dependencia, secuencia temporal, relaciones
nombre-espacio. Estos gráficos no suelen ser ni siquiera planares, mucho menos
jerárquicos. De hecho, una de las maneras de establecer el control conceptual sobre
tal estructura es forzar el corte de enlaces hasta que uno o más de los gráficos se
conviertan en jerárquicos. [1]

A pesar del progreso en la restricción y simplificación de las estructuras del


software, éstas siguen siendo intrínsecamente invisualizables, y por lo tanto no
permiten que la mente utilice algunas de sus herramientas conceptuales más
poderosas. Esta carencia no sólo impide el proceso de diseño dentro de una mente,
sino que dificulta severamente la comunicación entre las mentes.

Avances pasados resolvieron dificultades accidentales


Si examinamos los tres pasos en el desarrollo de la tecnología de software que han
sido más fructíferos en el pasado, descubrimos que cada uno de ellos atacó una
dificultad importante en la construcción de software, pero que esas dificultades han
sido accidentales, no esenciales. También podemos ver los límites naturales de la
extrapolación de cada ataque.

Lenguas de alto nivel. Seguramente el golpe más poderoso para la productividad,


confiabilidad y simplicidad del software ha sido el uso progresivo de lenguajes de
alto nivel para la programación. La mayoría de los observadores dan crédito a ese
desarrollo con al menos un factor de cinco en la productividad, y con las ganancias
concomitantes en fiabilidad, simplicidad y comprensibilidad.

¿Qué logra un lenguaje de alto nivel? Libera a un programa de gran parte de su


complejidad accidental. Un programa abstracto consiste en construcciones
conceptuales: operaciones, tipos de datos, secuencias y comunicación. El programa
concreto de la máquina se ocupa de los bits, registros, condiciones, ramas, canales,
discos y demás. En la medida en que el lenguaje de alto nivel encarna los
constructos que uno quiere en el programa abstracto y evita todos los más bajos,
elimina todo un nivel de complejidad que nunca fue inherente al programa.

Lo más que puede hacer un lenguaje de alto nivel es amueblar todas las
construcciones que el programador imagina en el programa abstracto. Sin duda, el
nivel de nuestro pensamiento sobre las estructuras de datos, los tipos de datos y las
operaciones está en constante aumento, pero a un ritmo cada vez menor. Y el
desarrollo del lenguaje se acerca cada vez más a la sofisticación de los usuarios.

Además, en algún momento la elaboración de un lenguaje de alto nivel crea una


carga de herramientas-masterización que aumenta, no reduce, la tarea intelectual del
usuario que raramente utiliza las construcciones esotéricas.

Tiempo compartido. El tiempo compartido supuso una mejora importante en la


productividad de los programadores y en la calidad de su producto, aunque no tan
grande como la aportada por los lenguajes de alto nivel.
Compartir el tiempo ataca una dificultad muy diferente. El tiempo compartido
preserva la inmediatez, y por lo tanto permite mantener una visión general de la
complejidad. El lento giro de la programación por lotes significa que uno se olvida
inevitablemente de las minucias, si no del empuje, de lo que uno estaba pensando
cuando dejó de programar y llamó a la compilación y ejecución. Esta interrupción es
costosa en el tiempo, pues hay que refrescar la memoria. El efecto más grave bien
puede ser la decadencia del agarre de todo lo que está sucediendo en un sistema
complejo.

El giro lento, al igual que las complejidades del lenguaje de la máquina, es una
dificultad accidental y no esencial del proceso de software. Los límites de la
contribución potencial del tiempo compartido se derivan directamente. El principal
efecto del tiempo compartido es acortar el tiempo de respuesta del sistema. A
medida que este tiempo de respuesta pasa a cero, en algún momento sobrepasa el
umbral humano de notoriedad, unos 100 milisegundos. Más allá de ese umbral, no
cabe esperar ningún beneficio.

Entornos de programación unificados. Unix e Interlisp, los primeros entornos de


programación integrados que entran en uso generalizado, parecen haber mejorado la
productividad por factores integrales. ¿Por qué?

Atacan las dificultades accidentales que resultan del uso conjunto de programas
individuales, proporcionando bibliotecas integradas, formatos de archivo unificados
y tuberías y filtros. Como resultado de ello, las estructuras conceptuales que en
principio siempre podrían llamarse, alimentarse y utilizarse mutuamente pueden
hacerlo fácilmente en la práctica.

Este avance a su vez estimuló el desarrollo de bancos de herramientas completos, ya


que cada herramienta nueva podía aplicarse a cualquier programa que utilizara los
formatos estándar.

Debido a estos éxitos, los entornos son el tema de gran parte de la investigación
actual en ingeniería de software. Miramos sus promesas y limitaciones en la
siguiente sección.

Esperanzas para la Plata


Consideremos ahora los avances técnicos que más a menudo son avanzados como
posibles balas de plata. ¿Qué problemas abordan, los problemas de esencia o las
dificultades accidentales restantes? ¿Ofrecen avances revolucionarios o
incrementales?

Ada y otros avances lingüísticos de alto nivel. Uno de los acontecimientos


recientes más aclamados es Ada, un lenguaje de alto nivel para fines generales de
los años ochenta. Ada no sólo refleja mejoras evolutivas en los conceptos
lingüísticos, sino que además incorpora características para fomentar el diseño
moderno y la modularización. Tal vez la filosofía Ada es más un avance que el
lenguaje Ada, porque es la filosofía de la modularización, de los tipos de datos
abstractos, de la estructuración jerárquica. Ada es excesivamente rica, un resultado
natural del proceso por el que se establecieron los requisitos en su diseño. Eso no es
fatal, porque los vocabularios de trabajo subestablecidos pueden resolver el
problema del aprendizaje, y los avances de hardware nos darán el MIPS barato para
pagar los costos de compilación. Avanzar en la estructuración de los sistemas de
software es de hecho un uso muy bueno para el aumento del MIPS que nuestros
dólares comprarán. Los sistemas operativos, fuertemente criticados en los años 60
por sus costes de memoria y ciclos, han demostrado ser una forma excelente de
utilizar algunos de los MIPS y bytes de memoria baratos de la pasada oleada de
hardware.

Sin embargo, Ada no será la bala de plata que mate al monstruo de la productividad
del software. Después de todo, es sólo otro lenguaje de alto nivel, y la mayor
recompensa de tales lenguajes vino de la primera transición -- la transición de las
complejidades accidentales de la máquina a la declaración más abstracta de
soluciones paso a paso. Una vez que esos accidentes hayan sido eliminados, los
restantes serán menores, y el resultado de su remoción seguramente será menor.

Predigo que dentro de una década, cuando se evalúe la eficacia de Ada, se verá que
ha hecho una diferencia sustancial, pero no debido a ninguna característica
lingüística en particular, ni por la combinación de todas ellas. Tampoco los nuevos
entornos Ada serán la causa de las mejoras. La mayor contribución de Ada será que
el cambio a ella ocasionó que los programadores de entrenamiento en técnicas
modernas de diseño de software.

Programación orientada a objetos. Muchos estudiantes de arte tienen más


esperanza para la programación orientada a objetos que para cualquiera de las otras
técnicas de modas del día. Yo estoy entre ellos. Mark Sherman de Dartmouth anota
en CSnet News que uno debe tener cuidado de distinguir dos ideas separadas que
van bajo ese nombre: tipos de datos abstractos y tipos jerárquicos. El concepto del
tipo de datos abstractos es que el tipo de un objeto debe estar definido por un
nombre, un conjunto de valores propios y un conjunto de operaciones adecuadas en
lugar de por su estructura de almacenamiento, que debe ocultarse. Algunos ejemplos
son los paquetes Ada (con tipos privados) y los módulos de Modula.

Los tipos jerárquicos, como las clases de Simula-67, permiten definir interfases
generales que pueden perfeccionarse aún más proporcionando tipos subordinados.
Los dos conceptos son ortogonal_uno puede tener jerarquías sin esconderse y
ocultarse sin jerarquías. Ambos conceptos representan avances reales en el arte de
construir software.

Cada uno de ellos elimina otra dificultad accidental del proceso, permitiendo al
diseñador expresar la esencia del diseño sin tener que expresar grandes cantidades
de material sintáctico que no agrega contenido informativo. Tanto para los tipos
abstractos como para los tipos jerárquicos, el resultado es eliminar un tipo de
dificultad accidental de orden superior y permitir una expresión de mayor orden del
diseño.

Sin embargo, tales avances no pueden sino eliminar todas las dificultades
accidentales de la expresión del dibujo o modelo. La complejidad del diseño en sí
mismo es esencial, y tales ataques no hacen ningún cambio en eso. Una ganancia de
orden de magnitud sólo se puede obtener mediante programación orientada a objetos
si el subcepillo de especificación de tipo innecesario que todavía se encuentra en
nuestro lenguaje de programación es nueve décimas partes del trabajo que implica el
diseño de un producto de programa. Lo dudo.

Inteligencia artificial. Mucha gente espera que los avances en inteligencia artificial
proporcionen el revolucionario avance que dará ganancias de orden de magnitud en
productividad y calidad del software. [3] Yo no. Para ver por qué, debemos
diseccionar lo que significa "inteligencia artificial".

D.L. Parnas ha aclarado el caos terminológico:[4]

Hoy en día se utilizan comúnmente dos definiciones bastante diferentes de la


IA. AI-1: El uso de ordenadores para resolver problemas que antes sólo
podían resolverse mediante la aplicación de inteligencia humana. Al-2: El uso
de un conjunto específico de técnicas de programación conocidas como
programación heurística o basada en reglas. En este enfoque se estudian los
expertos humanos para determinar qué heurística o reglas de pulgar utilizan
para resolver problemas..... El programa está diseñado para resolver un
problema de la manera en que los seres humanos parecen resolverlo.

La primera definición tiene un significado deslizante.... Algo puede encajar


con la definición de Al-1 hoy en día pero, una vez que veamos cómo funciona
el programa y entendamos el problema, ya no pensaremos en él como Al?
Desafortunadamente no puedo identificar un cuerpo de tecnología que es
único en este campo..... La mayor parte de la obra es específica del problema,
y se requiere algo de abstracción o creatividad para ver cómo transferirla.

Estoy totalmente de acuerdo con esta crítica. Las técnicas utilizadas para el
reconocimiento de voz parecen tener poco en común con las utilizadas para el
reconocimiento de imágenes, y ambas son diferentes de las utilizadas en sistemas
expertos. Me cuesta mucho trabajo ver cómo el reconocimiento de imágenes, por
ejemplo, marcará cualquier diferencia apreciable en la práctica de la programación.
El mismo problema ocurre con el reconocimiento del habla. Lo difícil de construir
software es decidir lo que uno quiere decir, no decirlo. Ninguna facilitación de la
expresión puede dar más que ganancias marginales.

La tecnología de sistemas expertos, AI-2, merece una sección propia.

Sistemas expertos. La parte más avanzada del arte de la inteligencia artificial, y la


más ampliamente aplicada, es la tecnología para la construcción de sistemas
expertos. Muchos científicos de software están trabajando arduamente aplicando
esta tecnología al entorno de creación de software. 3,5] ¿Cuál es el concepto y
cuáles son las perspectivas?

Un sistema experto es un programa que contiene un motor de inferencia


generalizado y una base de reglas, toma los datos de entrada y las suposiciones,
explora las inferencias derivadas de la base de reglas, genera conclusiones y
consejos, y ofrece explicar sus resultados mediante el rastreo de su razonamiento
para el usuario. Los motores de inferencia típicamente pueden tratar con datos
borrosos o probabilísticos y reglas, además de la lógica puramente determinista.

Tales sistemas ofrecen algunas ventajas claras sobre los algoritmos programados
diseñados para llegar a las mismas soluciones a los mismos problemas:

La tecnología del motor de inferencia se desarrolla de forma independiente de


la aplicación y luego se aplica a muchos usos. Uno puede justificar mucho
esfuerzo en los motores de inferencia. De hecho, esa tecnología está muy
avanzada.

Las partes intercambiables de los materiales característicos de la aplicación se


codifican en la base de reglas de manera uniforme y se proporcionan
herramientas para desarrollar, cambiar, probar y documentar la base de
reglas. Esto regulariza gran parte de la complejidad de la propia aplicación.

El poder de tales sistemas no proviene de mecanismos de inferencia cada vez más


fanáticos, sino de bases de conocimiento cada vez más ricas que reflejan el mundo
real con mayor precisión. Creo que el avance más importante que ofrece la
tecnología es la separación de la complejidad de la aplicación del programa en sí.

¿Cómo se puede aplicar esta tecnología a la ingeniería de software? De muchas


maneras: Estos sistemas pueden sugerir reglas de interfaz, aconsejar sobre
estrategias de prueba, recordar frecuencias de tipo bug y ofrecer consejos de
optimización.

Muchas dificultades se interponen en el camino de la pronta realización de útiles


asesores expertos en sistemas para el desarrollador del programa. Una parte crucial
de nuestro escenario imaginario es el desarrollo de formas fáciles de llegar desde la
especificación de la estructura del programa hasta la generación automática o
semiautomática de reglas de diagnóstico. Aún más difícil e importante es la doble
tarea de adquirir conocimientos: encontrar expertos autoanalíticos que sepan por qué
hacen las cosas y desarrollar técnicas eficientes para extraer lo que saben y destilarlo
en bases de reglas. El prerrequisito esencial para construir un sistema experto es
contar con un experto.

La contribución más poderosa de los sistemas expertos seguramente será poner al


servicio del programador inexperto la experiencia y sabiduría acumulada de los
mejores programadores. Esta no es una contribución pequeña. La brecha entre la
mejor práctica de ingeniería de software y la práctica promedio es muy
amplia_quizás más amplia que en cualquier otra disciplina de ingeniería. Sería
importante disponer de una herramienta que difunda las buenas prácticas.

Programación "automática". Durante casi 40 años, la gente ha estado anticipando


y escribiendo acerca de la "programación automática", o la generación de un
programa para resolver un problema a partir de una declaración de las
especificaciones del problema. Algunos escriben hoy en día como si esperaran que
esta tecnología les proporcione el próximo avance. [5]
Parnas[4] implica que el término se usa para glamour, no para contenido semántico,
afirmando,

En resumen, la programación automática siempre ha sido un eufemismo para


la programación con un lenguaje de nivel superior al que estaba disponible
actualmente para el programador.

Sostiene, en esencia, que en la mayoría de los casos es el método de solución, no el


problema, cuya especificación hay que dar.

Estas aplicaciones tienen propiedades muy favorables:

 Los problemas se caracterizan fácilmente por un número relativamente


reducido de parámetros.
 Hay muchos métodos conocidos de solución para proporcionar una biblioteca
de alternativas.
 Un análisis exhaustivo ha conducido a reglas explícitas para seleccionar las
técnicas de solución, dados los parámetros del problema.

Es difícil ver cómo estas técnicas generalizan al mundo más amplio del sistema de
software ordinario, donde los casos con propiedades tan limpias son la excepción. Es
difícil incluso imaginar cómo podría ocurrir este avance en la generalización.

Programación gráfica. Una asignatura favorita para las tesis de doctorado en


ingeniería de software es la programación gráfica, o visual, la aplicación de gráficos
computarizados al diseño de software. [6,7] A veces la promesa de tal enfoque se
postula por analogía con el diseño de chips VLSI, en el que los gráficos
computarizados juegan un papel tan fructífero. A veces el teórico justifica el
enfoque considerando los diagramas de flujo como el medio ideal para diseñar
programas y proporcionando poderosas facilidades para construirlos.

Nada, ni siquiera convincente y mucho menos emocionante, ha surgido de tales


esfuerzos. Estoy convencido de que nada lo hará.

En primer lugar, como he argumentado en otras partes[8], el diagrama de flujo es


una abstracción muy pobre de la estructura del software. De hecho, es mejor verlo
como Burks, von Neumann y el intento de Goldstine de proporcionar un lenguaje de
control de alto nivel desesperadamente necesario para su computadora propuesta. En
la forma lamentable, multipágina, caja de conexión a la que se ha elaborado el
diagrama de flujo hoy en día, ha demostrado ser inútil como herramienta de diseño -
los programadores dibujan diagramas de flujo después, no antes, de escribir los
programas que describen.

En segundo lugar, las pantallas de hoy en día son demasiado pequeñas, en píxeles,
para mostrar tanto el alcance como la resolución de cualquier diagrama de software
muy detallado. La llamada "metáfora de escritorio" de la estación de trabajo actual
es, en cambio, una metáfora de "asiento de avión". Cualquiera que haya barajado
una vuelta llena de papeles mientras está sentado entre dos pasajeros portentosos
reconocerá la diferencia - uno puede ver sólo muy pocas cosas a la vez. El verdadero
escritorio proporciona información general y acceso aleatorio a una veintena de
páginas. Por otra parte, cuando los ajustes de la creatividad corren fuertes, más de un
programador o escritor ha sido conocido por abandonar el escritorio para el piso más
espacioso. La tecnología de hardware tendrá que avanzar bastante antes de que el
alcance de nuestros alcances sea suficiente para la tarea de diseño de software.

Más fundamentalmente, como he argumentado anteriormente, el software es muy


difícil de visualizar.

Verificación del programa. Gran parte del esfuerzo en la programación moderna se


dedica a las pruebas y la reparación de errores. ¿Existe quizás una bala de plata que
se pueda encontrar eliminando los errores en la fuente, en la fase de diseño del
sistema? ¿Se puede mejorar radicalmente tanto la productividad como la fiabilidad
del producto siguiendo la estrategia profundamente diferente de demostrar que los
diseños son correctos antes de que el inmenso esfuerzo sea vertido en su
implementación y prueba?

No creo que encontremos magia de productividad aquí. La verificación de


programas es un concepto muy poderoso, y será muy importante para cosas como
los núcleos de sistemas operativos seguros. Sin embargo, la tecnología no promete
ahorrar mano de obra. Las verificaciones son tanto trabajo que sólo unos pocos
programas sustanciales han sido verificados.

La verificación del programa no significa programas a prueba de errores. Aquí


tampoco hay magia. Las pruebas matemáticas también pueden ser erróneas. Por lo
tanto, mientras que la verificación puede reducir la carga de prueba del programa, no
puede eliminarla.

Más en serio, incluso la verificación perfecta del programa sólo puede establecer
que un programa cumple con sus especificaciones. La parte más difícil de la tarea de
software es llegar a una especificación completa y consistente, y gran parte de la
esencia de construir un programa es de hecho la depuración de la especificación.

Entornos y herramientas. ¿Cuánta más ganancia se puede esperar de la explosión


de las investigaciones en mejores entornos de programación? La reacción instintiva
de uno es que los grandes problemas de pago: sistemas de archivos jerárquicos,
formatos de archivo uniformes para hacer posibles interfaces de programa uniformes
y herramientas generalizadas, fueron los primeros en ser atacados y se han resuelto.
Los editores inteligentes específicos del idioma son desarrollos que aún no se
utilizan ampliamente en la práctica, pero lo más prometedor es que están libres de
errores sintácticos y errores semánticos simples.

Tal vez la mayor ganancia que todavía no se ha realizado de los entornos de


programación es el uso de sistemas de base de datos integrados para mantener un
seguimiento de los innumerables detalles que deben ser recuperados con precisión
por el programador individual y mantenerse actualizados para un grupo de
colaboradores en un solo sistema.

Sin duda, este trabajo merece la pena, y seguramente dará algún fruto tanto en
productividad como en fiabilidad. Pero por su propia naturaleza, el retorno de ahora
en adelante debe ser marginal.

Estaciones de trabajo. ¿Qué ventajas se pueden esperar para el software art del
aumento seguro y rápido de la potencia y la capacidad de memoria de la estación de
trabajo individual? Bueno, ¿cuántos MIPS se pueden usar fructíferamente? La
composición y edición de programas y documentos está totalmente soportada por las
velocidades actuales. La compilación podría soportar un empuje, pero un factor de
10 en la velocidad de la máquina seguramente dejaría el thinktime la actividad
dominante en el día del programador. De hecho, así parece ser ahora.

Unas estaciones de trabajo más potentes son bienvenidas. Mejoras mágicas de ellos
que no podemos esperar.

Ataques prometedores a la esencia conceptual


A pesar de que ningún avance tecnológico promete dar el tipo de resultados mágicos
con los que estamos tan familiarizados en el área de hardware, hay una abundancia
de buenos trabajos que están sucediendo ahora, y la promesa de un progreso
constante, aunque no espectacular.
Todos los ataques tecnológicos sobre los accidentes del proceso de software están
fundamentalmente limitados por la ecuación de productividad:

Si, como creo, los componentes conceptuales de la tarea están tomando ahora la
mayor parte del tiempo, entonces ninguna cantidad de actividad en los componentes
de la tarea que son simplemente la expresión de los conceptos puede dar grandes
ganancias de productividad.

Por lo tanto, debemos considerar aquellos ataques que abordan la esencia del
problema del software, la formulación de estas complejas estructuras conceptuales.
Afortunadamente, algunos de estos ataques son muy prometedores.

Comprar contra construir. La solución más radical posible para construir software
es no construirlo en absoluto.

Cada día esto se hace más fácil, ya que cada vez más y más proveedores ofrecen
más y mejores productos de software para una variedad vertiginosa de aplicaciones.
Mientras que nosotros los ingenieros de software hemos trabajado en la metodología
de producción, la revolución personal-computadora ha creado no uno, sino muchos
mercados masivos de software. Cada quiosco tiene revistas mensuales, que
clasificadas por tipo de máquina, anuncian y revisan docenas de productos a precios
que van desde unos pocos dólares hasta cientos de dólares. Fuentes más
especializadas ofrecen productos muy potentes para el mercado de estaciones de
trabajo y otros mercados Unix. Incluso las herramientas y los entornos de software
se pueden comprar de serie. En otras partes he propuesto un mercado para módulos
individuales. [9]

Cualquier producto de este tipo es más barato de comprar que de construir de nuevo.
Incluso a un costo de cien mil dólares, una pieza de software comprada está
costando sólo alrededor de un año programador. Y la entrega es inmediata!
Inmediato al menos para los productos que realmente existen, productos cuyo
desarrollador puede referir los productos a un usuario satisfecho. Además, tales
productos tienden a estar mucho mejor documentados y en cierto modo mejor
mantenidos que el software local.

Creo que el desarrollo del mercado masivo es la tendencia más profunda a largo
plazo en ingeniería de software. El costo del software siempre ha sido el costo de
desarrollo, no el costo de replicación. Compartir ese costo entre unos pocos usuarios
reduce radicalmente el costo por usuario. Otra manera de verlo es que el uso de n
copias de un sistema de software multiplica efectivamente la productividad de sus
desarrolladores por n. Eso es una mejora de la productividad de la disciplina y de la
nación.

La cuestión clave, por supuesto, es la aplicabilidad. ¿Puedo utilizar un paquete


disponible para realizar mi tarea? Algo sorprendente ha pasado aquí. Durante las
décadas de 1950 y 1960, un estudio tras otro demostró que los usuarios no
utilizarían paquetes estándar para la nómina, el control de inventarios, cuentas por
cobrar, etcétera. Los requisitos eran demasiado especializados, la variación de un
caso a otro demasiado grande. Durante los años ochenta, encontramos tales envases
en alta demanda y uso generalizado. ¿Qué ha cambiado?

No los paquetes, en realidad. Pueden ser algo más generalizadas y algo más
personalizables que antes, pero no mucho. Tampoco las solicitudes. En todo caso,
las necesidades empresariales y científicas de hoy en día son más diversas y
complicadas que las de hace 20 años.

El gran cambio se ha producido en la relación coste hardware/software. En 1960, el


comprador de una máquina de dos millones de dólares sentía que podía permitirse
250.000 dólares más para un programa de nómina personalizado, uno que se
deslizaba fácilmente y sin interrupciones en el entorno social hostil a las
computadoras. Hoy en día, el comprador de una máquina de oficina de 50.000
dólares no puede permitirse un programa de nómina personalizado, por lo que
adapta el procedimiento de nómina a los paquetes disponibles. Las computadoras
son ahora tan comunes, si no tan queridas, que las adaptaciones son aceptadas como
algo natural.

Hay excepciones dramáticas a mi argumento de que la generalización de los


paquetes de software ha cambiado poco a lo largo de los años: hojas de cálculo
electrónicas y sistemas de bases de datos simples. Estas poderosas herramientas, tan
obvias en retrospectiva y sin embargo tan tardías en su aparición, se prestan a
innumerables usos, algunos poco ortodoxos. Ahora abundan los artículos e incluso
los libros sobre cómo abordar tareas inesperadas con la hoja de cálculo. Un gran
número de aplicaciones que anteriormente se habrían escrito como programas
personalizados en Cobol o Report Program Generator ahora se hacen rutinariamente
con estas herramientas.

Muchos usuarios ahora operan sus propias computadoras día tras día en varias
aplicaciones sin necesidad de escribir un programa. De hecho, muchos de estos
usuarios no pueden escribir nuevos programas para sus máquinas, pero son expertos
en resolver nuevos problemas con ellos.
Creo que la única estrategia de productividad de software más poderosa para muchas
organizaciones hoy en día es equipar a los trabajadores intelectuales que están en la
línea de fuego con computadoras personales y buenos programas generalizados de
escritura, dibujo, archivos y hojas de cálculo, y luego liberarlos. La misma
estrategia, llevada a cabo con paquetes matemáticos y estadísticos generalizados y
algunas capacidades simples de programación, también funcionará para cientos de
científicos de laboratorio.

Perfeccionamiento de requerimientos y prototipado rápido. La parte más difícil


de construir un sistema de software es decidir exactamente qué construir. Ninguna
otra parte del trabajo conceptual es tan difícil como establecer los requisitos técnicos
detallados, incluyendo todas las interfaces con personas, máquinas y otros sistemas
de software. Ninguna otra parte del trabajo paraliza el sistema resultante si se hace
mal. Ninguna otra parte es más difícil de rectificar después.

Por lo tanto, la función más importante que el constructor de software realiza para el
cliente es la extracción iterativa y el refinamiento de los requisitos del producto. La
verdad es que el cliente no sabe lo que quiere. Por lo general, el cliente no sabe qué
preguntas deben ser respondidas, y casi nunca ha pensado en el problema en los
detalles necesarios para la especificación. Incluso la simple respuesta_"Hacer que el
nuevo sistema de software funcione como nuestro antiguo sistema de procesamiento
manual de información"_es demasiado simple. Uno nunca quiere exactamente eso.
Los sistemas de software complejos son, además, cosas que actúan, que se mueven,
que funcionan. La dinámica de esa acción es difícil de imaginar. Así que en la
planificación de cualquier actividad de diseño de software, es necesario tener en
cuenta una amplia iteración entre el cliente y el diseñador como parte de la
definición del sistema.

Yo iría un paso más allá y afirmaría que es realmente imposible para un cliente,
incluso trabajando con un ingeniero de software, especificar completa, precisa y
correctamente los requisitos exactos de un producto de software moderno antes de
probar algunas versiones del producto.

Por lo tanto, uno de los esfuerzos tecnológicos más prometedores de los actuales, y
que ataca la esencia, no los accidentes, del problema del software, es el desarrollo de
enfoques y herramientas para la creación rápida de prototipos de sistemas, ya que el
prototipado es parte de la especificación iterativa de los requisitos.
Un sistema de software prototipo es aquel que simula las interfaces importantes y
realiza las funciones principales del sistema previsto, aunque no necesariamente está
sujeto a las mismas limitaciones de velocidad, tamaño o coste del hardware. Los
prototipos suelen realizar las tareas principales de la aplicación, pero no intentan
manejar las tareas excepcionales, responder correctamente a entradas no válidas o
abortar limpiamente. El propósito del prototipo es hacer realidad la estructura
conceptual especificada, de manera que el cliente pueda probarla para comprobar su
consistencia y usabilidad.

Gran parte del actual procedimiento de adquisición de software se basa en la


suposición de que uno puede especificar un sistema satisfactorio por adelantado,
obtener ofertas para su construcción, construirlo e instalarlo. Creo que esta
suposición es fundamentalmente errónea, y que muchos problemas de adquisición
de software surgen de esa falacia. Por lo tanto, no se pueden fijar sin una revisión
fundamental -revisión que prevé el desarrollo iterativo y la especificación de
prototipos y productos.

Desarrollo incremental---crecer, no construir, software. Todavía recuerdo la


sacudida que sentí en 1958 cuando escuché por primera vez a un amigo hablar sobre
la construcción de un programa, en lugar de escribir uno. En un santiamén amplió
mi visión del proceso de software. El cambio de metáfora era poderoso y preciso.
Hoy en día entendemos como otros procesos constructivos la construcción del
software es, y libremente utilizamos otros elementos de la metáfora, como
especificaciones, ensamblaje de componentes y andamios.

La metáfora del edificio ha sobrevivido a su utilidad. Es hora de cambiar de nuevo.


Si, como creo, las estructuras conceptuales que construimos hoy en día son
demasiado complicadas para ser especificadas de antemano con precisión y
demasiado complejas para ser construidas sin errores, entonces debemos adoptar un
enfoque radicalmente diferente.

Volvamos la naturaleza y estudiemos la complejidad en los seres vivos, en vez de


sólo las obras muertas del hombre. Aquí encontramos construcciones cuyas
complejidades nos emocionan con admiración. El cerebro por sí solo es intrincado
más allá del mapeo, poderoso más allá de la imitación, rico en diversidad,
autoprotector y renovador. El secreto es que crece, no se construye.
Así debe ser con nuestros sistemas de software. Hace algunos años, Harlan Mills
propuso que cualquier sistema de software debería ser cultivado mediante un
desarrollo incremental. 10] Es decir, primero se debe hacer funcionar el sistema,
aunque no haga nada útil excepto llamar al conjunto adecuado de subprogramas
ficticios. Luego, poco a poco, se debe desarrollar, con los subprogramas a su vez
desarrollados, en acciones o llamadas para vaciar los stubs en el nivel inferior.

He visto los resultados más dramáticos desde que empecé a instar esta técnica a los
constructores de proyectos en mi clase de Laboratorio de Ingeniería de Software.
Nada en la última década ha cambiado tan radicalmente mi propia práctica, o su
eficacia. El enfoque requiere un diseño de arriba hacia abajo, ya que es un
crecimiento del software de arriba hacia abajo. Permite un fácil retroceso. Se presta
a prototipos antiguos. Cada función añadida y nueva disposición para datos o
circunstancias más complejas crece orgánicamente a partir de lo que ya existe.

Los efectos de la moral son sorprendentes. El entusiasmo salta cuando hay un


sistema en marcha, incluso uno simple. Los esfuerzos se redoblan cuando la primera
imagen de un nuevo sistema de software gráfico aparece en la pantalla, aunque sólo
sea un rectángulo. Uno siempre tiene, en cada etapa del proceso, un sistema de
trabajo. Encuentro que los equipos pueden crecer en entidades mucho más
complejas en cuatro meses de lo que pueden construir.

Los mismos beneficios se pueden obtener en grandes proyectos como en los


pequeños. [11]

Grandes diseñadores. La cuestión central en cómo mejorar los centros de software


art, como siempre lo ha hecho, sobre las personas.

Podemos conseguir buenos diseños siguiendo buenas prácticas en vez de malas. Se


pueden enseñar buenas prácticas de diseño. Los programadores se encuentran entre
los sectores más inteligentes de la población, por lo que pueden aprender buenas
prácticas. Por lo tanto, un gran impulso en los Estados Unidos es promulgar buenas
prácticas modernas. Nuevos planes de estudio, nueva literatura, nuevas
organizaciones como el Instituto de Ingeniería del Software, todos han surgido para
elevar el nivel de nuestra práctica de pobre a bueno. Esto es totalmente correcto.

Sin embargo, no creo que podamos dar el siguiente paso hacia arriba de la misma
manera. Mientras que la diferencia entre los diseños conceptuales pobres y los
buenos puede estar en la solidez del método de diseño, la diferencia entre los buenos
diseños y los grandes seguramente no lo es. Grandes diseños vienen de grandes
diseñadores. La construcción de software es un proceso creativo. Una metodología
sólida puede empoderar y liberar la mente creativa; no puede inflamar o inspirar el
impulso.

Las diferencias no son menores, son como las diferencias entre Salieri y Mozart.
Estudio tras estudio muestra que los mejores diseñadores producen estructuras más
rápidas, pequeñas, simples, limpias y producidas con menos esfuerzo. 12] Las
diferencias entre lo grande y lo medio se acercan a un orden de magnitud.

Un poco de retrospección muestra que aunque muchos sistemas de software buenos


y útiles han sido diseñados por comités y construidos como parte de proyectos
multiparte, aquellos sistemas de software que han entusiasmado a los apasionados
son aquellos que son producto de una o varias mentes de diseño, grandes
diseñadores. Considere Unix, APL, Pascal, Modula, la interfaz Smalltalk, incluso
Fortran; y compárelos con Cobol, PL/I, Algol, MVS/370 y MS-DOS. (Ver Tabla 1.)

Por lo tanto, aunque apoyo firmemente los esfuerzos de transferencia de tecnología


y desarrollo curricular actualmente en curso, creo que el esfuerzo más importante
que podemos realizar es desarrollar maneras de hacer crecer a los grandes
diseñadores.

Ninguna organización de software puede ignorar este desafío. Los buenos gerentes,
por escasos que sean, no son más escasos que los buenos diseñadores. Los grandes
diseñadores y los grandes managers son muy raros. La mayoría de las
organizaciones invierten un esfuerzo considerable en encontrar y cultivar las
perspectivas de gestión; no conozco a nadie que se esfuerce por igual en encontrar y
desarrollar a los grandes diseñadores de los que la excelencia técnica de los
productos dependerá en última instancia.

Table 1. Exciting Vs. Useful But Unexciting Software Products.


Exciting Products
Yes No
Unix Cobol
APL PL/I
Pascal Algol
Modula MVS/370
Smalltalk MS-DOS
Fortran
Mi primera propuesta es que cada organización de software debe determinar y
proclamar que los grandes diseñadores son tan importantes para su éxito como lo
son los grandes gerentes, y que se puede esperar que sean igualmente nutridos y
recompensados. No sólo el salario, sino también los requisitos de reconocimiento -
tamaño de la oficina, mobiliario, equipo técnico personal, fondos para viajes y
apoyo del personal- deben ser completamente equivalentes.

¿Cómo hacer crecer a los grandes diseñadores? El espacio no permite una discusión
larga, pero algunos pasos son obvios:

 Identificar sistemáticamente a los mejores diseñadores lo antes posible. Los


mejores a menudo no son los más experimentados.
 Asignar un mentor de carrera para que sea responsable del desarrollo del
prospecto, y mantener cuidadosamente un expediente de carrera.
 Elaborar y mantener un plan de desarrollo de carrera para cada prospecto,
incluyendo aprendizajes cuidadosamente seleccionados con los mejores
diseñadores, episodios de educación formal avanzada y cursos cortos, todos
mezclados con tareas de diseño individual y liderazgo técnico.
 Proporcionar oportunidades para que los diseñadores en crecimiento
interactúen y se estimulen entre sí.

También podría gustarte