miércoles, 8 de julio de 2015

El Para y los diagramas de flujo: ese pequeño gran detalle

Una pregunta en el foro de PSeInt trajo consecuencias inesperadas. La versión corta de la historia: hace más de 10 años que cometo sistemáticamente un error en mis diagramas de flujo (y entonces el error está en los diagramas de PSeInt). Es un detalle, pero según cómo se mire, puede no ser menor. Antes de revelar cuál es y contar la historia, hagamos una prueba. Solo voy a decir que el error está relacionado a la estructura repetitiva Para (el "for"). Antes de seguir avanzando en la lectura de este post, intente adivinar qué tiene "mal" el siguiente dibujo:


¿Algo raro? "Sí", dirá usted, "varias cosas, pero ¿a cuál se refiere?". Este era el diagrama que generaba PSeInt hasta ayer. Avancemos un poco. El que sigue es el diagrama que está en el material con el que estudié programación en la universidad hace ya más de 10 años, material producido por la cátedra, y en el cual me basé al comenzar el desarrollo de PSeInt. Encuentre las 7 diferencias:


¿Notaron algo? Última oportunidad... Bien, empecemos con la historia y el análisis del problema. Hace unas semanas, algún docente publicó en el foro de PSeInt algo como (resumiendo) "un alumno me preguntó algo y no se cómo responder, así que te transmito la pregunta: ¿por qué el Para es como es en el diagrama de flujo?" Mi primer respuesta sería: "porque así lo aprendí, pregúntenle al que me enseñó". Pero esa no es de ninguna manera una respuesta aceptable. Así que no respondí, lo dejé pendiente. Hasta que esta semana le empecé a preguntar a algunos de los docentes más "antiguos" de la cátedra, los que seguramente participaron en la confección primera de ese material del cual lo aprendí. Y resulta que había un detalle importante que yo no había registrado...

En los dibujos de todas las demás entidades que uso en PSeInt, está muy claro cómo avanza el flujo... Si uno sigue la flecha roja, no puede perderse. Siempre que encuentre más de un camino, será claro cuáles son las posibilidades, y cuál es la expresión que indica cuál elegir. En todos los puntos donde los caminos se unen, está claro el sentido de circulación, y entonces es fácil saber cómo avanzar.


Con el Para esto no ocurre. El Para genera dos "lugares" en el tramado de caminos y flechas que marcan el flujo, en los que no queda del todo claro qué hay que hacer. Y peor aún, si uno intenta completar con algún sentido común lo que falta para que quede claro, el resultado dista aún más de lo que realmente se quiere representar:


Tomemos por ejemplo el punto de entrada. En ese punto, confluyen 3 líneas. Según el sentido de circulación de cada una, estaría claro que cuando uno ingresa a la estructura, tiene que seguir de largo hacia la primera instrucción que esta contenga. Pero eso no es cierto. Lo primero que se hace al interpretar un bucle Para/For es inicializar el contador y evaluar la condición para determinar si efectivamente hay que ingresar o no. Ya tenemos dos problemas claros: no estamos representando las acciones de inicializar y comparar como parte de ese trayecto, y tampoco existe un trayecto alternativo posible que contemple lo que ocurre cuando no hay que entrar porque la condición es falsa desde el vamos.

Ahora el punto de salida. Es mucho peor. Aquí, si venimos desde adentro del Para, llegamos a un punto donde hay dos caminos válidos según el sentido de circulación, y no hay absolutamente nada que de una pista acerca de cual tomar. En el mejor de los casos, agregando inercia, podríamos decir que lo más natural sería seguir de largo y de nuevo estaríamos alejándonos cada vez más de la verdadera intención. Por otra parte, si vamos para el costado con la intención de ir a incrementar el contador, ya no hay vuelta atrás, no hay camino para regresar si ese contador llegó al final.

Entonces, ¿cómo debería verse en realidad el Para? Busqué y busqué ejemplos en Google, y mi conclusión es que no hay consenso. Hay opciones más o menos razonables, y otras no tanto. Curiosamente, no hay ninguna parecida a la del círculo que yo aprendí. Mis docentes aseguran que lo tomaron originalmente de unos viejísimos libros de ForTran y/o COBOL hace como 30 años, pero no logramos averiguar cuales eran exactamente esos libros o sus autores. En cualquier caso, la forma más realista, de acuerdo a cómo funciona, es esta:


Básicamente, lo partimos en 3. Y esto parece inevitable si queremos ser bien explícitos, ya que las tres partes se ejecutan en distintos momentos. La inicialización del contador va solo una vez, antes de empezar a iterar, las otras dos partes se repiten en cada iteración. Pero la verificación del valor final se hace antes de cada iteración, mientras que el incremento del contador después. No hay un solo lugar donde poner el para, a menos que hagamos la "truchada" de promediar y calzarlo a mitad camino. Que es más o menos lo que hago en PSeInt con ese círculo dudoso que estamos cuestionando.

Entonces, digamos que no hay una muy buena forma de representarlo con solo una entidad. Pero si quiero mantener la relación 1:1 entre entidades e instrucciones/estructuras de control, y quiero mantener al para fácilmente diferenciable del resto (que se note que es bicho raro), tengo que tomar alguna solución de compromiso y ceder en algo. Digamos que el círculo cede en la lógica impecable que traían hasta entonces las flechitas. Y aquí es donde entra el detalle: en la versión del apunte de la cátedra, en los puntos de entrada y salida, donde el para se une al resto del algoritmo, hay dos rayitas diagonales, de las que no se ven en ninguna otra estructura. Y ese detalle, yo no lo había registrado. Hasta tuve que buscar el apunte para convencerme de que estaba. Cuando era alumno, seguramente no le di importancia, lo aprendí digamos que mal, lo grabé así, y cuando hice el PSeInt arrastré sin darme cuenta esos errores. Siempre me hizo algo de ruido el dibujo del Para, pero nadie más lo había cuestionado y de tanto hacerlo así se tornó natural. Ahora, la pregunta del foro revivió esos ruidos y me llevó a rastrear el origen.


Entonces, esas dos rayitas, aparentemente inofensivas, a mi gusto lo cambian todo. Porque esas rayitas son en sí algo raro, algo que no es obvio. Entonces, si uno viene siguiendo el flujo alegremente según las flechas, y de pronto se topa con esa rayita, seguramente se preguntará qué significan. Es decir, esas rayitas pueden llamar la atención, advirtiendo de alguna manera que ahí pasa algo raro. Si vamos a hacer cosas raras con el flujo, al menos pongamos señales/indicadores donde intervenimos para que no quede como si no hubiera pasado nada. Por otro lado, el sentido de las demás líneas auxiliares, aún sin ser estricto, evoca la idea de iteración. Sigue siendo entonces una solución de compromiso, pero tal vez está un poquito menos mentirosa, ya que no esconde el error. Así que por lo pronto, comienzo por poner el par de rayitas en la nueva release de PSeInt, y quedará para el futuro analizar mejor las otras tantas versiones del Para que hay dando vueltas.

5 comentarios:

  1. >> y quedará para el futuro analizar mejor las otras tantas versiones del Para que hay dando vueltas.

    Si hay que mostrar un mejor FOR

    la versión actual del FOR es un dibujo de afán, no muestra verdaderamente un diagrama de flujo de información o de como funciona el bloque, requiere imaginarse los pasos de incremento, comparación de la variable, como inicia la variable, la rayita vertical para mi no soluciona cuando el bucle termina, sigo pensando que camino seguir

    propongo diagramar un FOR como el que se muestra en la siguiente imagen y dejar el actual para el que le guste como esta, este cambio debería estar en un menú de configuracion

    http://jaimeza.org/ComputerEngineering/images/diagramaDeFlujo_image01.png

    también propongo para reducir el dibujo vertical, una opción para mostrar sentencias consecutivas en una sola línea de esta manera se expande el diagrama de flujo horizontalmente resultando un diagrama mas cuadrado y no vertical.

    el diagrama para IF debería ser mejor un hexágono de esta manera se puede organizar y aprovechar mejor la pantalla

    Gracias

    ResponderEliminar
  2. Este comentario ha sido eliminado por el autor.

    ResponderEliminar
  3. ... analizando lo que dices mostrar un FOR en un solo bloque no es intuitivo, ni explicito, como bloque PARA desde el punto de vista visual por que parece un bloque IF,

    en la siguiente imagen

    http://4.bp.blogspot.com/-oGNmqFfiSdc/VZaota5ODwI/AAAAAAAAB3c/5LjjxXqmFGQ/s320/para4.png


    una manera de hacer entender que se trata de un BUCLE seria agregando un pequeño detalle de texto en el bloque condicional la palabra PARA, y en el bloque del incremento poner PASO, la otra idea seria encerrar toda dentro un cuadro punteado indicando que se trata de un bloque PARA

    también en la anterior imagen para realizar menos dibujos la opción de salida debe ser derecha como en la siguiente imagen

    http://jaimeza.org/ComputerEngineering/images/diagramaDeFlujo_image01.png

    ResponderEliminar
  4. Encontré una aplicación para generar código a partir de diagrama de flujo, este proyecto nació en la agencia espacial de la ex unión soviética, dicen que los soviéticos tomaban lo que hacia occidente y lo optimizaban, no inventaban sino que mejoraban lo que estaba hecho, al igual como lo hacia FERRARI con los autos

    el proyecto sobre un lenguaje a partir de diagrama de flujo se llama DRAKON y fue continuado en 2011
    ver

    ver tutorial en
    http://drakon-editor.sourceforge.net/DRAKON.pdf

    ResponderEliminar
  5. una alternativa a los diagramas de flujo de PSEINT son los que propone FLOWGORITHM http://www.flowgorithm.org se podría pensar en clonar esta caracteristica

    ResponderEliminar