stringtranslate.com

Programación estructurada de Jackson

Ejemplo de un diagrama JSP.

La programación estructurada de Jackson ( JSP ) es un método de programación estructurada desarrollado por el consultor de software británico Michael A. Jackson y descrito en su libro de 1975 Principios de diseño de programas . [1] La técnica de JSP es analizar las estructuras de datos de los archivos que un programa debe leer como entrada y producir como salida, y luego producir un diseño de programa basado en esas estructuras de datos, de modo que la estructura de control del programa maneje esas estructuras de datos. de forma natural e intuitiva.

JSP describe estructuras (tanto de datos como de programas) utilizando tres estructuras básicas: secuencia, iteración y selección (o alternativas). Estas estructuras están diagramadas como (en efecto) una representación visual de una expresión regular .

Introducción

Michael A. Jackson desarrolló originalmente JSP en la década de 1970. Documentó el sistema en su libro de 1975 Principios de diseño de programas . [1] En una conferencia de 2001, [2] proporcionó un análisis retrospectivo de las fuerzas impulsoras originales detrás del método y lo relacionó con desarrollos posteriores de ingeniería de software. El objetivo de Jackson era hacer que los programas de procesamiento de archivos por lotes COBOL fueran más fáciles de modificar y mantener, pero el método se puede utilizar para diseñar programas para cualquier lenguaje de programación que tenga estructuras de control estructuradas: secuencia, iteración y selección ("si/entonces/si no") .

La programación estructurada de Jackson era similar a la programación estructurada de Warnier/Orr [3] [4] aunque JSP consideraba estructuras de datos tanto de entrada como de salida, mientras que el método Warnier/Orr se centraba casi exclusivamente en la estructura del flujo de salida.

Motivación por el método.

En el momento en que se desarrolló JSP, la mayoría de los programas eran programas COBOL por lotes que procesaban archivos secuenciales almacenados en cinta. Un programa típico lee su archivo de entrada como una secuencia de registros, de modo que todos los programas tienen la misma estructura: un único bucle principal que procesa todos los registros del archivo, uno a la vez. Jackson afirmó que la estructura de este programa casi siempre era incorrecta y animó a los programadores a buscar estructuras de datos más complejas. En el Capítulo 3 de Principios de diseño de programas [1] Jackson presenta dos versiones de un programa, una diseñada usando JSP y la otra usando la estructura tradicional de bucle único. Aquí está su ejemplo, traducido de COBOL a Java. El propósito de estos dos programas es reconocer grupos de registros repetidos (líneas) en un archivo ordenado y producir un archivo de salida que enumere cada registro y el número de veces que aparece en el archivo.

Aquí está la versión tradicional de bucle único del programa.

Línea de cuerda ; recuento entero = 0 ; Cadena primeraLíneaDeGrupo = nulo ;       // comienza el bucle principal único while ( ( línea = in . readLine ()) != null ) { if ( firstLineOfGroup == null || ! line .quals ( firstLineOfGroup )) { if ( firstLineOfGroup != null ) { System . afuera . println ( primeraLíneaDeGrupo + " " + recuento ); } cuenta = 0 ; primeraLíneaDeGrupo = línea ; } contar ++ ; } if ( primeraLíneaDeGrupo ! = nulo ) { System . afuera . println ( primeraLíneaDeGrupo + " " + recuento ); }                                         

Aquí hay una versión estilo JSP del mismo programa. Tenga en cuenta que (a diferencia del programa tradicional) tiene dos bucles, uno anidado dentro del otro. El bucle externo procesa grupos de registros repetidos, mientras que el bucle interno procesa los registros individuales de un grupo.

Línea de cuerda ; int númeroDeLíneasEnGrupo ;  línea = en . leerLínea (); // comienza el bucle externo: procesa 1 grupo while ( línea ! = nulo ) { numberOfLinesInGroup = 0 ; Cadena primeraLíneaDeGrupo = línea ;               // comienza el bucle interno: procesa 1 registro en el grupo while ( línea ! = nulo && línea . igual ( firstLineOfGroup )) { numberOfLinesInGroup ++ ; línea = en . leerLínea (); } Sistema . afuera . println ( primeraLíneaDeGrupo + " " + númeroDeLíneasEnGrupo ); }                 

Jackson critica la versión tradicional de bucle único por no procesar la estructura del archivo de entrada (grupos repetidos de registros que contienen registros individuales repetidos) de forma natural. Una señal de su diseño antinatural es que, para funcionar correctamente, se ve obligado a incluir un código especial para manejar el primer y último registro del archivo.

El método básico

JSP utiliza pasos semiformales para capturar la estructura existente de las entradas y salidas de un programa en la estructura del programa mismo.

La intención es crear programas que sean fáciles de modificar a lo largo de su vida. La principal idea de Jackson fue que los cambios de requisitos suelen ser ajustes menores a las estructuras existentes. Para un programa construido usando JSP, las entradas, las salidas y las estructuras internas del programa coinciden, por lo que pequeños cambios en las entradas y salidas deberían traducirse en pequeños cambios en el programa.

JSP estructura los programas en términos de cuatro tipos de componentes:

El método comienza describiendo las entradas de un programa en términos de los cuatro tipos de componentes fundamentales. Luego continúa describiendo los resultados del programa de la misma manera. Cada entrada y salida se modela como un diagrama de estructura de datos (DSD) independiente. Para que JSP funcione en aplicaciones de computación intensiva, como el procesamiento de señales digitales (DSP), también es necesario dibujar diagramas de estructura de algoritmos, que se centran en las estructuras de datos internas en lugar de las de entrada y salida.

Luego, las estructuras de entrada y salida se unifican o fusionan en una estructura de programa final, conocida como diagrama de estructura del programa (PSD). Este paso puede implicar la adición de una pequeña cantidad de estructura de control de alto nivel para unir las entradas y las salidas. Algunos programas procesan todas las entradas antes de generar cualquier salida, mientras que otros leen un registro, escriben un registro e iteran. Estos enfoques deben reflejarse en el PSD.

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

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

Una operación simple se dibuja como un cuadro.


Una operación

Una secuencia de operaciones está representada por cuadros conectados con líneas. En el siguiente ejemplo, A es una secuencia que consta de las operaciones B, C y D.


Una secuencia

Una iteración se representa nuevamente con cuadros unidos. Además, la operación iterada tiene una estrella en la esquina superior derecha de su cuadro. En el siguiente ejemplo, A es una iteración de cero o más invocaciones de la operación B.


Una iteración

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, A es una selección de una y sólo una de las operaciones B, C o D.


Una selección

Tenga en cuenta que en los diagramas anteriores, es el elemento A el que es la secuencia o iteración, no los elementos B, C o D (que en los diagramas anteriores son todos elementales). Jackson da la 'regla de mirar hacia abajo' para determinar qué es un elemento, es decir, mirar los elementos debajo de un elemento para descubrir qué es.

Un ejemplo trabajado

Como ejemplo, aquí se muestra cómo un programador JSP diseñaría y codificaría un codificador de longitud de ejecución . Un codificador de longitud de ejecución es un programa cuya entrada es un flujo de bytes que puede considerarse que ocurre en ejecuciones , donde una ejecución consta de una o más apariciones de bytes del mismo valor. La salida del programa es un flujo de pares de bytes, donde cada par de bytes es una descripción comprimida de una ejecución. En cada par, el primer byte es el valor del byte repetido en una ejecución y el segundo byte es un número que indica el número de veces que ese valor se repitió en la ejecución. Por ejemplo, una ejecución de ocho apariciones de la letra "A" en el flujo de entrada ("AAAAAAAA") produciría "A8" como un par de bytes en el flujo de salida. Los codificadores de longitud de ejecución se utilizan a menudo para comprimir mapas de bits de forma tosca.

Con JSP, el primer paso es describir la(s) estructura(s) de datos de los flujos de entrada de un programa. El programa tiene solo un flujo de entrada, que consta de cero o más ejecuciones del mismo valor de byte. Aquí está el diagrama de estructura de datos JSP para el flujo de entrada.

El segundo paso es describir la estructura de datos de salida, que en este caso consta de cero o más iteraciones de pares de bytes.

El siguiente paso es describir las correspondencias entre los componentes de las estructuras de entrada y salida.

El siguiente paso es utilizar las correspondencias entre las dos estructuras de datos para crear una estructura de programa que sea capaz de procesar la estructura de datos de entrada y producir la estructura de datos de salida. (A veces esto no es posible. Consulte la discusión sobre conflictos de estructuras a continuación).

Una vez terminada la estructura del programa, el programador crea una lista de las operaciones computacionales que el programa debe realizar, y el diagrama de la estructura del programa se desarrolla colgando esas operaciones de los componentes estructurales apropiados.

  1. leer un byte
  2. recordar byte
  3. poner el contador a cero
  4. contador de incrementos
  5. byte recordado de salida
  6. contador de salida

Además, en esta etapa las condiciones de las iteraciones (bucles) y selecciones (si-entonces-declaraciones de caso) se enumeran y se agregan al diagrama de estructura del programa.

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

Una vez terminado el diagrama, se puede traducir a cualquier lenguaje de programación que se esté utilizando. Aquí hay una traducción al C.

#incluir <stdio.h> #incluir <stdlib.h>  int principal ( int argc , char * argv []) { int c ; int primer_byte ; recuento int ;           c = getchar (); /* obtener el primer byte */ while ( c != EOF ) { /* procesar el primer byte en la ejecución */ first_byte = c ; contar = 1 ; c = getchar (); /* obtener el siguiente byte */                    /* procesa los bytes siguientes en la ejecución */ while ( c != EOF && c == first_byte && count < 255 ) { /* procesa un byte del mismo valor */ count ++ ; c = getchar (); /* obtener el siguiente byte */ }                     putchar ( primer_byte ); putchar ( cuenta ); } devolver EXIT_SUCCESS ; }    

Técnicas para manejar problemas de diseño difíciles.

En Principios de diseño de programas, Jackson reconoció situaciones que planteaban tipos específicos de problemas de diseño y proporcionó técnicas para manejarlos.

Una de estas situaciones es un caso en el que un programa procesa dos archivos de entrada, en lugar de uno. En 1975, uno de los "problemas perversos" habituales era cómo diseñar un programa de procesamiento de transacciones. En dicho programa, un archivo secuencial de registros de actualización se ejecuta contra un archivo maestro secuencial, generando un archivo maestro actualizado como salida. (Por ejemplo, por la noche un banco ejecutaría un programa por lotes que actualizaría los saldos de las cuentas de sus clientes basándose en los registros de los depósitos y retiros que habían realizado ese día). Los Principios de Diseño de Programas proporcionaron una solución estándar para ese problema. , junto con una explicación de la lógica detrás del diseño.

Otro tipo de problema involucraba lo que Jackson llamó "dificultades de reconocimiento" y hoy llamaríamos problemas de análisis. La técnica básica de diseño JSP se complementó con operaciones POSIT y QUIT para permitir el diseño de lo que ahora llamaríamos un analizador de retroceso.

JSP también reconoció tres situaciones que se denominan "choques de estructuras" (un choque de límites, un choque de ordenamiento y un choque de intercalación) y proporcionó técnicas para abordarlas. En situaciones de conflicto de estructuras, las estructuras de datos de entrada y salida son tan incompatibles que no es posible producir el archivo de salida a partir del archivo de entrada. En efecto, es necesario escribir dos programas: el primero procesa el flujo de entrada, lo divide en fragmentos más pequeños y los escribe en un archivo intermedio. El segundo programa lee el archivo intermedio y produce el resultado deseado.

JSP y diseño orientado a objetos

JSP se desarrolló mucho antes de que estuvieran disponibles las tecnologías orientadas a objetos. Este y su método sucesor JSD no tratan lo que ahora se llamarían "objetos" como colecciones de métodos más o menos independientes. En cambio, siguiendo el trabajo de CAR Hoare , JSP y JSD describen los objetos de software como co-rutinas . [5] [6]

Ver también

Referencias

  1. ^ abc Jackson, MA (1975), Principios de diseño de programas , Académico.
  2. ^ Jackson, MA (2001), JSP en perspectiva (PDF) , Conferencia de pioneros de sd&m, Bonn, junio de 2001 , consultado el 26 de enero de 2017{{citation}}: Mantenimiento CS1: ubicación ( enlace ) Mantenimiento CS1: ubicación falta editor ( enlace )
  3. ^ Warnier, JD (1974), Construcción lógica de programas , Nueva York: Van Nostrand Reinhold
  4. ^ Orr, KT (1980), "Programación estructurada en la década de 1980", Actas de la conferencia anual de ACM 1980 , Nueva York, NY: ACM Press, págs. 323–26, doi :10.1145/800176.809987, ISBN 978-0897910286, S2CID  26834496
  5. ^ Wieringa, R (diciembre de 1998), "Un estudio de métodos y técnicas de especificación de software estructurado y orientado a objetos", Comput Surv , 30 (4): 459–527, CiteSeerX 10.1.1.107.5410 , doi :10.1145/299917.299919, S2CID  14967319 .
  6. ^ Henderson-Sellers, Brian ; Edwards, JM (septiembre de 1990), "El ciclo de vida de los sistemas orientados a objetos", Communications of the ACM , 33 (9): 142–59, doi : 10.1145/83880.84529 , S2CID  14680399.

enlaces externos