Desarrollando en Cobol y Natural sobre Plataforma Mainframe
Mostrando entradas con la etiqueta Cobol. Mostrar todas las entradas
Mostrando entradas con la etiqueta Cobol. Mostrar todas las entradas

lunes, 11 de abril de 2016

READ FILE: Leer fichero VSAM desde Cobol

Uno de los problemas relevantes con los que nos vamos a encontrar a menudo es la necesidad de acceder a un fichero VSAM para leer su contenido desde un programa Cobol. Este acceso no es tan sencillo como la lectura de una tabla DB2 y, por tanto, para su implementación tendremos que utilizar instrucciones CICS. Pero bueno, no hay que dejarse amedrentar por ello y en este post trataremos de explicar en detalle cómo realizar dicha operativa.

Leer fichero VSAM desde programa Cobol


En muchas ocasiones nos vamos a encontrar con que, desde un programa Cobol, tenemos que proceder a leer información que no está almacenada en ninguna tabla DB2 y que, en cambio, está contenida en un fichero VSAM. Para poder realizar esta función tendremos que recurrir a la instrucción CICS denominada READ FILE (o, en su codificación antigua, READ DATASET). Se trata de uno de los comandos básicos de acceso a ficheros.



Para ver cómo se debería implementar esta actuación vamos a revisar un ejemplo con el que me encontré hace algún tiempo. En él se trataba de leer los registros contenidos en un fichero VSAM denominado JJRPRTAK para luego tratarlos posteriormente en el programa Cobol.

05 COM2EZ-CLAVE.                                  
   10 COM2EZ-EIBTASK                      PIC 9(7).
   10 COM2EZ-JJEQ-IN-TIPELE               PIC X.  
   10 COM2EZ-JJEQ-NU-EXTERN               PIC 9(9).

05 W-RESP                    PIC S9(8) COMP  VALUE ZEROES.

...

EXEC CICS                  
   READ FILE('JJRPRTAK')
        INTO(COM2EZ) 

        LENGTH(COM2EZ-LONGITUD)      
        RIDFLD(COM2EZ-CLAVE)             
        RESP(W-RESP)       
END-EXEC. 


IF W-RESP NOT  = 0                                 
   MOVE W-CD-1             TO COM2JN-W-NMENSA      
   MOVE W-CD-MENSAJE-E0301 TO COM2JN-W-MENSA(W-CD-1)
   PERFORM 9999-ERROR THRU 9999-ERROR-FIN          
END-IF.
                                            

Como vemos, en el código anterior tenemos dos partes diferenciadas. En la primera parte aparece, entre los marcadores EXEC CICS y END-EXEC, el comando READ FILE y las cláusulas de las que se compone. Y en la segunda parte se muestra simplemente una de las formas (habría otras alternativas) en la que se podría implementar el control de errores asociado a la instrucción READ FILE.



Cláusulas de la instrucción CICS READ FILE


A la hora de implementar un READ FILE, lo  más importante es que tengamos claro a qué concepto corresponde cada una de las cláusulas del comando CICS. A continuación, vamos a ir examinando las sentencias de las que se compone la instrucción READ DATASET del ejemplo anterior.

1º) Instrucción READ: Este comando se emplea para indicarle al CICS que vamos a proceder con la lectura de un fichero VSAM.

2º) Cláusula FILE (o DATASET): En esta cláusula tenemos que indicar el nombre del fichero que queremos leer con la instrucción READ.

3º) Cláusula INTO: Aquí indicaremos el nombre de la variable del área de datos en la que queremos que se almacenen los campos del registro recuperado del fichero VSAM.

4º) Cláusula LENGTH: Aquí tendremos que especificar la longitud del área de datos en la que se va a capturar el registro del fichero VSAM.


5º) Cláusula RIDFLD: En esta importante cláusula tendremos que indicar el nombre de la variable de la clave por la que se tiene que buscar el registro en el fichero VSAM. Esto es, el READ del CICS buscará el registro cuya clave coincida con la que hemos especificado en RIDFLD y, una vez encontrado, nos lo devolverá para que almacenemos sus campos en la variable que habíamos indicado en INTO.

6º) Cláusula RESP: Aquí indicaremos el nombre de la variable en la que queremos capturar el código de retorno de la ejecución del comando CICS READ FILE.

7º) Control de errores: Finalmente, en la última intrucción IF validaremos si el retorno ha sido igual a cero (ejecución correcta) o distinto de cero (ejecución errónea). En este último caso procederemos a ejecutar el control de errores que consideremos necesario.

Una vez rellenadas las cláusulas anteriores, nuestra declaración EXEC CICS debería ejecutarse sin problema alguno. Como resultado de la misma se accedería al fichero indicado en FILE mediante la clave especidficada en la cláusula RIDFLD. Y posteriormente se cargaría el contenido de un registro del fichero VSAM en la variable especificada en la cláusula INTO, siempre y cuando se obtenga un código de retorno nulo en RESP.



Conclusiones acerca de la instrucción READ FILE


La instrucción READ FILE nos será muy útil en los casos en los que tengamos necesidad de acceder a los ficheros VSAM de una aplicación. Recordemos que los accesos a las tablas DB2 deben hacerse de otra forma diferente, tal y como ya vimos en el blog hace algún tiempo. Pero en el mundo host tan importantes son los VSAM como el DB2.

Hay que tener en cuenta que, al tratarse de un comando CICS, la instrucción READ FILE también podría ejecutarse directamente desde el entorno CICS. Esto se haría mediante el empleo de la transacción CECI. Tal y como ya sabemos, CECI nos permite, entre otras cosas, acceder tanto a ficheros VSAM como a colas TS y colas TD.

Si provisionamos las cláusulas tal y como hemos especificado más arriba, no deberíamos tener ningún problema a la hora de ejecutar nuestro programa Cobol. Pero, eso sí, si nunca habéis usado EXEC CICS READ FILE, entonces tendréis que tener un poco de paciencia, ya que a nadie le suelen funcionar los comandos CICS la primera vez que los usa.



En un futuro seguiremos viendo instrucciones CICS adicionales para operar con los ficheros VSAM desde programas Cobol. Aparte de leer, siempre son necesarias las operaciones de actualización, de inserción y de borrado. Pero, como digo, eso lo dejaremos para más adelante.

Así que eso es todo por hoy. Espero que os haya quedado claro cómo debemos emplear el comando CICS READ FILE. Si seguís teniendo alguna duda, la podéis dejar en el apartado de comentarios.

Saludos.

lunes, 26 de octubre de 2015

Comando COMPUTE para Cobol

Como en todos los lenguajes, en Cobol también disponemos de un comando específico que nos permite realizar operaciones matemáticas entre operandos. Eso sí, debido a que nuestro lenguaje no está pensado para su utilización en entornos científicos, en las rutinas que elaboremos sólo podremos incluir operaciones aritméticas sencillas.

Ejecución de operaciones matemáticas en Cobol


Seguro que, en más de una ocasión, os habéis encontrado con una situación en la que el algoritmo de una determinada funcionalidad os ha obligado a implementar alguna operación matemática. Para acometer tareas de este tipo, en lenguaje Cobol disponemos de los comandos ADD, SUBTRACT, MULTIPLY y DIVIDE (sumar, restar, multiplicar y dividir).

Pero, si queremos implementar fórmulas algo más complejas, podemos recurrir al comando COMPUTE. Esta función nos permitiría incluir, en una misma declaración, la ejecución de múltiples operaciones sobre operandos diversos. De este modo, podremos realizar sumas, restas, multiplicaciones y divisiones en la misma sentencia.


Como vemos, se trata de un comando bastante estándar. De hecho, hay varios lenguajes de programación en los que esta función se denomina del mismo modo: COMPUTE. Sin ir más lejos, así ocurre en Natural ADABAS, otro de los lenguajes de los que solemos hablar de vez en cuando en el blog.

¿Cómo se implementa una sentencia COMPUTE?


A continuación vamos a ver un ejemplo de cómo se debería implementar la sentencia COMPUTE dentro de un párrafo de Cobol. Obviamente, el número de combinaciones para esta función es muy elevado pero, para facilitar su explicación, centrémonos en la siguiente fórmula modelo que se compone de 3 operadores y de 8 variables.

DATA DIVISION.
WORKING-STORAGE SECTION.

01 W-PTOS-CALCULADOS           PIC 9(5).

01 W-DISTANCIAS-ABS.                                   
  05 W-REGL-NU-COORDX-DESDE    PIC  9(5)     VALUE ZEROES.
  05 W-REGL-NU-COORDY-DESDE    PIC  9(5)     VALUE ZEROES.
  05 W-PTCO-NU-COORDX-DESDE    PIC  9(5)     VALUE ZEROES.
  05 W-PTCO-NU-COORDY-DESDE    PIC  9(5)     VALUE ZEROES.

  05 W-REGL-NU-COORDX-HASTA    PIC  9(5)     VALUE ZEROES.
  05 W-REGL-NU-COORDY-HASTA    PIC  9(5)     VALUE ZEROES.
  05 W-PTCO-NU-COORDX-HASTA    PIC  9(5)     VALUE ZEROES.
  05 W-PTCO-NU-COORDY-HASTA    PIC  9(5)     VALUE ZEROES.


...

PROCEDURE DIVISION.

COMPUTE  W-PTOS-CALCULADOS  =    
   (W-REGL-NU-COORDX-HASTA -     
    W-REGL-NU-COORDX-DESDE + 1 ) *
   (W-REGL-NU-COORDY-HASTA -     
    W-REGL-NU-COORDY-DESDE + 1 ) *
   (W-PTCO-NU-COORDX-HASTA -     
    W-PTCO-NU-COORDX-DESDE + 1 ) *
   (W-PTCO-NU-COORDY-HASTA -     
    W-PTCO-NU-COORDY-DESDE + 1 ).   


Como se aprecia, en la declaración anterior se están usando 8 variables y 3 operadores aritméticos: suma, resta y multiplicación. De este modo nos evitamos tener que emplear 3 sentencias distintas con los comandos ADD, SUBTRACT y MULTIPLY y, al mismo tiempo, nos ahorramos la definición de algunas variables auxiliares que hubiésemos tenido que utilizar en el caso de no recurrir al comando COMPUTE.


Por lo que respecta a la fórmula en sí misma, entiendo que es muy sencilla y que no hace falta recurrir a ninguna explicación adicional de la misma. Básicamente, se están calculando las diferencias entre varias coordenadas y multiplicando dichas distancias entre sí para obtener un valor denominado "Puntos Calculados" (variable que, una vez visto el ejemplo, ya no tiene interés para nosotros y que se usará posteriormente en el algoritmo del programa Cobol CICS).

Aprendiendo a utilizar el comando COMPUTE


Una vez visto cómo hemos realizado la declaración en nuestro ejemplo, no deberíais tener problemas a la hora de extrapolar su empleo a vuestros propios programas. Se trata de un comando estándar cuya utilización es bastante intuitiva y, según mi experiencia, no suele causar demasiadas dificultades a los programadores principiantes.

Por si acaso, y teniendo en cuenta que un ejemplo práctico vale más que 1.000 palabras de teoría, a continuación paso a incluir algunas sentencias más con posibles usos del comando. A partir de ellos, se pueden elaborar otras 1.000 variantes diferentes, de manera que no vamos a tener problemas para encontrar la opción que encaje con el que requiera nuestro algoritmo.

COMPUTE W-TOTAL-1 = W-OPERANDOS-1 + W-OPERANDOS-2

COMPUTE W-TOTAL-2 = W-OPERANDOR-1 - W-OPERANDOR-2

COMPUTE W-TOTAL-3 = W-OPERANDOM-1 * W-OPERANDOM-2

COMPUTE W-TOTAL-4 = W-OPERANDOD-1 / W-OPERANDOD-2

COMPUTE W-TOTAL-5 = (W-OPERANDOSD-1 + W-OPERANDOSD-2) / (W-OPERANDOSD-3 - W-OPERANDOSD-4)

COMPUTE W-TOTAL-6 = (W-OPERANDODM-1 / W-OPERANDODM-2) * (W-OPERANDODM-3 / W-OPERANDODM-4)

COMPUTE W-TOTAL-7 = (W-OPERANDORD-1 - W-OPERANDORD-2) / W-OPERANDORD-3

COMPUTE W-TOTAL-8 = (W-OPERANDOSM-1 + 1) * (W-OPERANDOSM-2 / W-OPERANDOSM-3) * ((W-OPERANDOSM-4 - W-OPERANDOSM-5) / W-OPERANDOSM-6)

Como vemos, las construcciones con COMPUTE se pueden ir incrementando de dificultad de forma indefinida. Esto nos va a facilitar la incorporación de la complejidad requerida a nuestras fórmulas, siempre y cuando no nos salgamos del catálogo de operaciones aritméticas básicas. En mi propia experiencia, el comando COMPUTE es más que suficiente para implementar la mayoría de las fórmulas requeridas en los algoritmos de los programas Cobol CICS DB2.


En definitiva, tenemos que considerar al COMPUTE como una sentencia de elaboración de fórmulas aritméticas que nos va a permitir ahorrar tiempo y código a la hora de desarrollar. Por un lado, su uso nos permitirá sustituir a los comandos ADD, SUBTRAC, MULTIPLY y DIVIDE; por otro lado, reduciremos el número de variables auxiliares precisadas para operar.

Y eso es todo por hoy. Espero que lo comentado os sirva para resolver todas las dudas que tengáis acerca del comando COMPUTE y que os facilite vuestra labor con el cliente. De todas formas, ya sabéis que podéis dejarme cualquier comentario aquí abajo y os lo responderé lo antes posible...

Saludos.

jueves, 16 de abril de 2015

Como obtener la fecha del sistema en Cobol

Una rutina típica que suele tener todo programa Cobol es la de recuperación de la fecha y la hora actual del sistema. Se trata de una información muy útil generalmente precisada para su inclusión en los informes solicitados por el usuario o para indicar la fecha de actualización de los datos en las tablas DB2 (TIMESTAMP).

Aunque hay varias alternativas, una forma estándar de obtener la fecha en Cobol es mediante la utilización de los comandos CICS ASKTIME y FORMATTIME. Con unas pocas operaciones, estas instrucciones nos permiten disponer de una variable fecha (y hora) formateada según las necesidades de nuestra aplicación.



A continuación, vamos a ver un ejemplo en Cobol de cómo se podría recuperar la fecha y dejarla cargada en una variable de trabajo. Supongamos, en primer lugar, que tenemos definidas las siguientes variables en nuestra WORKING-STORAGE SECTION.

05  W-FECHA-HORA-SISTEMA  PIC   S9(15) COMP-3 VALUE   0.
05  W-ANNO-SISTEMA        PIC   S9(8)  COMP   VALUE   0.
05  W-MES-SISTEMA         PIC   S9(8)  COMP   VALUE   0.
05  W-DIA-SISTEMA         PIC   S9(8)  COMP   VALUE   0.


05  W-HORA-SISTEMA.                                  
    10  W-HH-SISTEMA      PIC    9(2)      VALUE    0.
    10  FILLER            PIC    X         VALUE  '.'.
    10  W-MM-SISTEMA      PIC    9(2)      VALUE    0.
    10  FILLER            PIC    X         VALUE  '.'.
    10  W-SS-SISTEMA      PIC    9(2)      VALUE    0.


05  W-FECHA-SISTEMA.                                 
    10  W-ANNO            PIC    9(4)      VALUE    0.
    10  FILLER            PIC    X         VALUE  '-'.
    10  W-MES             PIC    9(2)      VALUE    0.
    10  FILLER            PIC    X         VALUE  '-'.
    10  W-DIA             PIC    9(2)      VALUE    0.

05  W-TIMESTAMP.                                       
    10  W-FECHA-SYS       PIC    X(10)     VALUE SPACES.
    10  FILLER            PIC    X(1)      VALUE '-'.  
    10  W-HORA-SYS        PIC    X(8)      VALUE SPACES.
    10  FILLER            PIC    X(1)      VALUE '-'.  
    10  W-MILISEG-SYS     PIC    9(6)      VALUE 0.    


La idea es recuperar la fecha del CICS en el parámetro W-FECHA-HORA-SISTEMA y, tras las operaciones pertinentes, dejar preparada la fecha/hora del sistema en W-TIMESTAMP. Esta última variable podrá ser utilizada para provisionar los campos TIMESTAMP de los registros de las tablas DB2 que sean modificados por nuestro programa.

A continuación, mostramos un código que podría ser incluido en una rutina Cobol para realizar la transformación comentada. Obviamente, no es la única solución que podría ser implementada.

EXEC CICS                        
     ASKTIME                     
     ABSTIME(W-FECHA-HORA-SISTEMA)
END-EXEC                         
                                 
EXEC CICS                        
     FORMATTIME                  
     ABSTIME(W-FECHA-HORA-SISTEMA)
     YEAR(W-ANNO-SISTEMA)        
     MONTHOFYEAR(W-MES-SISTEMA)  
     DAYOFMONTH (W-DIA-SISTEMA)  
     TIME(W-HORA-SISTEMA)        
     TIMESEP('.')                
END-EXEC.                        

MOVE W-DIA-SISTEMA  TO  W-DIA              
MOVE W-MES-SISTEMA  TO  W-MES              
MOVE W-ANNO-SISTEMA TO  W-ANNO.            
                                           
MOVE W-FECHA-SISTEMA      TO W-FECHA-SYS   
MOVE W-HORA-SISTEMA       TO W-HORA-SYS    
MOVE W-FECHA-HORA-SISTEMA TO W-MILISEG-SYS.

Una vez visto el código completo, pasamos a detallar un poco cuál sería el objetivo de cada uno de los bloques desarrollados.

1º) En primer lugar, se emplea el comando CICS ASKTIME para recuperar la fecha y hora actual del sistema.

2º) La cláusula ABSTIME permite almacenar (en una variable) la fecha del sistema con un formato conocido como tiempo absoluto. Dicho formato especifica la cantidad de milisegundos transcurridos desde el inicio del año 1900 hasta el momento actual.

3º) El comando FORMATTIME transforma una fecha de tiempo absoluto en una fecha y hora con el formato que deseemos.



4º) En el ejemplo anterior se obtienen varios elementos de la variable de tiempo absoluto. Con YEAR, MONTHOFYEAR y DAYOFMONTH se extraen de ella el año, el mes y el día, respectivamente. Finalmente, con TIME extraemos la hora del reloj y con TIMESEP especificamos el separador deseado entre horas, minutos y segundos.

5º) A continuación, transferimos los datos extraídos de día, mes y año a una variable W-FECHA-SISTEMA donde guardaremos la información con el formato que deseemos.

6º) Finalmente, movemos la fecha del sistema, la hora del sistema y el tiempo absoluto en milisegundos a una variable W-TIMESTAMP. Esta variable será la que se use para almacenar el TIMESTAMP en los registros que nuestro programa Cobol precise modificar en las tablas DB2.

Aunque aparentemente parecen demasiados pasos para la elaboración de una rutina tan básica, la realidad es que, una vez codificada, podremos ir copiándola sin más de un programa a otro. Se trata de un párrafo que no necesitará modificaciones adicionales, salvo que queramos cambiar el formato de la fecha obtenida.



Como vemos, aquí tenemos un método estándar para crear una fecha/hora de sistema y para disponer de un TIMESTAMP en los programas Cobol. La primera funcionalidad es muy útil para mostrar información a los usuarios y la segunda resulta imprescindible si queremos mantener una trazabilidad de las modificaciones que se vayan realizando en las tablas DB2. Si todavía no estáis de acuerdo con ello, os aseguramos que tarde o temprano lo estaréis.

Pues nada, eso es todo lo que queríamos comentaros por hoy. Esperamos que esta rutina de captura de fecha de sistema os sea útil y que podáis emplearla frecuentemente en vuestros propios objetos.

Saludos.

jueves, 19 de febrero de 2015

Tipos de Colas CICS (y 2)

Hace algunas semanas comenzamos a ver en qué consistían las Colas CICS y cuáles eran los tipos que nos podíamos encontrar en un sistema Mainframe. Básicamente, las colas son un soporte de almacenamiento alternativo a los ficheros secuenciales, a los ficheros VSAM y a las tablas DB2.

En la primera parte del post ya estuvimos revisando las Colas TS - Temporary Storage (ver post Tipos de Colas CICS - 1). Sin embargo, nos quedó pendiente examinar el funcionamiento del otro gran grupo de este género de entidades: las Colas TD - Transient Data.

Colas TD: Transient Data Queue

Las Colas TD son un tipo de almacenamiento que, en su origen, se usaba fundamentalmente para implementar las colas de impresión. Actualmente suelen ser utilizadas como soporte de memoria para procesos batch: con cierta periodicidad, los demonios recogen los datos de la cola y realizan un tratamiento con ellos. Por supuesto, también pueden ser empleadas como simples ubicaciones de memoria para nuestros procesos on-line.

Los registros guardados en una Cola TD, tal y como ocurría con los de las Colas TS, son de longitud variable y se denominan items. En este caso son almacenados y recuperados de forma secuencial.

A diferencia de las TS, las Colas TD tienen que ser creadas y definidas antes de poder ser utilizadas en un programa Cobol. Junto a esto, la otra diferencia importante es que, conforme vamos recuperando la información, los items extraídos se van borrando automáticamente de la Cola TD.



Las Colas TD pueden ser de dos tipos:

- Tipo Extra-Partition: Este tipo de colas, que tienen que ser definidas como de entrada o de salida, permiten intercambiar datos con ubicaciones exteriores a nuestra región CICS. Es decir, con una Cola Extra-Partition podríamos enviar datos a un demonio externo o recoger los datos generados por un proceso batch externo.

- Tipo Intra-Partition: Estas Colas TD se almacenan en un espacio de memoria interno de nuestro CICS y admiten el procesamiento ATI (Automatic Transaction Initiation). Dicha técnica permite lanzar de forma automática (sin intervención alguna del usuario) una transacción CICS predefinida cuando en la Cola TD se acumule un número determinado de items.



En resumen, hemos visto que en el sistema CICS disponemos de varios tipos de Colas para afrontar las diversas opciones de procesamiento que nos podemos encontrar en una aplicación. Por un lado, las Colas TS (Main y Auxiliary) nos permitirán almacenar información que va a ser requerida de forma temporal por nuestros programas Cobol. Y por otro lado, las Colas TD (Extra-Partition e Intra-Partition) nos permitirán realizar procesamientos ATI o implementar procesos batch de intercambio de datos con otros CICS.

Las Colas son un tipo adicional de soporte de almacenamiento utilizable en los sistemas CICS, una opción más que se une a las ya conocidas de ficheros secuenciales, ficheros VSAM y tablas DB2. Ya será decisión nuestra, en función de las necesidades, usar uno u otro tipo en los programas Cobol.



Por supuesto, la única forma de aprender a utilizar las Colas es practicando con ellas. Aunque su uso pueda parecer un poco extraño al principio (sobre todo si estamos acostumbrados a operar con ficheros y tablas DB2), la realidad es que su operativa es tan sencilla como pueda serlo la del resto de tipos de almacenamiento.

Esperamos que, con todo lo comentado en el post, queden resueltas todas las dudas que os puedan surgir con relación a las Colas CICS. Si no es así, se aceptan preguntas...

Saludos.

jueves, 12 de febrero de 2015

Tipos de Colas CICS (1)

Las Colas CICS son instrumentos auxiliares que se utilizan para almacenar datos (fundamentalmente de forma temporal) que, con posterioridad, podrán ser empleados por nuestros programas Cobol. Cada una de las unidades de información guardadas en dichas Colas se denomina item (de manera análoga a lo que sería el registro de un fichero).

Las Colas CICS son ampliamente utilizadas para el intercambio de datos temporales entre varios programas Cobol (o incluso dentro de un mismo programa). De esta forma, evitamos sobrecargar los ficheros secuenciales, los ficheros VSAM o las tablas DB2 con información de vida efímera.

En un primer nivel, las Colas se dividen en dos tipos principales: Colas TD (Transient Data Queue) y Colas TS (Temporary Storage Queue). A continuación, pasamos a verlas en detalle.


Colas TS: Temporary Storage Queue

Las Colas TS, tal y como su nombre indica, sirven para almacenar información temporalmente y suelen ser utilizadas para la paginación de los datos mostrados por los programas Cobol. Los registros que se guardan en ellas son de longitud variable y se denominan items.

La ventaja de este tipo de Colas es que no es necesario que estén predefinidas con anterioridad a la ejecución de nuestra aplicación. Es decir, si en un objeto Cobol indicamos que queremos almacenar información en una Cola TS inexistente (con el comando WRITEQ, por ejemplo), la entidad se creará automáticamente en el momento en que se ejecute la instrucción del programa.

Los items de la Cola pueden ser recuperados de forma secuencial o directa y, una vez dados de alta, también podrían ser modificados. Finalmente, comentar que la información permanecerá almacenada en la Cola hasta que los items no sean borrados explícitamente (con el comando DELETEQ, por ejemplo).



Las Colas TS pueden ser de dos tipos:

- Tipo Main: Se almacenan en la memoria principal. Son el tipo más común de Cola TS, ya que su creación es viable en cualquier sistema CICS.

- Tipo Auxiliary: Utilizarán como soporte de almacenamiento una memoria temporal auxiliar. Este tipo de Colas TS se podrá crear siempre y cuando nuestro sistema CICS permita el uso de memoria auxiliar.

El próximo día continuaremos viendo el segundo tipo de Colas CICS, las Transient Data Queue, y haremos hincapié en las características específicas que las distinguen de las Colas TS. Tal y como veremos, hay algunas diferencias importantes en el comportamiento de ambas entidades, cosa que deberá ser tenida en cuenta a la hora de implementar su uso en los programas Cobol.

Pues nada más. Os invitamos a que leaís la segunda parte del post, donde terminaremos de revisar los tipos de Colas CICS existentes. Con ello nos debería quedar una idea bastante clara que nos ayude a entender qué son estas entidades.

Saludos.

jueves, 23 de octubre de 2014

Herramienta DCLGEN para generar Includes de DB2 (y 2)

Hace unas semanas comenzamos a ver cuáles eran los pasos a seguir para generar objetos DCL mediante la Herramienta DCLGEN (ver post Herramienta DCLGEN para generar Includes de Ficheros - 1). Hoy trataremos de ver qué es lo que tenemos que hacer para utilizar dichos objetos desde nuestros programas Cobol.

Tal y como estuvimos viendo, siguiendo el procedimiento indicado, la herramienta DCLGEN nos generaba un objeto en una librería de nuestra elección. Al final del anterior post llegamos a mostrar un ejemplo de cómo era el contenido de un objeto DCL que habíamos generado con el nombre SEQUIPOS.



Como se podía observar en dicho ejemplo, el código de un objeto DCL está dividido en 3 partes:

A) Estructura de la Tabla DB2. En esta primera parte nos aparece el nombre de la tabla DB2  y de las columnas que la componen. Estos son los nombres de columna que tendremos que usar en las sentencias SQL que usemos en nuestro programa Cobol.

B) Estructura de Variable Host. En esta segunda parte nos aparece la definición de todas las variables Host que podríamos utilizar en el programa Cobol. Básicamente, el DCLGEN habrá creado una variable Host equivalente a cada una de las columnas de la tabla DB2. La idea es que podamos usar cada una de estas variables de la agrupación DCLEQUIPOS para recoger la información de la columna de nombre análogo de la tabla DB2.

C) Estructura de Variables Indicador. En la tercera y última parte se habrán creado las Variables de Indicador Nulo asociadas a cada una de las variables Host que lo requieran. Se da de alta un array INDSTRUC cuyo tamaño será igual al número de columnas de la tabla DB2 (en el ejemplo, se crea un INDSTRUC de 5 ocurrencias debido a que la tabla EQUIPOS tiene 5 columnas).

Para que toda la estructura de datos creada está disponible desde Cobol, en el programa tendremos que incluir la correspondiente sentencia INCLUDE haciendo referencia al objeto DCL. En nuestro ejemplo, en la WORKING-STORAGE SECTION tendríamos que incluir tanto las del área de comunicaciones estándar SQLCA como las de nuestro objeto SEQUIPOS.

* INCLUDES DE LOS OBJETOS DCL
EXEC SQL      
  INCLUDE SQLCA
END-EXEC.

*      
EXEC SQL      
  INCLUDE SEQUIPOS
END-EXEC.     


Con la definición anterior, un ejemplo de cómo se codificaría, en un programa Cobol, una declaración SELECT contra la tabla EQUIPOS empleando el objeto DCL sería la siguiente. En primer lugar, ponemos la definición del Cursor de la tabla (que estaría en la WORKING-STORAGE SECTION) y, a continuación, la sentencia FETCH que carga la información en las variables Host (ubicada en la PROCEDURE DIVISION).

* CURSOR PARA POSICIONARSE EN LA TABLA EQUIPOS
EXEC SQL DECLARE EQUIPOS-C CURSOR FOR
  SELECT *                        
  FROM   EQUIPOS                    
  WHERE EQUINO = :ENO              
  ORDER BY EQUINAME               
END-EXEC.                           


...
...
...

* OBTENCION DE COLUMNAS DE REGISTRO DE LA TABLA EQUIPOS
EXEC SQL                       
         FETCH EQUIPOS-C        
         INTO                  
         :EQUINO,           
         :EQUINAME,           
         :ENTNO, 
         :EMPREQUI,              
         :CITYNAME
END-EXEC.
                       

Como vemos, en el FETCH se está haciendo referencia a las variables Host que aparecen en el objeto DCL definidas bajo la agrupación DCLEQUIPOS (en el DECLARE CURSOR que aparece justo encima, por contra, se hace referencia a los nombres de las columnas de la tabla DB2). Una vez recuperadas, ahora ya podremos trabajar normalmente con estas variables Host en el código de nuestro programa Cobol. Por ejemplo, podríamos hacer un DISPLAY así.

DISPLAY EQUINO EQUINAME ENTNO EMPREQUI CITYNAME

Como se puede observar, el empleo de la herramienta DCLGEN nos ahorra mucho trabajo a la hora de definir, en nuestros programas Cobol, las estructuras de las tablas DB2 y las estructuras de sus variables Host asociadas. Esto mismo se podría declarar de forma manual, pero es indudable que haciéndolo mediante la herramienta nos ahorraremos quebraderos de cabeza.

Siguiendo los pasos que se han ido indicando en el post, no deberíamos tener ningún problema con la generación de los objetos DCL a través de la herramienta DCLGEN. Quizás os parezca un poco complicado la primera vez, pero os podemos asegurar que enseguida dominaréis el procedimiento y que agradeceréis el tiempo economizado.

En principio, con todo lo comentado, por nuestra parte quedaría completado el tema de la herramienta DCLGEN. De todas formas, no dudéis en consultarnos cualquier duda que os surja respecto a ella, si lo consideráis oportuno.

Saludos.

jueves, 16 de octubre de 2014

Herramienta DCLGEN para generar Includes de DB2 (1)

Cuando estamos implementando un programa Cobol con acceso a DB2, una de las cosas que tenemos que incluir en el mismo es la declaración de las tablas DB2, junto con todos los campos que las componen, y la declaración de las variables auxiliares que vamos a emplear para recoger los registros de dichas tablas. El DCLGEN nos permitirá crear de forma automática toda esta estructura de datos.

La herramienta DCLGEN sirve para realizar la generación de objetos DCL. El DCL (Data Control Language) es la parte del lenguaje SQL destinada al control de los datos. Así que, dicho de otro modo, el DCLGEN nos permite realizar la generación de la parte del código SQL que contiene las variables necesarias para el tratamiento de las tablas DB2 desde los programas Cobol.

Obviamente, estas sentencias DCL también se podrían generar manualmente, pero siempre será más cómodo realizar la tarea mediante un generador automático como el DCLGEN. Una vez hayamos aprendido cómo se opera con él, lo más probable es que nunca dejemos de usarlo.



Los pasos a seguir para realizar la generación de un objeto con código DCL son los siguientes, suponiendo que nos encontramos en el menú principal POM (Primary Option Menu) del ISPF.

1º) Seleccionamos la opción 12 - Subsystems - DB/DC Subsystems. Se nos abrirá una ventana mostrando las diversas opciones disponibles.

12 Subsystems    DB/DC Subsystems 

2º) Opción D - DB2I: Seleccionamos la opción D - DB2I - Interactive Database 2. Así entraremos en el menú principal (POM) de la herramienta DB2I.

D  DB2I      Interactive Database 2   

3º) Opción 2 - DCLGEN: Seleccionamos la opción 2 - DCLGEN - Generate SQL and source language declarations.

2  DCLGEN      (Generate SQL and source language declarations)

4º) En el panel DCLGEN tendremos que introducir los parámetros requeridos para la generación del objeto DCL.

- SOURCE TABLE NAME: Aquí tendremos que introducir el nombre de la tabla para la cual deseamos que se genere su objeto DCL asociado. Por ejemplo, nosotros especificamos la tabla EQUIPOS.

1  SOURCE TABLE NAME ===> EQUIPOS

- TABLE OWNER: Aquí habrá que especificar el nombre del usuario propietario de la tabla.

2  TABLE OWNER ..... ===> SYSTEM1

- DATA SET NAME: En este campo se debe especificar el nombre (y la ubicación) del objeto DCL que va a generar la herramienta DCLGEN. Por ejemplo, nosotros queremos un objeto llamado SEQUIPOS que deberá crearse en la librería JJ00.FACTURAS.DCLGEN.DATA.

4  DATA SET NAME ... ===> 'JJ00.FACTURAS.DCLGEN.DATA(SEQUIPOS)'

- ACTION: Se provisionará el comando ADD si vamos a generar un nuevo objeto DCL o el comando REPLACE si se va a cambiar la estructura de un objeto ya existente.

6  ACTION .......... ===> REPLACE 

- INDICATOR VARS: Si queremos que nuestro objeto DCL incluya la declaración de las Variables de Indicador Nulo para los campos de la tabla que lo requieran, entonces tendremos que indicar YES en este parámetro.

12  INDICATOR VARS .. ===> YES

5º) Tras especificar todos los parámetros anteriores y pulsar INTRO, nos aparecerá un mensaje indicando que la generación se ha llevado a cabo correctamente.

DSNE904I EXECUTION COMPLETE, MEMBER SEQUIPOS REPLACED
***
  
                                               

A continuación, iríamos a la librería especificada en DATA SET NAME (en nuestro ejemplo, la JJ00.FACTURAS.DCLGEN.DATA) y podríamos verificar la existencia del nuevo objeto DCL generado.

Si nos asomamos al interior del objeto, veremos que su contenido tendrá un aspecto similar al siguiente:

******************************************************************
* DCLGEN TABLE(SYSTEM1.EQUIPOS)                                  *
*        LIBRARY(JJ00.FACTURAS.DCLGEN.DATA(SEQUIPOS))            *
*        LANGUAGE(COBOL)                                         *
*        QUOTE                                                   *
*        INDVAR(YES)                                             *
* ... IS THE DCLGEN COMMAND THAT MADE THE FOLLOWING STATEMENTS   *
******************************************************************
     EXEC SQL DECLARE EQUIPOS TABLE                     
     ( EQUINO                         CHAR(3) NOT NULL,          
       EQUINAME                       VARCHAR(36) NOT NULL,      
       ENTNO                          CHAR(6),                   
       EMPREQUI                       CHAR(3) NOT NULL,          
       CITYNAME                       VARCHAR(16)                
     ) END-EXEC.                                                 
******************************************************************
* COBOL DECLARATION FOR TABLE SYSTEM1.EQUIPOS                    *
******************************************************************
 01  DCLEQUIPOS.                                                

     10 EQUINO               PIC X(3).                           
     10 EQUINAME.                                                
        49 EQUINAME-LEN      PIC S9(4) USAGE COMP.               
        49 EQUINAME-TEXT     PIC X(36).                          
     10 ENTNO                PIC X(6).                           
     10 EMPREQUI             PIC X(3).                           
     10 CITYNAME.                                                
        49 CITYNAME-LEN      PIC S9(4) USAGE COMP.               
        49 CITYNAME-TEXT     PIC X(16).                          
******************************************************************
* INDICATOR VARIABLE STRUCTURE                                   *
******************************************************************
 01  IEQUIPOS.                                                  
     10 INDSTRUC           PIC S9(4) USAGE COMP OCCURS 5 TIMES.  
******************************************************************
* THE NUMBER OF COLUMNS DESCRIBED BY THIS DECLARATION IS 5       *
******************************************************************


El próximo día seguiremos viendo el procedimiento que hay que seguir para poder hacer uso del contenido del objeto DCL desde el programa Cobol en el que vamos a operar con el fichero DB2. Recordemos que, al fin y al cabo, la finalidad del DCL es que nos facilite el intercambio de información entre el entorno SQL DB2 y el entorno Host Cobol.

Dicho esto, ya sólo nos queda emplazaros a la segunda parte del post, donde terminaremos de ver la forma en que debe utilizarse la herramienta DCLGEN. Disfrutad del Cobol mientras tanto.

Saludos.

jueves, 9 de octubre de 2014

Estructura básica de un programa Cobol (y 2)

Hace algunas semanas comenzamos a repasar la configuración estándar de un programa Cobol (ver post Estructura básica de un programa Cobol - 1). Aunque vimos unas cuantas secciones del código, nos quedaron pendientes otras tantas para completar la revisión de la estructura.

Recordemos que un programa Cobol está organizado en 4 Divisiones principales. De ellas, en la primera parte del post vimos la "Identification Division" y la "Environment Division". A continuación, completaremos la revisión de la estructura viendo las secciones y párrafos de las dos Divisiones restantes.

 

3º) DATA DIVISION

Esta División es, quizás, la más compleja de la programación Cobol, ya que se compone de varias secciones que no resultan del todo intuitivas para los programadores de otros lenguajes más modernos.

DATA DIVISION

A) FILE SECTION

Aquí se definirá la estructura de los ficheros especificados en la INPUT-OUTPUT-SECTION y también habrá que detallar los campos en los que se desglosan los registros asociados a cada uno de dichos ficheros.

   FILE SECTION
      ...
      FICHERO
         REGISTRO
      ... 

B) WORKING-STORAGE SECTION

Aquí deben definirse todas las variables que van a usarse en la lógica procedimental del programa. Se incluyen tanto las variables estándar como las variables auxiliares que se emplearán para trabajar con la información descargada de los ficheros.

   WORKING-STORATE SECTION
      ...
      VARIABLE
      ...

C) LINKAGE SECTION

Aquí se deberán indicar los parámetros (variables) con los que debe invocarse nuestro fuente si es llamado desde otro objeto. Lógicamente, esta sección sólo se usará si estamos codificando un subprograma que debe ser invocado, mediante unos parámetros determinados, por otros objetos de la aplicación.

   LINKAGE SECTION
      ...
      PARAMETRO
      ... 

4º) PROCEDURE DIVISION

Finalmente llegamos a la última División de la estructura de un programa Cobol. En ella tendremos que definir las secciones y párrafos (esto es, las subrutinas) en las que queramos dividir nuestro objeto y, en cada una de ellas, se deberán incluir las sentencias (esto es, las instrucciones) requeridas para la correcta implementación del algoritmo de nuestro programa.

Por supuesto, en la DATA DIVISION tienen que estar definidas todas las variables con las que vayamos a operar en la PROCEDURE DIVISION.

PROCEDURE DIVISION
   ...
   SECCION
      PARRAFO
         SENTENCIA
   ...

Obviamente, la elaboración de un programa Cobol tiene más complejidad que la detallada a lo largo de todo el artículo. Sin embargo, esta estructura básica nos puede servir de guía cuando realicemos la creación de nuestros primeros objetos Cobol. Y esa era la idea del post, servir de ayuda a los programadores novatos.

Como hemos dicho al principio, no hay que desanimarse por la aparente rigidez del Cobol. Todos los lenguales tienen sus particularidades y eso puede hacer que, al principio, nos parezca extraña la forma en que se realiza el tratamiento de algunas cosas. Sin embargo, con un poco de tiempo y de práctica, seremos capaces de adaptarnos al nuevo entorno y codificar nuestros programas con fluidez.

Y nada más. Esperamos que el post os sea de ayuda, sobre todo a los que nos habéis escrito pidiendo esta información enfocada para los programadores menos avanzados.

Saludos.

jueves, 2 de octubre de 2014

Estructura básica de un programa Cobol (1)

Hoy vamos a tratar un tema muy básico de nuestro lenguaje pero para el que, sin embargo, hemos recibido varias cuestiones de lectores principiantes en el mundo Cobol. Se trata de identificar cuáles son todos los apartados que debe incorporar un programa Cobol estándar.

Al principio, si no estamos acostumbrados a trabajar con Cobol, nos puede parecer un poco rígida la forma en que se estructuran los programas en este lenguaje. Sin embargo, una vez vayamos ampliando nuestra experiencia, nos daremos cuenta de que la cosa es tan sencilla como pueda serlo en cualquier otro lenguaje de programación.



Un programa Cobol está estructurado en una serie de Divisiones, Secciones y Párrafos en los que hay que ir declarando la información que corresponda a cada una de ellas. La estructura general sería la siguiente:

IDENTIFICATION DIVISION
   PROGRAM-ID
   AUTHOR
   INSTALLATION
   DATE-WRITTEN
   DATE-COMPILED
   SECURITY

ENVIRONMENT DIVISION

   CONFIGURATION SECTION
      SOURCE-COMPUTER
      OBJECT-COMPUTER
      SPECIAL-NAMES

   INPUT-OUTPUT SECTION
      FILE CONTROL
      I-O-CONTROL

DATA DIVISION

   FILE SECTION
      ...
      FICHERO
         REGISTRO
      ...

   WORKING-STORATE SECTION
      ...
      VARIABLE
      ...

   LINKAGE SECTION
      ...
      PARAMETRO
      ...

PROCEDURE DIVISION
   ...
   SECCION
      PARRAFO
         SENTENCIA
   ...

A continuación, comentamos un poco más en detalle en qué consiste cada una de las Divisiones y Secciones enumeradas anteriormente.

1º) IDENTIFICATION DIVISION

Esta División se utiliza para declarar una serie de variables globales asociadas al programa, tales como el nombre del objeto (PROGRAM-ID), el nombre del autor del objeto (AUTHOR), la instalación (INSTALLATION), las fechas de codificación y de compilación (DATE-WRITTEN y DATE- COMPILED) y la seguridad (SECURITY). En general, se trata de datos informativos que no tienen mayor impacto en la codificación posterior del programa.

IDENTIFICATION DIVISION
   PROGRAM-ID
   AUTHOR
   INSTALLATION
   DATE-WRITTEN
   DATE-COMPILED
   SECURITY 

2º) ENVIRONMENT DIVISION

Esta División se compone de dos importantes secciones, CONFIGURATION SECTION e INPUT-OUTPUT-SECTION, cuyo contenido pasamos a detallar a continuación.

ENVIRONMENT DIVISION

A) CONFIGURATION SECTION

Aquí se especifica información relevante para el programa. Por un lado, se debe indicar el nombre de la máquina empleada para la codificación (SOURCE-COMPUTER y OBJECT-COMPUTER). Por otro lado, en el apartado SPECIAL-NAMES hay que detallar las configuraciones especiales que vaya a tener nuestro programa.

Este último apartado tiene su importancia. En general, en Europa se emplea para hacer la declaración DECIMAL POINT IS COMMA, que le indica al compilador que, en nuestro programa, la parte decimal de un número va a ir precedida de una coma (,) y no de un punto (.) como ocurre en EEUU.

   CONFIGURATION SECTION
      SOURCE-COMPUTER
      OBJECT-COMPUTER
      SPECIAL-NAMES 

B) INPUT-OUTPUT SECTION

En esta sección, en el apartado FILE CONTROL hay que especificar el nombre de los ficheros que se tratarán en nuestro fuente. Se indicará la equivalencia entre el nombre lógico que va a tener un determinado fichero en el programa Cobol y el nombre externo que tendrá en el JCL que lo invoque. Este apartado sólo se rellenará si nuestro objeto va a estar insertado en un proceso batch (por contra, no se usará si se va a tratar de un programa CICS on-line).

Adicionalmente, en esta sección aparece también el apartado I-O-CONTROL, que se usará para indicar el área de memoria que va a ser compartida por los ficheros utilizados en el programa. Este segundo apartado es opcional.

   INPUT-OUTPUT SECTION
      FILE CONTROL
      I-O-CONTROL

El próximo día continuaremos revisando las dos últimas Divisiones del programa Cobol, junto con todas las secciones contenidas en ellas. Os adelantamos que hablaremos de la "Data Division" y de la "Procedure Division", aunque ya las revisaremos en detalle en el siguiente post.

Y eso es todo. Ya sólo nos queda emplazaros a la segunda parte para que podamos completar la revisión de todas las Divisiones y secciones de la estructura básica de un programa Cobol.

Saludos.

miércoles, 13 de agosto de 2014

Test de conocimientos de Cobol CICS DB2

Para el que se aburra durante estos días de verano y quiera evaluar su nivel de conocimientos de COBOL / CICS / DB2, aquí os traemos un interesante test que servirá para cumplir dicha función. No tardaremos mucho tiempo en realizarlo y siempre nos permitirá aprender alguna cosa nueva.

Recordad que, como ya sabemos, en un test también influye un poco la suerte (ya que todo depende del tipo de preguntas que nos hagan) y, por tanto, es posible que vuestro nivel real difiera bastante de la puntuación obtenida aquí. Pero bueno, como mínimo nos servirá para pasar un rato entretenido.

El tiempo límite para la realización del test no debería ser superior a 20 minutos (si pasado ese tiempo no lo habéis completado, entonces es que realmente no sabéis la respuesta de las cuestiones restantes). El listado de las preguntas es el siguiente.



=============================================================

1º) ¿Qué es el CICS?

   a) Un sistema operativo.
   b) Un middleware.
   c) Un protocolo de red.
   d) Una aplicación de usuario.

2º) Cuando un usuario introduce una transacción, ¿qué componente CICS valida el código de transacción?

   a) Terminal Control
   b) Task Control
   c) Program Control
   d) Transaction Control

3º) Si dos usuarios introducen el mismo identificador de Transacción, CICS carga dos copias del programa inicial, una para cada usuario.

   a) Verdadero.
   b) Falso.

4º) ¿Qué acción tiene que realizar un programador para asegurarse de que CICS copia el bloque DFHEIBLK en un programa de una aplicación?

   a) COPY DFHEIBLK
   b) INCLUDE DFHEIBLK
   c) COPY DFHCOMMAREA
   d) Ninguna de las anteriores

5º) Cuando se codifica el comando de control de terminal RECEIVE (puntualizar que no hablamos del comando BMS RECEIVE MAP), ¿cuál de las siguientes es considerada una condición de excepción normal?

   a) NORMAL
   b) EOC
   c) LENGERR
   d) (a) y (b)
   e) Todas las anteriores

6º) Las dos condiciones siguientes son equivalentes:
   I) IF EIBRESP NOT EQUAL DFHRESP(NORMAL)
   II) IF EIBRESP EQUAL DFHRESP(ERROR)

   a) Verdadero
   b) Falso

7º) Para colocar el cursor en una posición particular de la pantalla, se debe usar el comando SEND CONTROL.

   a) Verdadero
   b) Falso

8º) Para ejecutar una nueva transacción en CICS por primera vez, los únicos requisitos son que el programa esté precompilado, compilado y linkeditado.

   a) Verdadero
   b) Falso

9º) ¿Cuál de las siguientes acciones no se puede realizar con la herramienta CEDF?

   a) Modificar todos los comandos CICS
   b) Modificar todas las condiciones de excepción
   c) Cambiar la WORKING STORAGE de los programas
   d) Elegir no ejecutar todos los comandos CICS (opción NOOP)
   e) Producir un ABEND en una tarea
   f) Debug de un programa que está ejecutándose en otro terminal

10º) Para desencadenar un ABEND de una tarea desde CEDF, se debe presionar dos veces la tecla función ABEND.

   a) Verdadero
   b) Falso

=============================================================



Las soluciones a las cuestiones anteriores son las siguientes: 1º) b, 2º) b, 3º) b, 4º) d, 5º) d, 6º) b, 7º) a, 8º) b, 9º) a y 10º) a. Es importante que intentéis agotar los 20 minutos tratando de deducir las respuestas antes de recurrir a la resolución. Nunca viene mal esforzarse un poco...

En función de los aciertos que hayamos tenido en el quiz, nos encontraremos en un grupo de conocimiento u otro. A continuación podéis echarle un vistazo a la categoría que os corresponda.

A) Ocho aciertos o más: Se nota que esto del Cobol se te da bien aunque, por otra parte, es normal ya que seguramente tengas muchos años de experiencia con el entorno CICS.

B) Seis o siete aciertos: Tienes bastantes conocimientos de Cobol CICS, y probablemente dentro de algún tiempo sustituirás a los programadores más veteranos de este entorno.

C) Cuatro o cinco aciertos: Es evidente que sabes muchas cosas sobre Cobol, aunque todavía te queda bastante margen para mejorar. Hay que ganar un poco más de experiencia.

D) Dos o tres aciertos: Bueno, posiblemente eres un programador novato en el mundo del Cobol. Pero no te desanimes, en algún momento hay que empezar y tarde o temprano acabarás dominando el lenguaje.

E) Menos de dos aciertos: Probablemente todavía no has estudidado Cobol CICS con suficiente profundidad como para afrontar un test de este tipo. Tienes que decidir si este mundo es lo que te interesa o no.



De todas formas, os volvemos a recordar lo que dijimos al principio. En un test también interviene el azar y, por tanto, es posible que el resultado no coincida exactamente con vuestra experiencia en Cobol. Puede haber ocurrido que las 10 cuestiones de este test sean justo las que todavía no os sabéis o, al contrario, es posible que estas sean las únicas 10 preguntas que seríais capaces de responder en relación con el Cobol CICS. Cuando hablamos de test, nunca hay que descartar el factor fortuna.

Pues nada, aparte de esto, esperamos que al menos os hayáis divertido durante 20 minutos respondiendo a las diversas cuestiones del test. En un futuro, si tenemos tiempo, trataremos de ir incluyendo más quiz de este tipo en el blog.

Saludos.

Related Posts Plugin for WordPress, Blogger...