Estructura del software
Un caso contra la declaración GO TO.
Desde hace varios años estoy familiarizado con la observación de que la calidad de los programadores es una función decreciente de la densidad de instrucciones go to en los programas que producen. Más tarde descubrí por qué el uso de la instrucción go to tiene efectos tan desastrosos y me convencí de que la instrucción go to debería eliminarse de todos los lenguajes de programación de "nivel superior" (es decir, todo excepto —quizás— código simple de máquina).
En ese momento no le di demasiada importancia a este descubrimiento; Ahora presento mis consideraciones para su publicación porque en discusiones muy recientes en las que surgió el tema, se me ha instado a hacerlo.
Mi primer comentario es que, aunque la actividad del programador termina cuando ha construido un programa correcto, el proceso que tiene lugar bajo el control de su programa es el verdadero tema de su actividad, ya que es este proceso el que tiene que lograr el efecto deseado, es este proceso el que en su comportamiento dinámico debe satisfacer las especificaciones deseadas. Sin embargo, una vez realizado el programa, se delega en la máquina la “realización” del proceso correspondiente.
Mi segunda observación es que nuestros poderes intelectuales están más bien orientados a dominar las relaciones estáticas y que nuestros poderes para visualizar procesos que evolucionan en el tiempo están relativamente poco desarrollados. Por esa razón, debemos hacer (como programadores sabios conscientes de nuestras limitaciones) nuestro mejor esfuerzo para acortar la brecha conceptual entre el programa estático y el proceso dinámico, para hacer la correspondencia entre el programa (esparcido en el espacio de texto) y el proceso ( extendido en el tiempo) lo más trivial posible.
Consideremos ahora cómo podemos caracterizar el progreso de un proceso. (Puedes pensar en esta pregunta de una manera muy concreta: supongamos que un proceso, considerado como una sucesión temporal de acciones, se detiene después de una acción arbitraria, ¿qué datos tenemos que arreglar para que podamos rehacer el proceso hasta que ¿El mismo punto?) Si el texto del programa es una pura concatenación de, digamos, declaraciones de asignación (para el propósito de esta discusión consideradas como descripciones de acciones individuales), es suficiente señalar en el texto del programa a un punto entre dos acciones sucesivas descripciones. (En ausencia de ir adeclaraciones Puedo permitirme la ambigüedad sintáctica en las tres últimas palabras de la oración anterior: si las analizamos como "sucesivas (descripciones de acción)" nos referimos a sucesivas en el espacio de texto, si las analizamos como "descripciones (acciones sucesivas)" queremos decir sucesivas en el tiempo). Llamemos a tal puntero a un lugar adecuado en el texto "índice textual".
Cuando incluimos cláusulas condicionales ( si B entonces A ), cláusulas alternativas ( si B entonces A1 más A2), cláusulas de elección tal como las introdujo CARHoare ( caso [i] de ( A1, A2, ....., An )) o expresiones condicionales introducidas por J. McCarthy ( B1 → E1, B2 → E2, ....., Bn → En ), el hecho es que el progreso del proceso permanece caracterizado por un solo índice textual.
Una vez que incluimos en nuestros procedimientos de lenguaje debemos admitir que un índice textual único ya no es suficiente: en el caso de que un índice textual apunte al interior de un cuerpo de procedimiento, el progreso dinámico solo se caracteriza cuando también aportamos a qué llamada del procedimiento al que nos referimos. Con la inclusión de procedimientos podemos caracterizar el progreso del proceso a través de una secuencia de índices textuales, siendo la longitud de esta secuencia igual a la profundidad dinámica de la llamada al procedimiento.
Consideremos ahora las cláusulas de repetición (como, mientras que B repite A o repite A hasta que B). Lógicamente hablando, tales cláusulas son ahora superfluas, porque podemos expresar la repetición con la ayuda de procedimientos recursivos. Por razones de realismo, no deseo excluirlos: por un lado, las cláusulas de repetición se pueden implementar con bastante comodidad con el equipo finito actual, por otro lado, el patrón de razonamiento conocido como "inducción" nos hace bien equipados para retener nuestra capacidad intelectual, captar los procesos generados por las cláusulas de repetición.
Con la inclusión de las cláusulas de repetición, los índices textuales ya no son suficientes para describir el progreso dinámico del proceso. Con cada entrada en una cláusula de repetición, sin embargo, podemos asociar un llamado “índice dinámico”, contando inexorablemente el número ordinal de la correspondiente repetición actual. Como las cláusulas de repetición (al igual que las llamadas a procedimientos) se pueden aplicar anidadas,
El punto principal es que los valores de estos índices están fuera del control del programador: se generan (ya sea por la redacción de su programa o por la evolución dinámica del proceso), lo desee o no. Proporcionan coordenadas independientes en las que describir el progreso del proceso.
¿Por qué necesitamos tales coordenadas independientes? La razón es, y esto parece ser inherente a los procesos secuenciales, que podemos interpretar el valor de una variable solo con respecto al progreso del proceso. Si deseamos contar el número, n decir, de las personas en una sala vacía inicialmente, podemos lograr esto mediante el aumento de n por 1 cada vez que vemos a alguien entrar en la habitación; en el momento intermedio en el que hemos observado que alguien entra en la habitación pero aún no hemos realizado el aumento posterior de n , su valor es igual al número de personas en la habitación menos uno.
El uso desenfrenado de la declaración go to tiene como consecuencia inmediata que resulta terriblemente difícil encontrar un conjunto significativo de coordenadas en las que describir el progreso del proceso. Por lo general, las personas también tienen en cuenta los valores de algunas variables bien elegidas, pero esto está fuera de discusión porque es relativo al progreso que se debe entender el significado de estos valores.
Con la instrucción go to uno puede, por supuesto, seguir describiendo el progreso de forma única mediante un contador que cuenta el número de acciones realizadas desde el inicio del programa (es decir, una especie de reloj normalizado). La dificultad es que tal coordenada, aunque única, es completamente inútil: en tal sistema de coordenadas se vuelve un asunto extremadamente complicado definir todos esos puntos de progreso donde, digamos, n es igual al número de personas en la habitación menos uno.
La declaración go to tal como está es demasiado primitiva, es una invitación demasiado a hacer un lío en el programa. Uno puede considerar y apreciar las cláusulas consideradas como un freno a su uso. No pretendo que las cláusulas mencionadas sean exhaustivas en el sentido de que satisfagan todas las necesidades; pero cualesquiera que sean las cláusulas que se sugieran (por ejemplo, cláusulas de cancelación), deben satisfacer el requisito de que se pueda mantener un sistema de coordenadas independiente del programador para describir el proceso de una manera útil y manejable.
Es difícil terminar este artículo con un reconocimiento justo: ¿debo juzgar por quién ha sido influenciado mi pensamiento? Es bastante obvio que Peter Landin y Christopher Strachey no me dejan de influir, y que no me arrepiento de su influencia sobre mí. Finalmente, me gustaría dejar constancia (como lo recuerdo con bastante claridad) de cómo Heinz Zemanek, en la reunión previa a ALGOL a principios de 1959 en Copenhague, expresó de manera bastante explícita sus dudas sobre si la declaración go to debería tratarse en pie de igualdad sintáctica con la declaración de asignación. Hasta cierto punto me culpo por no haber sacado las consecuencias de su comentario.
La observación sobre lo indeseable de la declaración go to está lejos de ser nueva. Recuerdo haber leído la recomendación explícita de restringir el uso de la declaración go to para alarmar salidas, pero no he podido rastrearla; presumiblemente, ha sido realizado por CAR Hoare. En [1, Sec. 3.2.1]
Wirth y Hoare juntos hacen un comentario en la misma dirección para motivar la construcción del caso: “Como el condicional, refleja la estructura dinámica de un programa más claramente que ir a declaraciones y conmutadores, y elimina la necesidad de introducir una gran cantidad de etiquetas en el programa ".
En [2] Guiseppe [sic] Jacopini parece haber demostrado la superfluidad (lógica) de la declaración go to . Sin embargo, no se recomienda el ejercicio de traducir un diagrama de flujo arbitrario más o menos mecánicamente en uno sin saltos. Entonces, no se puede esperar que el diagrama de flujo resultante sea más transparente que el original.
REFERENCIAS:
Wirth, Niklaus y Hoare, CAR Una contribución al desarrollo de ALGOL. Comm. ACM 9 (junio de 1966), 413–432.
Böhm, Corrado y Jacopini, Guiseppe. Diagramas de flujo, máquinas de Turing y lenguajes con solo dos reglas de formación. Comm. ACM 9 (mayo de 1966), 366–371.


No hay comentarios:
Publicar un comentario