Programación estructurada de Jackson

La Programación estructurada de Jackson (JSP) es un método para programación estructurada fundamentada sobre las correspondencias que se establecen entre la estructura de flujo de datos y la estructura de un programa. JSP programas y estructuras de datos en términos de secuencias, iteraciones y selecciones, y como consecuencia es aplicado cuando se diseña la estructura de control detallada de un programa, por debajo del nivel en el que los métodos orientados a objetos se vuelven importantes.[1][2]

Ejemplo de diagrama JSP.

Introducción editar

Michael A. Jackson desarrolló originalmente JSP en la década de 1970. Se documentó el sistema en sus 1975 libro Principios de Diseño del Programa.[3]​ El objetivo de Jackson era hacer los programas de procesamiento de archivos por lotes COBOL más fácil de modificar y mantener, pero el método se puede utilizar para diseñar programas para cualquier lenguaje de programación que tenga constructores, lenguajes como C, Java y Perl. A pesar de su edad, JSP está todavía en uso y con el apoyo de herramientas de diagramación tales como herramientas de Microsoft Visio y CASE como Jackson Workbench[4]

Jackson Programación Estructurada fue visto por muchos como relacionada[5]​ con la programación estructurada Warnier,[6]​ pero este último método se centró casi exclusivamente en la estructura de la secuencia de salida. JSP y método de Warnier, ambos programas de estructura y datos utilizando solo secuencias, iteraciones y selecciones, por lo que básicamente crean programas que son analizadores de expresiones regularesque coincidan simultáneamente flujos de datos de entrada y salida del programa. .

Debido a que JSP se centra en los flujos de entrada y salida de datos existentes, el diseño de un programa utilizando JSP se afirma que es más directo que con otros métodos de programación estructurada, evitando los saltos de la intuición necesaria para programar con éxito utilizando métodos como la descomposición de arriba hacia abajo.[7]

Otra consecuencia del enfoque de JSP en flujos de datos es que crea diseños de programas con una estructura muy diferente a la clase creada por los métodos de refinamiento por pasos de Wirth y Dijkstra. Una característica típica de la estructura de los programas JSP es que tienen varias operaciones de entrada distribuidos por todo el código en contraste con los programas diseñados utilizando refinamiento paso a paso, que tienden a tener solo una operación de entrada. Jackson ilustra esta diferencia en el Capítulo 3 de Principios de Diseño del Programa.[3]​ Presenta dos versiones de un programa, uno diseñado utilizando JSP, el otro usando métodos "tradicionales".

Equivalente estructural editar

Para un ejemplo comparando Jackson Programación Estructurada a la programación estructurada "tradicional", consideremos un programa en C para contar el número de líneas repetidas en un archivo.

La versión JSP del programa es estructuralmente equivalente a

String line;

line = in.readLine();
while (line != null) {
    int count = 0;
    String firstLineOfGroup = line;

    while (line != null && line.equals(firstLineOfGroup)) {
        count++;
        line = in.readLine();
    }
    System.out.println(firstLineOfGroup + " " + count);
}

y la versión tradicional del programa es equivalente a

String line;

int count = 0;
String firstLineOfGroup = null;
while ((line = in.readLine()) != null) {
    if (firstLineOfGroup == null
            || !line.equals(firstLineOfGroup)) {
        if (firstLineOfGroup != null) {
            System.out.println(firstLineOfGroup + " " + count);
        }
        count = 0;
        firstLineOfGroup = line;
    }
    count++;
}
if (firstLineOfGroup != null) {
    System.out.println(firstLineOfGroup + " " + count);
}

Jackson critica la versión tradicional, alegando que esconde las relaciones que existen entre las líneas de entrada, lo que compromete la comprensibilidad y mantenibilidad del programa, por ejemplo, obligando al uso de un caso especial de la primera línea y forzando otro caso especial para una operación final de salida.

El método editar

JSP utiliza pasos semi-formales para capturar la estructura existente de las entradas y salidas de un programa en la estructura del programa en sí.

La intención es crear programas que son fáciles de modificar a lo largo de su vida. La importante visión de Jackson fue que los cambios de requisitos suelen ser pequeños ajustes a las estructuras existentes. Para un programa construido con JSP, las entradas, las salidas y las estructuras internas del programa todas combinan, por lo que pequeños cambios en las entradas y salidas deben traducirse en pequeños cambios en el programa.

Programas de estructuras JSP en términos de cuatro tipos de componentes:

  • operaciones fundamentales
  • secuencias
  • iteraciones
  • selecciones

El método comienza con la descripción de las entradas de un programa en términos de los cuatro tipos fundamentales de componentes. A continuación, pasa a describir las salidas del programa de la misma manera. Cada entrada y salida es modelada como un Diagrama de Estructura de Datos separados(DSD). Para hacer JSP trabajar para aplicaciones de cálculo intensivo, tales como procesamiento de señal digital (DSP) es también necesario dibujar diagramas de estructura de algoritmo, que se centran en las estructuras internas de datos en lugar de los de entrada y salida.

Las estructuras de entrada y salida son entonces unificadas o mezcladas en una estructura de programa final, conocida como Diagrama de Estructura de un Programa (PSD). Este paso puede implicar la adición de una pequeña cantidad de estructura de alto nivel de control para vincular las entradas y salidas. Algunos programas procesan toda la entrada antes de hacer cualquier salida, mientras que otros leen en un registro, escriben un registro e iteran. Tales enfoques tienen que ser capturados en el PSD.

El PSD, que es un lenguaje neutro, es implementado entonces en un lenguaje de programación. JSP está orientado a la programación a nivel de las estructuras de control, por lo que los diseños implementados utilizan solo operaciones primitivas, secuencias, iteraciones y selecciones. JSP no se utiliza para estructurar programas a nivel de clases y objetos, aunque puede estructurar amablemente el flujo de control dentro de los métodos de una clase.

JSP utiliza una notación de diagramas para describir la estructura de entradas, salidas y programas, con elementos de diagrama para cada uno de los tipos fundamentales de componentes.

Una simple operación es dibujada como una caja.

 An operation

Una secuencia de operaciones es representada por cajas conectadas con líneas. En el ejemplo siguiente, la operación A se compone de la secuencia de operaciones B, C y D.

 A sequence

Una iteración es representada de nuevo con cajas unidas. Además la iteración tiene una estrella en la esquina superior derecha de su caja. En el ejemplo siguiente, la operación A se compone de una iteración de cero o más invocaciones de la operación B.

 An iteration

La selección es similar a una secuencia, pero con un círculo dibujado en la esquina superior derecha de cada operación opcional. En el ejemplo, la operación A se compone de una y solo una de las operaciones B, C o D.

 A selection

Un ejemplo práctico editar

Como ejemplo, aquí es cómo un programador podría diseñar y codificar un codificador de longitud de ejecución usando JSP.

Un codificador de longitud de ejecución es un programa que toma como entrada un flujo de bytes. Tiene como salida un flujo de pares formados por un byte junto con un contador de las ocurrencias consecutivas del byte. Codificadores de longitud de ejecución se utilizan a menudo para comprimir crudamente mapas de bits.

Con JSP, el primer paso es describir la estructura de las entradas de un programa. Un codificador de longitud de ejecución solo tiene una entrada, una cadena de bytes que se pueden ver como cero o más carreras. Cada ejecución se compone de uno o más bytes del mismo valor. Esto está representado por el siguiente diagrama JSP.

 The run length encoder input

El segundo paso es describir la estructura de la salida. La salida del codificador de longitud de ejecución puede ser descrita como cero o más pares, cada par que consta de un byte y su contador. En este ejemplo, el contador será también un byte.

 The run length encoder output

El siguiente paso es describir las correspondencias entre las operaciones en las estructuras de entrada y salida.

 The correspondences between the run length encoders inputs and its outputs

Es en esta etapa que el programador astuto puede encontrar un conflicto en la estructura, en el que no hay una correspondencia obvia entre las estructuras de entrada y salida. Si se encuentra un conflicto en la estructura, por lo general es resuelto dividiendo el programa en dos partes, utilizando una estructura de datos intermedia para proporcionar un marco estructural común con la que las dos partes del programa pueden comunicarse. Las dos partes del programa se implementan a menudo como procesos o corrutinas.

En este ejemplo, no hay un conflicto en la estructura, por lo que las dos estructuras se pueden combinar para dar la estructura del programa final.

 The run length encoder program structure

En esta etapa el programa se puede concretarse en la horca diversas operaciones primitivas fuera de los elementos de la estructura. Primitivos que sugieren mismos son:

  1. leer un byte
  2. guardar un byte
  3. establecer contador a cero
  4. incrementar contador
  5. output remembered byte
  6. contador de salida

Las iteraciones también tienen que concretarse. Necesitan condiciones añadidas. Las condiciones adecuadas serían

  1. mientras haya más bytes
  2. mientras haya más bytes y este byte es el mismo que el primer byte de la carrera y el contador aún cabe en un byte

Si ponemos todo esto junto, podemos convertir el diagrama y las operaciones primitivas en C, manteniendo una correspondencia uno a uno entre el código y las operaciones y la estructura del diagrama de diseño de programas.

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    int c;

    c = getchar();
    while (c != EOF) {
        int count = 1;

        int first_byte = c;

        c = getchar();

        while (c != EOF && c == first_byte && count < 255) {
            count++;
            c = getchar();
        }

        putchar(first_byte);
        putchar(count);
    }
    return EXIT_SUCCESS;
}

Crítica editar

Este método funcionará solo cuando la traducción de la entrada a la salida es equivalente a una gramática libre del contexto.[cita requerida]

Véase también editar

Referencias editar

  1. Wieringa, R (Dec 1998), «A survey of structured and object-oriented software specification methods and techniques», Comput Surv (ACM) 30 (4): 459-527, doi:10.1145/299917.299919 ..
  2. Henderson-Sellers, Brian; Edwards, JM (Sep 1990), «The object-oriented systems life cycle», Commun (ACM) 33 (9): 142-59, doi:10.1145/83880.84529 ..
  3. a b Jackson, MA (1975), Principles of Program Design, Academic ..
  4. Ourusoff, Nicholas (2003). «Using Jackson Structured Programming (JSP) and Jackson Workbench to Teach Program Design» (PDF). InSite 2003. Informing Science. Archivado desde el original el 26 de julio de 2011. Consultado el 18 de febrero de 2008. 
  5. Orr, KT (1980), «Structured programming in the 1980s», Proceedings of the ACM 1980 Annual Conference, New York, NY: ACM Press, pp. 323-26 ..
  6. Warnier, JD (1974), Logical Construction of Programs, NY: Van Nostrand Reinhold ..
  7. Sorensen, K; Verelst, J (2001), «On the conversion of program specifications into pseudo code using Jackson structured programming», Journal of Computing and Information Technology 9 (1): 71-80, doi:10.2498/cit.2001.01.06 ..

Enlaces externos editar