La Bala de Plata

La bala de plata Esencia y Accidentes de la Ingeniería de Software De todos los monstruos que llenan las pesadillas de n

Views 92 Downloads 6 File size 83KB

Report DMCA / Copyright

DOWNLOAD FILE

Recommend stories

Citation preview

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 incrementales?

restantes?

¿Ofrecen

avances

revolucionarios

o

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í.