Sie sind auf Seite 1von 16

Sin bala de plata: esencia y accidentes de la ingeniería de software

De todos los monstruos que llenan las pesadillas de nuestro folclore, ninguno aterroriza
más que a los hombres lobo, porque se transforman inesperadamente de lo familiar en
horrores. Para estos, uno busca balas de plata que pueden colocarlas mágicamente para
descansar.
El proyecto de software familiar, al menos como lo ve el gerente no técnico, tiene algo de
este carácter; generalmente es inocente y directo, pero es capaz de convertirse en un
monstruo de horarios perdidos, presupuestos destruidos y productos defectuosos. Así que
escuchamos gritos desesperados por una bala de plata, algo para hacer que los costos de
software caigan tan rápido como lo hacen los costos de hardware de la computadora.
Pero, cuando miramos hacia el horizonte de una década, no vemos una bala de plata. No
existe un desarrollo único, ya sea en la tecnología o en la técnica de gestión, que por sí
solo promete una mejora de un orden de magnitud en la productividad, en la
confiabilidad, en la simplicidad. En este artículo, intentaré mostrar por qué, examinando
tanto la naturaleza del problema de software como las propiedades de las viñetas
propuestas.
El escepticismo no es pesimismo, sin embargo. Aunque no vemos avances sorprendentes,
y de hecho, creo que eso es inconsistente con la naturaleza del software, están en marcha
muchas innovaciones alentadoras. Un esfuerzo disciplinado y consistente para desarrollar,
propagar y explotar estas innovaciones debería de hecho producir una mejora en el orden
de magnitud. No hay camino real, pero hay un camino.
El primer paso hacia el manejo de la enfermedad fue la sustitución de las teorías
demoníacas y las teorías de los humores por la teoría de los gérmenes. Ese mismo paso, el
comienzo de la esperanza, en sí mismo desvaneció 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 una atención persistente e inquebrantable a una
disciplina de limpieza. Lo mismo ocurre con la ingeniería de software hoy en día.

¿Tiene que ser difícil? - Dificultades esenciales

No solo no hay balas de plata a la vista, la propia naturaleza del software hace que sea
improbable que exista - ningún invento que haga por la productividad, confiabilidad y
simplicidad del software que hicieron los componentes electrónicos, transistores e
integración a gran escala para hardware de computadora No podemos esperar ver alguna
vez ganancias dobles 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
obtener beneficios en un rendimiento mejorado o en costos reducidos. Estas ganancias
fluyen de la transformación de la fabricación de computadoras de una industria de
ensamblaje a una industria de procesos.
En segundo lugar, para ver qué ritmo de progreso 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 asisten a su producción pero que no son inherentes.
La esencia de una entidad de software es una construcción de conceptos entrelazados:
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. Sin embargo, es muy preciso y muy
detallado.
Creo que la parte más difícil de la construcción de software es la especificación, el diseño y
las pruebas de esta construcción conceptual, no el trabajo de representarla y probar la
fidelidad de la representación. Aún así cometemos errores de sintaxis, para estar seguros;
pero son difusos en comparación con los errores conceptuales en la mayoría de los
sistemas.
Si esto es cierto, la creación de software siempre será difícil. Inherentemente no hay una
bala de plata.
Consideremos las propiedades inherentes de esta esencia irreductible de los sistemas de
software modernos: complejidad, conformidad, capacidad de cambio e invisibilidad.

Complejidad. Las entidades de software son más complejas para su tamaño que quizás
cualquier otra construcción humana porque no hay dos partes iguales (al menos por encima
del nivel de declaración). Si lo son, convertimos las dos partes similares en una subrutina,
abierta o cerrada. A este respecto, los sistemas de software difieren profundamente de las
computadoras, los edificios o los automóviles, donde abundan los elementos repetidos.
Las computadoras digitales son más complejas que la mayoría de las cosas que las personas
construyen: tienen un gran número de estados. Esto hace que concebir, describir y
probarlos sea difícil. Los sistemas de software tienen órdenes de magnitud más estados que
las computadoras.
Del mismo modo, una ampliación de una entidad de software no es simplemente una
repetición de los mismos elementos en tamaños más grandes, es necesariamente un
aumento en el número de elementos diferentes. En la mayoría de los casos, los elementos
interactúan entre sí de forma no lineal, y la complejidad del todo 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
construyendo modelos simplificados de complejos
fenómenos, derivar propiedades de los modelos y verificar esas propiedades por
experimento. 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 se derivan de
esta complejidad esencial y sus aumentos no lineales con el tamaño. De la complejidad
surge la dificultad de comunicación entre los miembros del equipo, lo que conduce a fallas
en los productos, a sobrecostos, a retrasos en el cronograma. De la complejidad surge la
dificultad de enumerar, y mucho menos entender, todos los estados posibles del programa,
y de ahí viene la falta de fiabilidad. De la complejidad de la función surge la dificultad de
invocar la función, lo que hace que los programas sean difíciles de usar. De la complejidad
de la estructura surge 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 solo problemas técnicos, sino también problemas de gestión provienen de la
complejidad. Hace la descripción general difícil, impidiendo así la integridad conceptual.
Hace que sea difícil encontrar y controlar todos los cabos sueltos. Crea la tremenda carga
de aprendizaje y comprensión que hace que la rotación de personal sea un desastre.

Conformidad. Las personas con software no están solas al enfrentar la complejidad. La física
se ocupa de objetos terriblemente complejos, incluso en el nivel de partículas
"fundamentales". El físico se esfuerza, sin embargo, en una fe firme de que existen
principios unificadores que se pueden encontrar, ya sea en los quarks o en las teorías del
campo unificado. 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 la complejidad arbitraria, forzada sin rima o razón por las muchas instituciones y sistemas
humanos a los que deben ajustarse sus interfaces. Estos difieren de la interfaz a la interfaz,
y de vez en cuando, no por necesidad, sino solo porque fueron diseñados por diferentes
personas, en lugar de por Dios.
En muchos casos, el software debe ajustarse porque es la llegada más reciente a la escena.
En otros, debe ajustarse porque se percibe como el más conformable. Pero en todos los
casos, mucha complejidad proviene de la conformación a otras interfaces; esta complejidad
no se puede simplificar mediante ningún rediseño del software solo.

Posibilidad de cambiar. La entidad de software está constantemente sujeta a presiones de


cambio. Por supuesto, también lo son los edificios, autos, computadoras. Pero las cosas
manufacturadas son cambiadas con poca frecuencia después de la fabricación; son
reemplazados por modelos posteriores, o los cambios esenciales se incorporan en copias
de números de serie posteriores del mismo diseño básico. Las retrollamadas automotrices
son bastante infrecuentes; los cambios de campo de las computadoras algo menos. Ambos
son mucho menos frecuentes que las modificaciones al software de campo.
En parte, esto es así porque el software de un sistema incorpora su función, y la función es
la que más siente las presiones del cambio. En parte, se debe a que el software se puede
cambiar más fácilmente: es algo puramente mental, infinitamente maleable. De hecho, los
edificios se cambian, pero los altos costos del cambio,
entendido por todos, sirven para amortiguar los caprichos de los cambiadores.
Todo el software exitoso se cambia. Dos procesos están en el trabajo. En primer lugar, como
se considera que un producto de software es útil, las personas lo prueban en casos nuevos
al margen o más allá del dominio original. Las presiones para la función extendida provienen
principalmente de los usuarios 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 normal del vehículo de
la máquina para el cual se escribió por primera vez. Si no son computadoras nuevas,
aparecen al menos discos nuevos, pantallas nuevas, impresoras nuevas; y el software debe
conformarse 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áquinas. Todo esto cambia continuamente y sus cambios
fuerzan inexorablemente el cambio sobre el producto de software.

Invisibilidad. El software es invisible y no se puede visualizar. Las abstracciones geométricas


son herramientas poderosas. El plano de un edificio ayuda tanto al arquitecto como al
cliente a evaluar espacios, flujos de tráfico y vistas.
Las contradicciones y omisiones se vuelven obvias. Los dibujos a escala de piezas mecánicas
y modelos de moléculas en forma de bastón, aunque abstracciones, tienen el mismo
propósito. Una realidad geométrica se captura en una abstracción geométrica.
La realidad del software no está intrínsecamente 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 estructurar el diagrama del software, encontramos que no constituye
uno, sino varios gráficos dirigidos generales superpuestos uno sobre el otro. Los diversos
gráficos pueden representar el flujo de control, el flujo de datos, patrones de dependencia,
secuencia de tiempo, relaciones de nombre-espacio. Estos gráficos generalmente no son
planos, mucho menos jerárquicos. De hecho, una de las formas de establecer un control
conceptual sobre dicha estructura es hacer cumplir el corte del enlace hasta que uno o más
de los gráficos se vuelvan jerárquicos.
A pesar del progreso en la restricción y simplificación de las estructuras del software, siguen
inherentemente indesviables, y por lo tanto no permiten que la mente use algunas de sus
herramientas conceptuales más poderosas. Esta falta no solo impide el proceso de diseño
dentro de una sola mente, sino que obstaculiza seriamente la comunicación entre las
mentes.

Avances pasados han resuelto 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 atacó una dificultad mayor diferente
en la construcción de software, pero que esas dificultades han sido accidentales, no
esenciales, dificultades. También podemos ver los límites naturales a la extrapolación de
cada ataque.

Idiomas de alto nivel. Sin duda, 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 atribuyen ese desarrollo al menos a un
factor de cinco en productividad, y con los consiguientes avances en confiabilidad,
simplicidad e inteligibilidad.
¿Qué logra un lenguaje de alto nivel? Libera 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 de máquina concreta se refiere a
bits, registros, condiciones, ramas, canales, discos, etc. En la medida en que el lenguaje de
alto nivel incorpore los constructos que uno quiere en el programa abstracto y evita todos
los más bajos, elimina un nivel completo de complejidad que nunca fue inherente al
programa en absoluto.
Lo más que puede hacer un lenguaje de alto nivel es proporcionar todos los constructos 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á
aumentando constantemente, 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
dominio de la herramienta que aumenta, no reduce, la tarea intelectual del usuario que
rara vez utiliza los constructos esotéricos.

Tiempo compartido. El tiempo compartido trajo una mejora importante en la productividad


de los programadores y en la calidad de sus productos, aunque no tan grande como la que
traen los lenguajes de alto nivel.
El tiempo compartido ataca una dificultad bastante diferente. El tiempo compartido
preserva la inmediatez y, por lo tanto, permite mantener una visión general de la
complejidad. El lento cambio de programación por lotes significa que uno inevitablemente
olvida las minucias, si no el verdadero impulso, de lo que uno pensaba cuando dejaba de
hacerlo.
programación y pidió compilación y ejecución. Esta interrupción es costosa en el tiempo, ya
que uno debe actualizar la memoria. El efecto más serio puede ser la disminución de la
comprensión de todo lo que está sucediendo en un sistema complejo.
La respuesta lenta, al igual que las complejidades del lenguaje de máquina, es una dificultad
accidental en lugar de una dificultad 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. Como este tiempo de
respuesta va a cero, en algún momento pasa el umbral humano de perceptibilidad,
alrededor de 100 milisegundos. Más allá de ese umbral, no se esperan beneficios.

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


programación integrados en general, parecen haber mejorado la productividad por factores
integrales.
¿Por qué?
Atacan las dificultades accidentales que resultan del uso de programas individuales, al
proporcionar bibliotecas integradas, formatos de archivos unificados y tuberías y filtros.
Como resultado, las estructuras conceptuales que, en principio, siempre podrían llamar,
alimentar y usar entre sí, de hecho pueden hacerlo fácilmente en la práctica.
Este avance a su vez estimuló el desarrollo de bancos de herramientas completos, ya que
cada nueva herramienta se podría aplicar a cualquier programa que usara formatos
estándar.
Debido a estos éxitos, los entornos son el tema de gran parte de la investigación actual de
ingeniería de software. Vemos sus promesas y limitaciones en la siguiente sección.

Hopes for the Silver

Ahora consideremos los desarrollos técnicos que con mayor frecuencia se presentan como
potenciales balas de plata. ¿Qué problemas abordan: los problemas de la esencia o las
dificultades accidentales restantes? ¿Ofrecen avances revolucionarios o incrementales?

Ada y otros avances de lenguaje de alto nivel. Uno de los desarrollos recientes más
promocionados es Ada, un lenguaje de alto nivel de propósito general de la década de 1980.
Ada no solo refleja las mejoras evolutivas en los conceptos de lenguaje, sino que incorpora
características para alentar el diseño moderno y la modularización.
Quizás la filosofía Ada es más un avance que el lenguaje Ada, ya que es la filosofía de la
modularización, de los tipos de datos abstractos, de la estructuración jerárquica. Ada es
demasiado rica, un resultado natural del proceso por el cual se establecieron los requisitos
en su diseño. Eso no es fatal, para el trabajo subconjunto
los vocabularios pueden resolver el problema de aprendizaje, y los avances de hardware
nos darán los MIPS baratos para pagar los costos de compilación. Avanzar en la
estructuración de los sistemas de software es de hecho un muy buen uso para el aumento
de MIPS que nuestros dólares comprarán. Los sistemas operativos, denunciados en voz alta
en la década de 1960 para su memoria
y los costos del ciclo, han demostrado ser una excelente forma de utilizar algunos de los
MIPS y bytes de memoria baratos del aumento de hardware pasado.
Sin embargo, Ada no probará ser la bala de plata que mata al monstruo de la productividad
del software. Después de todo, es solo otro lenguaje de alto nivel, y la mayor recompensa
de tales idiomas provino de la primera transición: la transición de las complejidades
accidentales de la máquina a la más abstracta.
declaración de soluciones paso a paso. Una vez que esos accidentes hayan sido eliminados,
los restantes serán más pequeños, y la recompensa de su eliminación seguramente será
menor.
Predigo que dentro de una década, cuando se evalúe la efectividad de Ada, se verá que ha
hecho una diferencia sustancial, pero no debido a ninguna característica particular del
lenguaje, ni a la combinación de todas ellas. Tampoco los nuevos entornos de Ada probarán
ser la causa de las mejoras.
La mayor contribución de Ada consistirá en cambiar a los programadores de capacitación
ocasionales en técnicas modernas de diseño de software.

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


para la programación orientada a objetos que para cualquiera de las otras modas técnicas
del día. Yo estoy entre ellos. Mark Sherman, de Dartmouth, anota en CSnet News que hay
que tener cuidado de distinguir dos ideas separadas que tienen 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 definirse por un nombre, un conjunto de valores correctos y un
conjunto de operaciones adecuadas en lugar de su estructura de almacenamiento, que
debe estar oculta. 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 interfaces generales
que pueden perfeccionarse proporcionando tipos subordinados. Los dos conceptos son
ortogonales_una puede tener jerarquías sin ocultarse y ocultarse sin jerarquías. Ambos
conceptos representan avances reales en el arte de
software de construcción.
Cada uno elimina otra dificultad accidental del proceso, lo que permite al diseñador
expresar la esencia del diseño sin tener que expresar grandes cantidades de material
sintáctico que no agrega contenido de información. 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 diseño de orden superior.
Sin embargo, tales avances no pueden hacer más que eliminar todas las dificultades
accidentales de la expresión del diseño. La complejidad del diseño en sí es esencial, y tales
ataques no cambian nada en eso. La programación orientada a objetos puede generar una
ganancia de orden de magnitud solo si el matorral de especificación de tipo innecesario aún
en nuestro lenguaje de programación es en sí mismo nueve décimas partes del trabajo
involucrado en el diseño de un producto de programa. Lo dudo.

Inteligencia artificial. Muchas personas esperan avances en la inteligencia artificial para


proporcionar el avance revolucionario que dará aumentos de orden de magnitud en la
productividad y calidad del software. [3] Yo no. Para ver por qué, debemos diseccionar lo
que se entiende por "inteligencia artificial".
D.L. Parnas ha aclarado el caos terminológico: [4]
Dos definiciones bastante diferentes de AI son de uso común en la actualidad. AI-1: El uso
de computadoras para resolver problemas que antes solo podían resolverse aplicando
inteligencia humana. Al2: el uso de un conjunto específico de técnicas de programación
conocido como programación heurística o basada en reglas. En este enfoque, se estudian
los expertos humanos para determinar qué heurística o reglas empíricas usan para resolver
problemas ... El programa está diseñado para resolver un problema de la forma en que los
humanos parecen resolverlo.
La primera definición tiene un significado deslizante ... Algo puede encajar en la definición
de Al-1 de hoy pero, una vez que veamos cómo funciona el programa y comprendamos el
problema, no lo consideraremos más como Al. Desafortunadamente No puedo identificar
un cuerpo de tecnología que sea exclusivo de este campo ... La mayor parte del trabajo es
específico de un problema, y se requiere algo de abstracción o creatividad para ver cómo
transferirlo.
Estoy completamente 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 los sistemas
expertos. Me cuesta ver cómo el reconocimiento de imágenes, por ejemplo, hará una
diferencia apreciable en la práctica de programación. El mismo problema es cierto para el
reconocimiento de voz. 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 inteligencia artificial, y la más
ampliamente aplicada, es la tecnología para construir sistemas expertos. Muchos científicos
de software están trabajando arduamente para aplicar 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 datos de entrada y suposiciones, explora las inferencias derivables
de la base de reglas, arroja conclusiones y consejos, y ofrece explicar sus resultados
volviendo sobre sus razonamientos para el usuario . Los motores de inferencia
generalmente pueden tratar con datos y reglas difusos o probabilísticos, además de la lógica
puramente determinista.
Dichos sistemas ofrecen algunas ventajas claras sobre los algoritmos programados
diseñados para llegar a las mismas soluciones a los mismos problemas:

 La tecnología de motores 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 cambiables de los materiales peculiares 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 aplicación en sí misma.
El poder de tales sistemas no proviene de mecanismos de inferencia cada vez más
sofisticados 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 tarea de ingeniería del software? En muchos
sentidos: dichos sistemas pueden sugerir reglas de interfaz, aconsejar sobre estrategias de
prueba, recordar frecuencias de tipo error y ofrecer sugerencias de optimización.
Considere un asesor de prueba imaginario, por ejemplo. En su forma más rudimentaria, el
sistema de diagnóstico experto es muy parecido a una lista de verificación de un piloto,
simplemente enumerando sugerencias sobre las posibles causas de la dificultad. A medida
que se incorpora más y más estructura del sistema en la base de reglas, y cuando la base de
reglas toma una cuenta más sofisticada de los síntomas de problemas reportados, el asesor
de pruebas se vuelve cada vez más particular en las hipótesis que genera y las pruebas que
recomienda. Tal sistema experto puede partir más radicalmente de los convencionales en
que su base de reglas debería modularse jerárquicamente de la misma manera que el
producto de software correspondiente, de modo que como el producto se modifique
modularmente, la base de regla de diagnóstico pueda modularse como bien.
El trabajo requerido para generar las reglas de diagnóstico es un trabajo que tendría que
hacerse de todos modos al generar el conjunto de casos de prueba para los módulos y para
el sistema. Si se hace de una manera adecuada general, con una estructura uniforme de
reglas y un buen motor de inferencia disponible, en realidad puede reducir el trabajo total
de generación de casos de prueba de arranque, y ayuda con el mantenimiento de por vida
y las pruebas de modificación. De la misma manera, uno puede postular a otros asesores,
probablemente muchos y probablemente simples, para las otras partes de la tarea de
construcción de software.
Muchas dificultades se interponen en el camino de la pronta realización de asesores de
sistemas expertos útiles para el desarrollador del programa. Una parte crucial de nuestro
escenario imaginario es el desarrollo de formas fáciles de pasar de la especificación de la
estructura del programa a 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 adquisición de conocimiento:
encontrar expertos claros y 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 requisito
previo esencial para construir un sistema experto es tener un experto.
La contribución más poderosa de los sistemas expertos seguramente será poner al servicio
del programador inexperto la experiencia y la sabiduría acumulada de los mejores
programadores. Esta no es una pequeña contribución. 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. Una herramienta que disemine buenas prácticas
sería importante.

Programación "automática". Durante casi 40 años, las personas han estado anticipando y
escribiendo sobre "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 hoy escriben como si esperaran que esta tecnología proporcionara el siguiente
avance. [5]
Parnas [4] implica que el término se usa para el glamour, no para el contenido semántico,
afirmando,
 En resumen, la programación automática siempre ha sido un eufemismo para
programar con un lenguaje de nivel superior al que actualmente estaba disponible
para el programador.

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


problema, cuya especificación debe ser dada.
Uno puede encontrar excepciones. La técnica de generar generadores es muy poderosa, y
se usa de forma rutinaria para obtener una buena ventaja en los programas de clasificación.
Algunos sistemas para integrar ecuaciones diferenciales también han permitido la
especificación directa del problema, y los sistemas han evaluado los parámetros, elegidos
de una biblioteca de métodos de solución, y generado los programas.
Estas aplicaciones tienen propiedades muy favorables:
 Los problemas se caracterizan fácilmente por relativamente pocos parámetros.
 Existen muchos métodos conocidos de solución para proporcionar una biblioteca de
alternativas.
 El análisis exhaustivo ha llevado a reglas explícitas para seleccionar técnicas de
solución, dados los parámetros del problema.

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

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


ingeniería de software es la programación gráfica o visual: la aplicación de gráficos por
computadora al diseño de software. [6, 7] A veces, la promesa que ofrece este enfoque se
postula por analogía con el diseño de chips VLSI, en el que los gráficos por computadora
desempeñan un papel tan fructífero. A veces, el teórico justifica el enfoque al considerar
los diagramas de flujo como el medio ideal de diseño de programas y al proporcionar
instalaciones potentes para construirlos.
Nada aún convincente, ni mucho menos emocionante, ha surgido de tales esfuerzos. Estoy
convencido de que nada lo hará.
En primer lugar, como he argumentado en otro lugar [8], el diagrama de flujo es una
abstracción muy pobre de la estructura del software. De hecho, se ve mejor como Burks,
von Neumann y el intento de Goldstine de proporcionar un lenguaje de control de alto nivel
que se necesita desesperadamente para su computadora propuesta. En la lamentable,
multipágina, forma de cuadro de conexión a la que se ha elaborado hoy el diagrama de flujo,
se ha demostrado que es 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 son demasiado pequeñas, en píxeles, para mostrar
tanto el alcance como la resolución de cualquier diagrama de software detallado. La
llamada "metáfora de escritorio" de la estación de trabajo de hoy en día es una metáfora
del "asiento del avión". Cualquiera que haya barajado una vuelta llena de papeles mientras
está sentado entre dos pasajeros corpulentos reconocerá la diferencia: uno puede ver muy
pocas cosas a la vez. El escritorio real brinda una visión general y acceso aleatorio a una
veintena de páginas. Además, cuando los ataques de creatividad son fuertes, se ha sabido
que más de un programador o escritor abandonó el escritorio para obtener un piso más
espacioso. La tecnología de hardware tendrá que avanzar considerablemente antes de que
el alcance de nuestros ámbitos sea suficiente para la tarea de diseño del software.
Más fundamentalmente, como he argumentado anteriormente, el software es muy difícil
de visualizar. Ya sea que un diagrama controle el flujo, anidamiento de alcance variable,
referencias cruzadas variables, flujo de datos, estructuras de datos jerárquicos, o lo que sea,
uno solo siente una dimensión del elefante de software intrincadamente entrelazado. Si
uno superpone todos los diagramas generados por las muchas vistas relevantes, es difícil
extraer una visión general global. La analogía de VLSI es fundamentalmente engañosa: un
diseño de chip es una descripción bidimensional estratificada cuya geometría refleja su
realización en 3 espacios. Un sistema de software no lo es.
Verificación del programa. Gran parte del esfuerzo en la programación moderna entra en
las pruebas y la reparación de errores. ¿Hay quizás una solución mágica para eliminar los
errores en la fuente, en la fase de diseño del sistema? ¿Se pueden mejorar radicalmente
tanto la productividad como la fiabilidad del producto siguiendo la estrategia
profundamente diferente de probar correctamente los diseños antes de que se aplique el
inmenso esfuerzo de implementarlos y probarlos?
No creo que encontremos la magia de la productividad aquí. La verificación del programa
es un concepto muy poderoso, y será muy importante para cosas como núcleos seguros del
sistema operativo. La tecnología no promete, sin embargo, ahorrar mano de obra. Las
verificaciones son tanto trabajo que solo se han verificado algunos programas sustanciales.
La verificación del programa no significa programas a prueba de errores. Aquí tampoco hay
magia. Las pruebas matemáticas también pueden ser defectuosas. Entonces, 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 solo 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 la
construcción de un programa es, de hecho, la depuración de la especificación.

Ambientes y herramientas. ¿Cuánto más se puede esperar de las investigaciones en


explosión en mejores entornos de programación? La reacción instintiva de uno es que los
problemas de gran rentabilidad (sistemas de archivos jerárquicos, formatos de archivo
uniformes para hacer posible las interfaces de programa uniformes y herramientas
generalizadas) fueron los primeros atacados y se resolvieron. Los editores inteligentes
específicos del lenguaje son desarrollos que aún no se utilizan ampliamente en la práctica,
pero lo máximo que prometen es la ausencia de errores sintácticos y errores semánticos
simples.
Tal vez la mayor ganancia de los entornos de programación sea la utilización de sistemas de
bases de datos integrados para realizar un seguimiento de la gran cantidad de detalles que
el programador individual debe recordar con precisión y mantener actualizados para un
grupo de colaboradores en un solo sistema.
Sin duda, este trabajo vale la pena, y seguramente dará algunos frutos tanto en
productividad como en fiabilidad. Pero por su propia naturaleza, el regreso de ahora en
adelante debe ser marginal.

Estaciones de trabajo. ¿Qué ganancias se esperan para el arte del software del aumento
cierto y rápido en la capacidad de potencia y memoria de la estación de trabajo individual?
Bueno, ¿cuántos MIPS uno puede usar de forma fructífera? La composición y edición de
programas y documentos es totalmente compatible con las velocidades actuales. La
compilación podría ser un estímulo, pero un factor de 10 en la velocidad de la máquina
seguramente dejaría al pensamiento como la actividad dominante en el día del
programador. De hecho, parece ser así ahora.
Estaciones de trabajo más potentes que seguramente daremos la bienvenida. Mejoras
mágicas de ellos que no podemos esperar.
Ataques prometedores en la esencia conceptual

Aunque ningún adelanto tecnológico promete dar el tipo de resultados mágicos con los que
estamos tan familiarizados en el área de hardware, existe tanto una gran cantidad de
trabajo bueno que está ocurriendo ahora, como la promesa de un progreso constante,
aunque no espectacular.
Todos los ataques tecnológicos a 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 ahora ocupan la mayor parte del
tiempo, entonces ninguna cantidad de actividad en los componentes de la tarea que sea
meramente 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 versus construir. La solución más radical posible para construir software no es
construirlo en absoluto.
Cada día es más fácil, ya que cada vez más proveedores ofrecen más y mejores productos
de software para una vertiginosa variedad de aplicaciones. Mientras que los ingenieros de
software hemos trabajado en la metodología de producción, la revolución de la
computadora personal ha creado no uno, sino muchos mercados masivos para software.
Cada puesto de periódicos tiene revistas mensuales, que clasifican por tipo de máquina,
publicitan y revisan docenas de productos a precios desde unos pocos dólares hasta unos
pocos cientos de dólares. Fuentes más especializadas ofrecen productos muy potentes para
la estación de trabajo y otros mercados de Unix. Incluso las herramientas de software y los
entornos se pueden comprar de forma inmediata. En otro lugar, propuse un mercado para
módulos individuales. [9]
Cualquier producto de este tipo es más barato de comprar que construir de nuevo. Incluso
con un costo de cien mil dólares, una pieza de software adquirida cuesta tan solo como un
programa en un año. ¡Y la entrega es inmediata! Inmediatamente al menos para productos
que realmente existen, productos cuyo desarrollador puede referir productos a un usuario
feliz. Además, tales productos tienden a estar mucho mejor documentados y mejor
conservados que el software nacional.
El desarrollo del mercado masivo es, creo, 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 incluso entre unos pocos usuarios reduce
radicalmente el costo por usuario. Otra forma 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 usar un paquete estándar
disponible para realizar mi tarea? Algo sorprendente ha sucedido aquí. Durante las décadas
de 1950 y 1960, el estudio tras otro demostró que los usuarios no usarían paquetes
comerciales para nómina, control de inventario, cuentas por cobrar, etc. Los requisitos eran
demasiado especializados, la variación caso por caso era demasiado alta. Durante la década
de 1980, encontramos tales paquetes de gran demanda y uso generalizado. ¿Que ha
cambiado?
No los paquetes, realmente. Pueden ser algo más generalizados y algo más personalizables
que antes, pero no mucho. No las aplicaciones, tampoco. En todo caso, las necesidades
comerciales y científicas de hoy en día son más diversas y complicadas que las de hace 20
años.
El gran cambio ha estado en la relación costo / hardware del software. En 1960, el
comprador de una máquina de dos millones de dólares sintió que podía pagar $ 250,000
más por un programa de nómina personalizado, que se deslizaba fácilmente y sin
interrupciones en el entorno social hostil a la computadora. Hoy en día, el comprador de
una máquina de oficina de $ 50,000 no puede permitirse un programa personalizado de
nómina, 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 normal.
Existen 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 tan tardías en aparecer, se prestan a innumerables usos, algunos bastante
poco ortodoxos. Los artículos e incluso libros abundan 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 realizan rutinariamente con estas herramientas.
Muchos usuarios ahora operan sus propias computadoras día tras día en varias aplicaciones
sin siquiera escribir un programa. De hecho, muchos de estos usuarios no pueden escribir
nuevos programas para sus máquinas, pero sin embargo son expertos en resolver nuevos
problemas con ellos.
Creo que la estrategia de productividad de software más poderosa para muchas
organizaciones hoy en día es equipar a los trabajadores intelectuales ingenuos que están en
la línea de fuego con computadoras personales y buenos programas generalizados de
escritura, dibujo, archivo y hoja de cálculo y luego soltarlos . La misma estrategia, llevada a
cabo con paquetes matemáticos y estadísticos generalizados y algunas capacidades de
programación simples, también funcionará para cientos de científicos de laboratorio.

Refinamiento de requisitos 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, incluidas todas
las interfaces para personas, máquinas y otros sistemas de software. Ninguna otra parte del
trabajo daña el sistema resultante si se hace mal. Ninguna otra parte es más difícil de
rectificar más tarde.
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. Porque la verdad
es que el cliente no sabe lo que quiere. El cliente generalmente no sabe qué preguntas
deben responderse, y casi nunca ha pensado en el problema en los detalles necesarios para
la especificación. Incluso la respuesta simple: "Hacer que el nuevo sistema de software
funcione como nuestro antiguo sistema manual de procesamiento de información" es de
hecho demasiado simple. Uno nunca quiere exactamente eso. Los sistemas de software
complejos son, además, cosas que actúan, se mueven, funcionan. La dinámica de esa acción
es difícil de imaginar. Por lo tanto, al planificar cualquier actividad de diseño de software,
es necesario permitir una extensa iteración entre el cliente y el diseñador como parte de la
definición del sistema.
Daría un paso más 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 actuales más prometedores y que ataca la
esencia, no los accidentes, del problema del software, es el desarrollo de enfoques y
herramientas para el prototipado rápido de sistemas, ya que la creación de prototipos
forma parte de la especificación iterativa de requisitos.
Un prototipo de sistema de software es aquel que simula las interfaces importantes y realiza
las funciones principales del sistema previsto, sin estar necesariamente sujeto a las mismas
limitaciones de velocidad, tamaño o costo del hardware. Los prototipos generalmente
realizan las tareas principales de la aplicación, pero no intentan manejar las tareas
excepcionales, responden correctamente a las entradas no válidas o cancelan limpiamente.
El propósito del prototipo es hacer real la estructura conceptual especificada, de modo que
el cliente pueda probarla en cuanto a consistencia y usabilidad.
Gran parte del procedimiento de adquisición de software actual se basa en la suposición de
que uno puede especificar un sistema satisfactorio por adelantado, obtener ofertas para su
construcción, hacer que se construya 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 pueden corregirse sin una revisión fundamental: revisión que
permite el desarrollo iterativo y la especificación de prototipos y productos.
Desarrollo incremental: desarrollar, no compilar, 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 instante, amplió mi visión completa del
proceso de software. El cambio de metáfora fue poderoso y preciso. Hoy entendemos
cómo, al igual que otros procesos de construcción, la construcción de software, y usamos
libremente 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 son demasiado complicadas para
ser especificadas con precisión de antemano, y demasiado complejas para ser construidas
sin fallas, entonces debemos adoptar un enfoque radicalmente diferente.
Volteemos la naturaleza y estudiemos la complejidad de los seres vivos, en lugar de solo las
obras muertas del hombre. Aquí encontramos constructos cuyas complejidades nos
estremecen de asombro. Solo el cerebro es intrincado más allá del mapeo, poderoso más
allá de la imitación, rico en diversidad, autoprotector y autorenovable. El secreto es que se
cultiva, no se construye.
Entonces debe ser con nuestros sistemas de software. Hace algunos años, Harlan Mills
propuso que cualquier sistema de software debería crecer mediante el desarrollo
incremental. [10] Es decir, primero se debe hacer que el sistema se ejecute, incluso si no
sirve de nada, excepto llamar al conjunto adecuado de subprogramas ficticios. Luego, poco
a poco, debería completarse, con los subprogramas a su vez en desarrollo, en acciones o
llamadas a talones vacíos en el nivel siguiente.
He visto los resultados más espectaculares desde que comencé a instar esta técnica a los
creadores de proyectos en mi clase de Laboratorio de Ingeniería de Software. Nada en la
última década ha cambiado radicalmente mi propia práctica o su eficacia. El enfoque
requiere un diseño de arriba hacia abajo, ya que es un crecimiento descendente del
software. Permite un retroceso fácil. Se presta a prototipos tempranos. Cada función
adicional y nueva disposición para datos o circunstancias más complejas crece
orgánicamente de lo que ya existe.
Los efectos de la moral son sorprendentes. El entusiasmo salta cuando hay un sistema en
ejecución, incluso uno simple. Los esfuerzos se redoblan cuando aparece la primera imagen
de un nuevo sistema de software gráfico en la pantalla, incluso si solo es un rectángulo. Uno
siempre tiene, en cada etapa del proceso, un sistema en funcionamiento. Encuentro que
los equipos pueden hacer crecer entidades mucho más complejas en cuatro meses de lo
que pueden construir. Se pueden obtener los mismos beneficios en proyectos grandes que
en mis proyectos pequeños. [11]

Grandes diseñadores. La pregunta central sobre cómo mejorar los centros de arte de
software, como siempre, en las personas.
Podemos obtener buenos diseños siguiendo las buenas prácticas en lugar de las malas. Se
pueden enseñar buenas prácticas de diseño. Los programadores se encuentran entre la
parte más inteligente de la población, por lo que pueden aprender buenas prácticas. Por lo
tanto, un impulso importante en los Estados Unidos es promulgar buenas prácticas
modernas. Nuevos planes de estudios, nueva literatura, nuevas organizaciones como el
Instituto de Ingeniería de Software, todas han surgido para elevar el nivel de nuestra
práctica de pobre a bueno. Esto es completamente 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 buenos no
lo es. Los grandes diseños provienen de grandes diseñadores. La construcción de software
es un proceso creativo. La metodología de sonido puede potenciar y liberar la mente
creativa; no puede inflamar ni inspirar al borracho.
Las diferencias no son menores: son más bien como las diferencias entre Salieri y Mozart.
Estudio tras estudio muestra que los mejores diseñadores producen estructuras que son
más rápidas, más pequeñas, más simples, más limpias y se producen con menos esfuerzo.
[12] Las diferencias entre el gran y el promedio se aproximan a un orden de magnitud.
Una pequeña retrospección muestra que, aunque muchos sistemas de software finos y
útiles han sido diseñados por comités y construidos como parte de proyectos multiparte,
esos sistemas de software que han entusiasmado a apasionados fanáticos son aquellos que
son productos de una o pocas mentes de diseño, grandes diseñadores. Considere Unix, APL,
Pascal, Modula, la interfaz Smalltalk, incluso Fortran; y contrastarlos con Cobol, PL / I, Algol,
MVS / 370 y MS-DOS. (Ver la Tabla 1.)
Por lo tanto, aunque estoy totalmente de acuerdo con los esfuerzos de transferencia de
tecnología y desarrollo curricular que están en marcha, creo que el esfuerzo individual más
importante que podemos hacer es desarrollar formas 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. Grandes diseñadores y
grandes gerentes son muy raros. La mayoría de las organizaciones dedican un esfuerzo
considerable a encontrar y cultivar las perspectivas de gestión; No conozco a ninguno que
invierta el mismo esfuerzo en encontrar y desarrollar a los grandes diseñadores de quienes
dependerá la excelencia técnica de los productos.

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 espera que se los nutra y se los recompense. No solo el salario, sino las
gratificaciones de reconocimiento (tamaño de oficina, mobiliario, equipo técnico personal,
fondos de viaje, personal de apoyo) deben ser totalmente equivalentes.
¿Cómo hacer crecer a los grandes diseñadores? El espacio no permite una discusión larga,
pero algunos pasos son obvios:
 Identifique sistemáticamente a los mejores diseñadores lo antes posible. Los
mejores a menudo no son los más experimentados.
 Asigne un mentor de carrera para que sea responsable del desarrollo de la
perspectiva y guarde cuidadosamente un archivo de carrera.
 Diseñe y mantenga un plan de desarrollo profesional para cada cliente potencial,
que incluya pasantías cuidadosamente seleccionadas con los mejores diseñadores,
episodios de educación formal avanzada y cursos breves, todos ellos intercalados
con asignaciones de diseño único y liderazgo técnico.
 Brinde oportunidades para que los diseñadores en crecimiento interactúen y se
estimulen mutuamente.

Das könnte Ihnen auch gefallen