Humildemente programador
Uno de los actores fundamentales para el pensar filosófico de DSN_XP es Edsger W. Dijkstra de quien se transcribe uno de sus artículos para entendimiento de nuestro planteamiento.
Programador (Codificador)
Como resultado de una larga secuencia de coincidencias, entré oficialmente a la profesión de programador la primera mañana de primavera de 1952 y, por lo que he podido rastrear, fui el primer holandés en hacerlo en mi país. En retrospectiva, lo más sorprendente fue la lentitud con la que, al menos en mi parte del mundo, surgió la profesión de la programación, una lentitud que ahora es difícil de creer. Pero agradezco dos vívidos recuerdos de ese período que establecen esa lentitud más allá de toda duda.
Después de haber programado durante unos tres años, tuve una discusión con A. van Wijngaarden, que entonces era mi jefe en el Centro Matemático de Ámsterdam, una discusión por la que le estaré agradecido mientras viva. El punto era que se suponía que debía estudiar física teórica en la Universidad de Leiden simultáneamente y como encontraba las dos actividades cada vez más difíciles de combinar, tuve que tomar una decisión, o dejar de programar y convertirme en un verdadero y respetable teórico. físico, o llevar mi estudio de física a una finalización formal solamente, con un mínimo de esfuerzo, y llegar a ser ....., ¿sí qué?
¿Un programador? ¿Pero era esa una profesión respetable? Porque después de todo ¿Qué era la programación? ¿Dónde estaba el sólido cuerpo de conocimientos que podría respaldarlo como una disciplina intelectualmente respetable?
Recuerdo muy vívidamente cómo envidiaba a mis colegas de hardware, quienes, cuando se les preguntó sobre su competencia profesional, al menos pudieron señalar que sabían todo sobre válvulas de vacío, amplificadores y demás, mientras que yo sentí que, al enfrentarme a esa pregunta, yo se quedaría con las manos vacías.
Lleno de recelo, llamé a la puerta de la oficina de van Wijngaarden, preguntándole si podía “hablar con él un momento”; cuando salí de su oficina varias horas después, era otra persona. Porque después de haber escuchado mis problemas con paciencia, estuvo de acuerdo en que hasta ese momento no había mucha disciplina de programación, pero luego pasó a explicar en voz baja que las computadoras automáticas llegaron para quedarse. que estábamos al principio y ¿no podría ser yo una de las personas llamadas a hacer de la programación una disciplina respetable en los próximos años?
Este fue un punto de inflexión en mi vida y completé formalmente mis estudios de física tan rápido como pude. Una moraleja de la historia anterior es, por supuesto, que debemos tener mucho cuidado cuando damos consejos a los más jóvenes; ¡a veces lo siguen!
Otros dos años más tarde, en 1957, me casé y los ritos matrimoniales holandeses requieren que declares tu profesión y yo dije que yo era programador. Pero las autoridades municipales de la ciudad de Ámsterdam no lo aceptaron alegando que no existía tal profesión. Y, lo crea o no, ¡pero bajo el título "profesión" mi acto matrimonial muestra la ridícula entrada "físico teórico"!
Hasta aquí la lentitud con la que vi emerger la profesión de programador en mi propio país. Desde entonces he visto más del mundo y tengo la impresión general de que en otros países, aparte de un posible cambio de fechas, el patrón de crecimiento ha sido muy similar.
Estructuras programáticas
Permítanme intentar capturar la situación de aquellos tiempos con un poco más de detalle, con la esperanza de comprender mejor la situación actual. Mientras continuamos con nuestro análisis, veremos cuántos malentendidos comunes sobre la verdadera naturaleza de la tarea de programación se remontan a ese pasado ahora lejano.
Las primeras computadoras electrónicas automáticas eran todas máquinas únicas de una sola copia y todas se encontraban en un entorno con el emocionante sabor de un laboratorio experimental. Una vez que la visión de la computadora automática estuvo ahí, su realización fue un tremendo desafío para la tecnología electrónica disponible en ese momento y una cosa es cierta: no podemos negar el coraje de los grupos que decidieron intentar construir un equipo tan fantástico.
En cuanto a piezas de equipo fantásticas, lo fueron: en retrospectiva, uno solo puede sorprenderse de que esas primeras máquinas funcionaran, al menos a veces. El problema abrumador era conseguir y mantener la máquina en funcionamiento. La preocupación por los aspectos físicos de la computación automática todavía se refleja en los nombres de las sociedades científicas más antiguas en el campo,
El codificador
¿Y el pobre programador? Bueno, a decir verdad: apenas se notó.
Por un lado, las primeras máquinas eran tan voluminosas que apenas se podían mover y, además, requerían un mantenimiento tan extenso que era bastante natural que el lugar donde la gente intentaba usar la máquina fuera el mismo laboratorio donde se había desarrollado la máquina.
En segundo lugar, su trabajo un tanto invisible carecía de glamour: se podía mostrar la máquina a los visitantes y eso era varios órdenes de magnitud más espectacular que algunas hojas de codificación.
Pero lo más importante de todo, el propio programador tenía una visión muy modesta de su propio trabajo: su trabajo se derivaba de toda la importancia de la existencia de esa maravillosa máquina. Como se trataba de una máquina única, sabía muy bien que sus programas solo tenían un significado local y también, como era claramente obvio que esta máquina tendría una vida útil limitada, sabía que, muy poco de su trabajo tendría un valor duradero.
Finalmente, existe otra circunstancia que influyó profundamente en la actitud del programador hacia su trabajo: por un lado, además de poco fiable, su máquina solía ser demasiado lenta y su memoria solía ser demasiado pequeña, es decir, se enfrentaba a una "rozadura de zapato", mientras que, por otro lado, su código de pedido generalmente algo extraño se adaptaría a las construcciones más inesperadas.
Y en aquellos días, muchos programadores inteligentes obtenían una inmensa satisfacción intelectual de los astutos trucos con los que se las ingeniaba para meter lo imposible en las limitaciones de su equipo, sabía que muy poco de su trabajo tendría un valor duradero.
Escuelas de diseño
Dos opiniones sobre la programación datan de esos días. Las menciono ahora, volveré a ellas más tarde. Una opinión era que un programador realmente competente debería tener una mentalidad de rompecabezas y ser muy aficionado a los trucos inteligentes; la otra opinión fue que la programación no era más que optimizar la eficiencia del proceso computacional, en una dirección u otra.
Esta última opinión fue el resultado de la circunstancia frecuente de que, de hecho, el equipo disponible era un dolorosa remordedura de zapato y en aquellos días uno se encontraba a menudo con la ingenua expectativa de que, una vez que se dispusiera de máquinas más potentes, la programación ya no sería un problema, porque entonces la lucha por llevar la máquina al límite ya no sería necesaria y de eso se trataba la programación, ¿no?
Pero en las décadas siguientes sucedió algo completamente diferente: se dispuso de máquinas más potentes, no solo en un orden de magnitud más potente, incluso varios órdenes de magnitud más potentes. Pero en lugar de encontrarnos en el estado de eterna felicidad de todos los problemas de programación resueltos, ¡nos encontramos hasta el cuello en la crisis del software! ¿Cómo?
Crisis del software debida al hardware
Hay una causa menor: en uno o dos aspectos, la maquinaria moderna es básicamente más difícil de manejar que la vieja. En primer lugar, tenemos las interrupciones de E / S, que ocurren en momentos impredecibles e irreproducibles; en comparación con la vieja máquina secuencial que pretendía ser un autómata completamente determinista, este ha sido un cambio dramático y las canas de muchos programadores de sistemas dan testimonio del hecho de que no debemos hablar a la ligera sobre los problemas lógicos creados por esa característica.
En segundo lugar, tenemos máquinas equipadas con almacenes multinivel, que nos presentan problemas de estrategia de gestión que, a pesar de la extensa literatura sobre el tema, siguen siendo bastante esquivos.
Hasta aquí la complicación añadida debido a los cambios estructurales de las máquinas reales.
Pero llamé a esto una causa menor; la causa principal es ... ¡que las máquinas se han vuelto varios órdenes de magnitud más poderosas! Para decirlo sin rodeos: mientras no habían máquinas, la programación no suponía ningún problema; cuando teníamos algunas computadoras débiles, la programación se convirtió en un problema leve y ahora tenemos computadoras gigantes, la programación se había convertido en un problema igualmente gigantesco.
En este sentido la industria electrónica no ha resuelto un solo problema, solo los ha creado, ha creado el problema del uso de sus productos. Para decirlo de otra manera: a medida que el poder de las máquinas disponibles creció en un factor de más de mil, la ambición de la sociedad por aplicar estas máquinas creció en proporción y fue el pobre programador quien encontró su trabajo en este campo explosivo de tensión entre fines y medios.
El aumento de potencia del hardware, junto con el aumento quizás aún más dramático de su confiabilidad, hicieron factibles soluciones con las que el programador no se había atrevido a soñar unos años antes. Y ahora, unos años después, él tuvo que soñar con ellas y, lo que es peor, ¡tuvo que transformar esos sueños en realidad! ¿Es de extrañar que nos encontremos en una crisis de software? No, ciertamente no, y como puede suponer, incluso se predijo con mucha anticipación; pero el problema con los profetas menores, por supuesto, es que sólo cinco años después se sabe realmente que tenían razón.
Luego, a mediados de los sesenta, sucedió algo terrible: aparecieron los ordenadores de la llamada tercera generación. La literatura oficial nos dice que su relación precio / rendimiento ha sido uno de los principales objetivos de diseño. Pero si toma como "rendimiento" el ciclo de trabajo de los diversos componentes de la máquina, poco le impedirá terminar con un diseño en el que la mayor parte de su objetivo de rendimiento se alcance mediante actividades internas de mantenimiento de dudosa necesidad. Y si su definición de precio es el precio a pagar por el hardware, poco le impedirá terminar con un diseño que es terriblemente difícil de programar: por ejemplo, el código de pedido puede ser tal que lo imponga, ya sea al programador o sobre el sistema, decisiones vinculantes tempranas que presentan conflictos que realmente no se pueden resolver.
Cuando se anunciaron estas máquinas y se conocieron sus especificaciones funcionales, algunos de nosotros debieron de ser bastante miserables; al menos yo lo estaba. Era razonable esperar que tales máquinas inundaran la comunidad informática y, por lo tanto, era aún más importante que su diseño fuera lo más sólido posible.
Pero el diseño contenía defectos tan graves que sentí que de un solo golpe el progreso de la informática se había retrasado al menos diez años: fue entonces cuando tuve la semana más negra de toda mi vida profesional.
Diseño de hardware e impacto en software
Quizás lo más triste ahora es que, incluso después de todos esos años de experiencia frustrante, muchas personas creen honestamente que alguna ley de la naturaleza nos dice que las máquinas tienen que ser así. Silencian sus dudas al observar cuántas de estas máquinas se han vendido y de esa observación derivan la falsa sensación de seguridad de que, después de todo, el diseño no puede haber sido tan malo. Pero si se examina más de cerca, esa línea de defensa tiene la misma fuerza convincente que el argumento de que fumar cigarrillos debe ser saludable porque mucha gente lo hace.
Es en este sentido que lamento que no sea habitual que las revistas científicas del área de la informática publiquen reseñas de computadoras recién anunciadas de la misma manera que revisamos publicaciones científicas: revisar las máquinas sería al menos tan importante.
Y aquí tengo una confesión que hacer: a principios de los años sesenta escribí una reseña de este tipo con la intención de presentarla al MCCA, pero a pesar de que los pocos compañeros a los que se envió el texto en busca de sus consejos, me urgieron todo para hacerlo, no me atrevía a hacerlo, temiendo que las dificultades para mí o para el consejo editorial fueran demasiado grandes.
Esta represión fue un acto de cobardía de mi parte por el que me culpo cada vez más. Las dificultades que preveía eran consecuencia de la ausencia de criterios generalmente aceptados y aunque estaba convencido de la validez de los criterios que había elegido aplicar, temía que mi reseña fuera rechazada o descartada por “cuestión de gusto personal”. Sigo pensando que estas revisiones serían extremadamente útiles y anhelo verlas aparecer, ya que su apariencia aceptada sería un signo seguro de madurez de la comunidad informática.
Diseño de software programable
La razón por la que he prestado la atención anterior a la escena del hardware es porque tengo la sensación de que uno de los aspectos más importantes de cualquier herramienta informática es su influencia en los hábitos de pensamiento de quienes intentan utilizarla y porque tengo razones para creer que esa influencia es muchas veces más fuerte de lo que comúnmente se supone. Pasemos ahora nuestra atención a la escena del software.
Aquí la diversidad ha sido tan grande que debo limitarme a unos pocos escalones. Soy dolorosamente consciente de la arbitrariedad de mi elección y le ruego que no saque ninguna conclusión con respecto a mi apreciación de los muchos esfuerzos que quedarán sin mencionar.
Estructura modular en el software
Al principio existía el EDSAC en Cambridge, Inglaterra y creo que es bastante impresionante que desde el principio la noción de una biblioteca de subrutinas haya jugado un papel central en el diseño de esa máquina y en la forma en que debería usarse. Han pasado casi 25 años y la escena de la computación ha cambiado drásticamente, pero la noción de software básico sigue con nosotros y la noción de subrutina cerrada sigue siendo uno de los conceptos clave en la programación.
Deberíamos reconocer las subrutinas cerradas como uno de los mayores inventos de software; ha sobrevivido a tres generaciones de computadoras y sobrevivirá a algunas más, porque se encarga de la implementación de uno de nuestros patrones básicos de abstracción.
Lamentablemente, su importancia se ha subestimado en el diseño de las computadoras de tercera generación, en el que el gran número de registros explícitamente nombrados de la unidad aritmética implica una gran sobrecarga en el mecanismo de subrutina. Pero incluso eso no acabó con el concepto de subrutina y solo podemos rezar para que la mutación no sea hereditaria.
El segundo desarrollo importante en la escena del software que me gustaría mencionar es el nacimiento de FORTRAN. En ese momento se trataba de un proyecto de gran temeridad y los responsables del mismo merecen nuestra gran admiración. Sería absolutamente injusto culparlos por deficiencias que solo se hicieron evidentes después de una década de uso extensivo: ¡los grupos con una anticipación exitosa de diez años son bastante raros! En retrospectiva, debemos calificar a FORTRAN como una técnica de codificación exitosa, pero con muy pocas ayudas efectivas para la concepción, ayudas que ahora se necesitan con tanta urgencia que ha llegado el momento de considerarlas obsoletas.
Cuanto antes olvidemos que FORTRAN ha existido, mejor, porque como vehículo del pensamiento ya no es adecuado: desperdicia nuestra capacidad intelectual, es demasiado arriesgado y, por lo tanto, demasiado caro de usar. El trágico destino de FORTRAN ha sido su amplia aceptación, encadenando mentalmente a miles y miles de programadores a nuestros errores pasados. Rezo a diario para que más de mis compañeros programadores encuentren la manera de liberarse de la maldición de la compatibilidad.
El tercer proyecto que no me gustaría dejar sin mencionar es LISP, una empresa fascinante de una naturaleza completamente diferente. Con algunos principios muy básicos en su base, ha demostrado una estabilidad notable. Además de eso, LISP ha sido el portador de un número considerable de, en cierto sentido, nuestras aplicaciones informáticas más sofisticadas. LISP se ha descrito en broma como "la forma más inteligente de hacer un mal uso de una computadora". Creo que esa descripción es un gran cumplido porque transmite todo el sabor de la liberación: ha ayudado a algunos de nuestros congéneres más dotados a pensar en pensamientos que antes eran imposibles.
El cuarto proyecto a mencionar es ALGOL 60. Si bien hasta el día de hoy los programadores de FORTRAN todavía tienden a entender su lenguaje de programación en términos de la implementación específica con la que están trabajando —de ahí la prevalencia de volcados octales y hexadecimales—, mientras que la definición de LISP sigue siendo una mezcla curiosa de lo que significa el lenguaje y cómo funciona el mecanismo, el famoso Informe sobre el lenguaje algorítmico ALGOL 60 es el fruto de un esfuerzo genuino por llevar la abstracción un paso vital más allá y definir un lenguaje de programación en una implementación en forma independiente.
Abstracción del lenguaje por su sintaxis
Se podría argumentar que a este respecto sus autores han tenido tanto éxito que han creado serias dudas sobre si podría implementarse en absoluto. El informe demostró gloriosamente el poder del método formal BNF, ahora bastante conocido como Backus-Naur-Form, y el poder del inglés cuidadosamente redactado, al menos cuando lo usa alguien tan brillante como Peter Naur.
Creo que es justo decir que muy pocos documentos tan breves como este han tenido una influencia igualmente profunda en la comunidad informática. La facilidad con la que en años posteriores se han utilizado los nombres ALGOL y ALGOL-like, como marca comercial desprotegida, para prestar algo de su gloria a una serie de proyectos más jóvenes, a veces apenas relacionados, es un elogio algo sorprendente a su prestigio.
La fuerza de BNF como dispositivo de definición es responsable de lo que considero una de las debilidades del lenguaje: una sintaxis demasiado elaborada y no demasiado sistemática podría ahora apiñarse en los confines de muy pocas páginas. Con un dispositivo tan poderoso como BNF, el Informe sobre el lenguaje algorítmico ALGOL 60 debería haber sido mucho más breve. Además de eso, tengo muchas dudas sobre el mecanismo de parámetros de ALGOL 60: le permite al programador tanta libertad combinatoria, que su uso seguro requiere una fuerte disciplina por parte del programador. Además de caro de implementar, parece peligroso de usar.
Finalmente, aunque el tema no es agradable, debo mencionar PL / 1, un lenguaje de programación para el cual la documentación definitoria es de un tamaño y complejidad aterradora. Usar PL / 1 debe ser como volar un avión con 7000 botones, interruptores y manijas para manipular en la cabina. No veo absolutamente cómo podemos mantener nuestros programas en crecimiento firmemente dentro de nuestro control intelectual cuando, por su puro barroquismo, el lenguaje de programación —¡nuestra herramienta básica, claro! - ya escapa a nuestro control intelectual. Y si tengo que describir la influencia que PL / 1 puede tener en sus usuarios, la metáfora más cercana que me viene a la mente es la de una droga.
Recuerdo de un simposio sobre lenguaje de programación de nivel superior una conferencia que dio en defensa de PL / 1 un hombre que se describió a sí mismo como uno de sus devotos usuarios. Pero dentro de una conferencia de una hora en alabanza de PL / 1. se las arregló para solicitar la adición de unas cincuenta nuevas "características", suponiendo poco que la principal fuente de sus problemas podría muy bien ser que ya contenía demasiadas "características". El hablante mostraba todos los deprimentes síntomas de la adicción, reducido como estaba al estado de estancamiento mental en el que solo podía pedir más, más, más ... Cuando se ha llamado a FORTRAN un trastorno infantil, PL / 1 completo, con sus características de crecimiento de un tumor peligroso, podrían convertirse en una enfermedad fatal.
Demasiado para el pasado. Pero no tiene sentido cometer errores a menos que a partir de entonces podamos aprender de ellos. De hecho, creo que hemos aprendido tanto, que dentro de unos años la programación puede ser una actividad muy diferente de lo que ha sido hasta ahora, tan diferente que es mejor que nos preparemos para el impacto.
El futuro de la programación
Déjeme esbozarle uno de los futuros posibles. A primera vista, esta visión de la programación quizás ya en un futuro próximo puede parecerle absolutamente fantástica. Permítanme, por tanto, añadir también las consideraciones que podrían llevarnos a la conclusión de que esta visión podría ser una posibilidad muy real.
La visión es que, mucho antes de que la década de los setenta se complete, seremos capaces de diseñar e implementar el tipo de sistemas que ahora están agotando nuestra capacidad de programación, a expensas de solo un pequeño porcentaje en años-hombre de lo que cuestan. nosotros ahora y que además de eso, estos sistemas estarán prácticamente libres de errores.
Estas dos mejoras van de la mano. En este último aspecto, el software parece ser diferente de muchos otros productos, donde, por regla general, una calidad superior implica un precio más elevado. Aquellos que quieran un software realmente confiable descubrirán que deben encontrar la manera de evitar la mayoría de los errores y, como resultado, el proceso de programación será más barato. Si desea programadores más efectivos, descubrirá que no deben perder el tiempo depurando, para empezar, no deben introducir los errores.
Un cambio tan drástico en tan poco tiempo sería una revolución y para todas las personas que basan sus expectativas de futuro en una suave extrapolación del pasado reciente, apelando a algunas leyes no escritas de inercia social y cultural, la posibilidad de que este se producirá un cambio drástico que debe parecer insignificante. ¡Pero todos sabemos que a veces se producen revoluciones! ¿Y cuáles son las posibilidades de este?
Parece haber tres condiciones principales que deben cumplirse. El mundo en general debe reconocer la necesidad del cambio; en segundo lugar, la necesidad económica debe ser suficientemente fuerte; y, en tercer lugar, el cambio debe ser técnicamente factible. Permítanme discutir estas tres condiciones en el orden anterior.
Con respecto al reconocimiento de la necesidad de una mayor confiabilidad del software, ya no espero ningún desacuerdo. Hace solo unos años esto era diferente: hablar de una crisis de software era una blasfemia. El punto de inflexión fue la Conferencia sobre Ingeniería de Software en Garmisch, octubre de 1968, una conferencia que causó sensación al producirse la primera admisión abierta de la crisis del software.
Y a estas alturas se reconoce generalmente que el diseño de cualquier gran sistema sofisticado va a ser un trabajo muy difícil y cada vez que uno se encuentra con personas responsables de tales empresas, los encuentra muy preocupados por el tema de la confiabilidad y con razón. En resumen, nuestra primera condición parece cumplida.
Ahora por la necesidad económica. Hoy en día, a menudo se encuentra la opinión de que en los años sesenta la programación ha sido una profesión sobre pagada y que en los próximos años se espera que bajen los sueldos de los programadores.
Por lo general, esta opinión se expresa en relación con la recesión, pero podría ser un síntoma de algo diferente y bastante saludable, a saber. que quizás los programadores de la última década no hayan hecho un trabajo tan bueno como deberían haberlo hecho.
La sociedad está insatisfecha con el desempeño de los programadores y de sus productos. Pero hay otro factor de mucho mayor peso. En la situación actual es bastante habitual que para un sistema específico, el precio a pagar por el desarrollo del software sea del mismo orden de magnitud que el precio del hardware necesario y la sociedad más o menos lo acepta.
Pero los fabricantes de hardware nos dicen que en la próxima década se puede esperar que los precios del hardware caigan en un factor de diez.
Si el desarrollo de software continuara siendo el mismo proceso torpe y costoso que ahora, las cosas se desequilibrarían por completo. No se puede esperar que la sociedad acepte esto y, por lo tanto, nosotros debemos aprender a programar un orden de magnitud de manera más eficaz. Para decirlo de otra manera: mientras las máquinas sean el elemento más importante del presupuesto, la profesión de programación podría salirse con la suya con sus técnicas torpes, pero ese paraguas se doblará rápidamente. En resumen, también nuestra segunda condición parece cumplida.
Y ahora la tercera condición: ¿es técnicamente factible? Creo que podría y le daré seis argumentos en apoyo de esa opinión.
- Un estudio de la estructura de los programas había revelado que los programas —incluso programas alternativos para la misma tarea y con el mismo contenido matemático— pueden diferir enormemente en su manejabilidad intelectual.
- Se han descubierto una serie de reglas, cuya violación dañará gravemente o destruirá totalmente la capacidad de gestión intelectual del programa.
Estas reglas son de dos tipos. Los del primer tipo se imponen fácilmente de forma mecánica, a saber. mediante un lenguaje de programación adecuadamente elegido. Algunos ejemplos son la exclusión de sentencias goto y de procedimientos con más de un parámetro de salida. Para los del segundo tipo, al menos —pero eso puede deberse a una falta de competencia de mi parte— no veo forma de imponerlos mecánicamente, ya que parece necesitar algún tipo de demostrador automático de teoremas para el que no tengo pruebas de existencia. Por lo tanto, por el momento y quizás para siempre, las reglas del segundo tipo se presentan como elementos de disciplina requeridos por el programador.
Algunas de las reglas que tengo en mente son tan claras que se pueden enseñar y que nunca es necesario discutir si un programa determinado las viola o no. Algunos ejemplos son los requisitos de que ningún bucle debe escribirse sin proporcionar una prueba de terminación o sin indicar la relación cuya invariancia no será destruida por la ejecución de la declaración repetible.
Sugiero ahora que nos limitemos al diseño e implementación de programas intelectualmente manejables. Si alguien teme que esta restricción sea tan severa que no podamos vivir con ella, puedo tranquilizarlo: la clase de programas intelectualmente manejables es todavía lo suficientemente rica como para contener muchos programas muy realistas para cualquier problema capaz de solución algorítmica.
No hay que olvidar que no es nuestro negocio el hacer programas, nuestro negocio es diseñar clases de cálculos que se mostrarán con un comportamiento deseado. La sugerencia de limitarnos a programas intelectualmente manejables es la base de los dos primeros de mis seis argumentos anunciados.
El argumento uno es que, dado que el programador solo necesita considerar programas manejables intelectualmente, las alternativas entre las que está eligiendo son muchas, mucho más fáciles de afrontar.
El segundo argumento es que, tan pronto como hemos decidido restringirnos al subconjunto de los programas intelectualmente manejables, hemos logrado, de una vez por todas, una reducción drástica del espacio de soluciones a considerar. Y este argumento es distinto del argumento uno.
El tercer argumento se basa en el enfoque constructivo del problema de la corrección del programa. Hoy en día una técnica habitual es hacer un programa y luego probarlo. Pero: la prueba del programa puede ser una forma muy efectiva de mostrar la presencia de errores, pero es desesperadamente inadecuada para mostrar su ausencia. La única forma eficaz de elevar significativamente el nivel de confianza de un programa es dar una prueba convincente de su corrección.
Pero no se debe hacer primero el programa y luego probar que es correcto, porque entonces el requisito de proporcionar la prueba solo aumentaría la carga del pobre programador. Al contrario: el programador debe dejar que la prueba de corrección y el programa crezcan de la mano. El argumento tres se basa esencialmente en la siguiente observación.
Si uno se pregunta primero cuál sería la estructura de una prueba convincente y, habiendo encontrado esto, luego construye un programa que satisface los requisitos de esta prueba, entonces estas preocupaciones de corrección resultan ser una guía heurística muy efectiva. Por definición, este enfoque solo es aplicable cuando nos limitamos a programas intelectualmente manejables, pero nos proporciona medios efectivos para encontrar uno satisfactorio entre ellos.
El argumento cuatro tiene que ver con la forma en que la cantidad de esfuerzo intelectual necesario para diseñar un programa depende de la duración del programa. Se ha sugerido que existe algún tipo de ley de la naturaleza que nos dice que la cantidad de esfuerzo intelectual necesario aumenta con el cuadrado de la duración del programa. Pero, gracias a Dios, nadie ha podido probar esta ley. Y esto se debe a que no tiene por qué ser verdad.
Todos sabemos que la única herramienta mental por medio de la cual un razonamiento muy finito puede cubrir una miríada de casos se llama "abstracción"; como resultado, la explotación efectiva de sus poderes de abstracción debe considerarse como una de las actividades más vitales de un programador competente.
A este respecto, podría ser conveniente señalar que el propósito de abstraer no es para ser vago, pero para crear un nuevo nivel semántico en el que uno puede ser absolutamente preciso. Por supuesto, he tratado de encontrar una causa fundamental que impida que nuestros mecanismos de abstracción sean suficientemente efectivos.
Pero no importa cuánto lo intenté, no encontré tal causa. Como resultado, tiendo a suponer —hasta ahora no refutado por la experiencia— de que mediante la aplicación adecuada de nuestros poderes de abstracción, el esfuerzo intelectual necesario para concebir o comprender un programa no necesita crecer más que proporcional a la longitud del programa.
Pero un subproducto de estas investigaciones puede tener una importancia práctica mucho mayor y es, de hecho, la base de mi cuarto argumento. El subproducto fue la identificación de una serie de patrones de abstracción que juegan un papel vital en todo el proceso de composición de programas. Ahora se sabe lo suficiente sobre estos patrones de abstracción como para dedicarle una conferencia sobre cada uno de ellos.
Lo que la familiaridad y el conocimiento consciente de estos patrones de abstracción implican se me ocurrió cuando me di cuenta de que, si hubieran sido de conocimiento común hace quince años, el paso de BNF a compiladores dirigidos por sintaxis, por ejemplo, podría haber tomado unos minutos en lugar de unos años.
Por tanto, presento nuestro conocimiento reciente de los patrones de abstracción vitales como el cuarto argumento.
Ahora para el quinto argumento. Tiene que ver con la influencia de la herramienta que estamos tratando de usar sobre nuestros propios hábitos de pensamiento. Observo una tradición cultural, que con toda probabilidad tiene sus raíces en el renacimiento, para ignorar esta influencia, para considerar a la mente humana como el amo supremo y autónomo de sus artefactos.
El mindset de la programación
Pero si empiezo a analizar los hábitos de pensamiento de mí mismo y de mis semejantes, llego, me guste o no, a una conclusión completamente diferente, a saber. que las herramientas que estamos tratando de usar y el lenguaje o la notación que estamos usando para expresar o registrar nuestros pensamientos, son los factores principales que determinan lo que podemos pensar o expresar.
El análisis de la influencia que los lenguajes de programación tienen en los hábitos de pensamiento de sus usuarios y el reconocimiento de que, a estas alturas, la capacidad intelectual es, con mucho, nuestro recurso más escaso, juntos nos brindan una nueva colección de criterios para comparar los méritos relativos de varios lenguajes de programación.
El programador competente es plenamente consciente del tamaño estrictamente limitado de su propio cráneo; por eso se acerca a la tarea de programar con total humildad y entre otras cosas evita trucos ingeniosos como la peste.
En el caso de un conocido lenguaje de programación conversacional me han dicho desde varios lados que, en cuanto una comunidad de programación está equipada con un terminal para ello, ocurre un fenómeno específico que incluso tiene un nombre bien establecido: se llama “ las frases ingeniosas ”.
Toma una de dos formas diferentes: un programador coloca un programa de una línea en el escritorio de otro y dice con orgullo lo que hace y agrega la pregunta "¿Puedes codificar esto con menos símbolos?" —¡Como si esto tuviera alguna relevancia conceptual! - o simplemente pregunta "¡Adivina qué hace!".
De esta observación debemos concluir que este lenguaje como herramienta es una invitación abierta a trucos ingeniosos; y aunque exactamente esta puede ser la explicación de parte de su atractivo, a saber. para aquellos a quienes les gusta mostrar lo inteligentes que son, lo siento, pero debo considerar esto como una de las cosas más condenatorias que se pueden decir sobre un lenguaje de programación.
Otra lección que deberíamos haber aprendido del pasado reciente es que el desarrollo de lenguajes de programación "más ricos" o "más potentes" fue un error en el sentido de que estas monstruosidades barrocas, estos conglomerados de idiosincrasias, son realmente inmanejables, tanto mecánica como mentalmente.
Veo un gran futuro para los lenguajes de programación muy sistemáticos y muy modestos. Cuando digo "modesto", me refiero a que, por ejemplo, no solo la "cláusula for" de ALGOL 60, pero incluso el "bucle DO" de FORTRAN puede resultar descartado por ser demasiado barroco.
He realizado un pequeño experimento de programación con voluntarios muy experimentados, pero apareció algo bastante inesperado y no intencionado.
Ninguno de mis voluntarios encontró la solución más obvia y elegante. Tras un análisis más detallado, esto resultó tener una fuente común: su noción de repetición estaba tan estrechamente conectada con la idea de una variable controlada asociada que debía intensificarse, que estaban mentalmente bloqueados para no ver lo obvio. Sus soluciones eran menos eficientes, innecesariamente difíciles de entender, y les llevó mucho tiempo encontrarlas.
Fue una experiencia reveladora, pero también impactante para mí. Finalmente, en un aspecto, uno espera que los lenguajes de programación del mañana difieran mucho de los que estamos acostumbrados ahora: en mucha mayor medida que hasta ahora deberían invitarnos a reflejar en la estructura de lo que escribimos todas las abstracciones necesarias para afrontar conceptualmente la complejidad de lo que estamos diseñando. Hasta aquí la mayor adecuación de nuestras herramientas futuras, que fue la base del quinto argumento.
Como un aparte me gustaría insertar una advertencia a quienes identifican la dificultad de la tarea de programación con la lucha contra las deficiencias de nuestras herramientas actuales, porque podrían concluir que, una vez que nuestras herramientas sean mucho más adecuadas, la programación ya no será suficiente, será un problema.
La programación seguirá siendo muy difícil, porque una vez que nos hayamos liberado de la incomodidad circunstancial, nos encontraremos libres para abordar los problemas que ahora están mucho más allá de nuestra capacidad de programación.
Puedes discutir con mi sexto argumento, porque no es tan fácil recolectar evidencia experimental para su apoyo, un hecho que no me impedirá creer en su validez. Hasta ahora no he mencionado la palabra “jerarquía”, pero creo que es justo decir que este es un concepto clave para todos los sistemas que incorporan una solución bien factorizada. Incluso podría dar un paso más y convertirlo en un artículo de fe, a saber. que los únicos problemas que realmente podemos resolver de manera satisfactoria son aquellos que finalmente admiten una solución bien factorizada.
A primera vista, esta visión de las limitaciones humanas puede parecerles una visión bastante deprimente de nuestra situación, pero yo no lo siento así, ¡al contrario! La mejor forma de aprender a vivir con nuestras limitaciones es conocerlas. En el momento en que seamos lo suficientemente modestos como para probar solo soluciones factorizadas, Debido a que los otros esfuerzos escapan a nuestro control intelectual, haremos todo lo posible para evitar que todas esas interfaces perjudiquen nuestra capacidad para factorizar el sistema de una manera útil.
Y no puedo dejar de esperar que esto conduzca repetidamente al descubrimiento de que, después de todo, se puede factorizar un problema inicialmente imposible de resolver. Cualquiera que haya visto cómo la mayoría de los problemas de la fase de compilación llamada "generación de código" se pueden rastrear hasta las propiedades divertidas del código de pedido, sabrá un ejemplo simple del tipo de cosas que tengo en mente. La aplicabilidad más amplia de soluciones bien factorizadas es mi sexto y último argumento a favor de la viabilidad técnica de la revolución que podría tener lugar en la década actual.
#AskYourSelf
En principio, dejo que usted decida por sí mismo cuánto peso le va a dar a mis consideraciones, sabiendo muy bien que no puedo obligar a nadie más a compartir mis creencias. Como cada revolución seria, provocará una oposición violenta y uno puede preguntarse dónde esperar las fuerzas conservadoras que intentan contrarrestar tal desarrollo.
No los espero principalmente en las grandes empresas, ni siquiera en el negocio de las computadoras; Los espero más bien en las instituciones educativas que brindan capacitación hoy en día y en esos grupos conservadores de usuarios de computadoras que piensan que sus viejos programas son tan importantes que no creen que valga la pena reescribirlos y mejorarlos.
A este respecto, es triste observar que en muchos campus universitarios la elección de la instalación informática central ha estado determinada con demasiada frecuencia por las demandas de unas pocas aplicaciones establecidas pero costosas, sin tener en cuenta la cuestión de cuántos miles de "pequeños usuarios" que estén dispuestos a escribir sus propios programas iban a sufrir esta elección.
Con demasiada frecuencia, por ejemplo, la física de altas energías parece haber chantajeado a la comunidad científica con el precio del equipo experimental restante. La respuesta más fácil, por supuesto, es una negación rotunda de la viabilidad técnica, pero me temo que se necesitan argumentos bastante sólidos para ello.
Desafortunadamente, no se puede obtener ninguna tranquilidad con la observación de que el techo intelectual del programador promedio de hoy impedirá que se produzca la revolución:
También puede haber impedimentos políticos. Incluso si sabemos cómo educar al programador profesional del mañana, no es seguro que la sociedad en la que vivimos nos lo permita.
El primer efecto de enseñar una metodología —más que difundir conocimientos— es el de potenciar las capacidades de los ya capaces, magnificando así la diferencia de inteligencia. En una sociedad en la que el sistema educativo se utiliza como instrumento para el establecimiento de una cultura homogeneizada, en la que se impide que la crema llegue a lo más alto, la formación de programadores competentes podría resultar políticamente imparable.
El movimiento mental TopDown
Déjame concluir. Las computadoras automáticas han estado con nosotros durante un cuarto de siglo. Han tenido un gran impacto en nuestra sociedad en su capacidad de herramientas, pero en esa capacidad su influencia no será más que una onda en la superficie de nuestra cultura, en comparación con la influencia mucho más profunda que tendrán en su capacidad de desafío intelectual sin precedente en la historia cultural de la humanidad.
Los sistemas jerárquicos parecen tener la propiedad de que "algo" considerado como "una entidad indivisa" en el primer nivel, se considera un objeto compuesto en el siguiente nivel inferior de mayor detalle; como resultado, el grano natural de espacio o tiempo que es aplicable en cada nivel disminuye en un orden de magnitud cuando cambiamos nuestra atención de un nivel al siguiente nivel inferior.
Entendemos las paredes en términos de ladrillos, los ladrillos en términos de cristales, cristales en términos de moléculas, etc. Como resultado, el número de niveles que se pueden distinguir de manera significativa en un sistema jerárquico es proporcional al logaritmo de la relación entre el grano más grande y el más pequeño, y por lo tanto, a menos que esta relación sea muy grande, no podemos esperar muchos niveles.
En programación de computadoras, nuestro bloque de construcción básico tiene una granularidad de tiempo asociado de menos de un microsegundo, pero nuestro programa puede tomar horas de tiempo de cálculo. No conozco ninguna otra tecnología que cubra una proporción de 10 elevado a la 10 o más: el ordenador, en virtud de su fantástica velocidad, parece ser el primero en proporcionarnos un entorno en el que los artefactos altamente jerárquicos son posibles y necesarios.
Este desafío, a saber. el enfrentamiento con la tarea de programación, es tan singular que esta novedosa experiencia puede enseñarnos mucho sobre nosotros mismos. Debería profundizar nuestra comprensión de los procesos de diseño y creación, debería darnos un mejor control sobre la tarea de organizar nuestros pensamientos. Si no fuera así, ¡a mi gusto no deberíamos merecer la computadora en absoluto!
Ya nos ha enseñado algunas lecciones y la que he elegido enfatizar en esta charla es la siguiente.Haremos un trabajo de programación mucho mejor, siempre que abordemos la tarea con una plena apreciación de su tremenda dificultad, siempre que nos ciñamos a lenguajes de programación modestos y elegantes, siempre que respetemos las limitaciones intrínsecas de la mente humana y abordemos la tarea. como programadores muy humildes.
















