miércoles, 26 de junio de 2013

Lenguaje Binder. Características y estrategias.

Los programas de servicio (*SRVPGM) se crearon en ILE para encapsular funciones reutilizables y cuya gran ventaja es que en tiempo de ejecución es rendimiento es muy bueno debido en parte a que cuando se crea un programa, se guarda cierta información del programa de servicio que facilita la carga e inicialización del mismo. Es la signature.
Podéis tener una información más detallada de las formas de llamada a objetos en ILE sobre este enlace.


Signature.

Pero ¿qué es esto?. De forma burda, se puede comparar con el lvlchk de un fichero. En este caso si un programa se ha creado utilizando un determinado lvlchk de un fichero, en el momento en que se vaya a utilizar dicho fichero en tiempo de ejecución, el sistema operativo comprobará que es el mismo, en cuyo caso permitirá continuar con la ejecución pero en caso contrario dará un error y finalizará el programa.

La signature es similar. Cuando se crea un programa ILE y se enlazan los programas de servicio, se almacena en el programas la signature del programa de servicio. En tiempo de ejecución, cuando se llama al programa, en tiempo de inicialización, revisa que la signature almacenada en el programa es igual a la que tiene el programa de servicio y si es así, permitirá la ejecución del programa y en caso contrario dará error.

Una diferencia muy importante con respecto al lvlchk de un fichero y que nos facilitará el mantenimiento de aplicaciones es que un programa de servicio puede tener muchas signatures que serían como versiones del mismo programa se servicio. 
Así, si por ejemplo tenemos, un programa de servicio con las signatures 1 y 2 y lo llaman dos programas, el programa X que cuando se creo lo enlazaba con la signature 1 y el programa Y que cuando se creo lo enlazaba con la signature 2, pueden funcionar perfectamente.



Ejemplo de múltiples signatures válidas de un programa de servicios. Comando DspSrvPgm


Como se genera y en que se basa

Hay dos formas de crear la signature. De forma automática o de forma manual. 
  • En la automática es el sistema operativo quien crea la signature en el momento de creación de programa de servicio.
  • En la forma manual es la persona que crea el programa de servicio quien le da el código que desea.
 Yo, hasta el momento, siempre he utilizado la forma automática ya que la ventaja principal que le encuentro es que es el SO quien controla el código que debe asignarle. En la forma manual es el usuario quien debe controlar el código o códigos que se le da y sería un trabajo más a realizar y con la posibilidad de generar errores cuando un programa de servicio pudiera tener varias signatures.

Pero en ¿qué se basa el código que le genera?

Esto tiene que ver con la reducción del tiempo de inicialización del programa de servicio en tiempo de ejecución. Para ello, se pretende que en tiempo de compilación ya que pueda revisar que esa llamada sea correcta. Y para ello inventaron la signature. 
Por ello, el código que genera está basado en:

  • Los componentes exportables que tienen un programa de servicio
  • El orden de los componentes exportables
  • Los parámetros de entrada y salida de cada componente exportable. 

Por lo tanto, como se ve, ese código que genera le permite al sistema operativo realizar una revisión muy rápida en tiempo de ejecución de si va a "casar" las llamadas al programa de servicio dentro del programa que estoy ejecutando.

Por ello es muy importante indicar que si cambio el código "interno" de un componente de un programa de servicio (sin tocar los parámetros de entrada/salida), la signature NO cambiará. 


Entendido, pero ¿cómo facilitan el mantenimiento de aplicaciones?

Hemos comentado que los programas de servicio permiten reutilizar código, realizar funciones comunes y me facilitan el mantenimiento de aplicaciones pero con la gestión de la signature ¿cómo puedo hacerlo fácilmente?

Vamos a ver con un ejemplo todas las posibilidades. Imaginemos que tenemos:

  • Un programa de servicio llamado SRV1 que tiene un componente exportable llamado calcDescuento. Este componente tiene un parámetro de entrada Importe y un parámetro de salida que es Descuento (como función). Básicamente lo que hace es recibir un importe y base a una serie de criterios, calcula un descuento que lo devuelve al programa que lo llamó. Los criterios son:
    • Si el importe es menor o igual que 1000 el descuento es un 0%
    • Si el importe está entre 1000 y 5000 el descuento es de un 10%
    • Si el importe es mayor que 5000 el descuento será de un 20%
  • Este componente del programa de servicio es utilizado 120 en los programas
 *==============================================
 *  calcDescuento    Calcula descuento          
 *==============================================
PcalcDescuento    B                   EXPORT    
DcalcDescuento    PI     15      4              
D P_Importe              15      4    Const     
                                                
D w_Descuento     S      15      4              
 /Free                                          
    // Aqui vendra el codigo del componente     
                                                
    Return w_Descuento                          
 /End-Free                                      
P                 E                             



1. Solo cambia el código interno

Ahora la Dirección indica que los criterios de descuento han cambiado y hay que aplicarle los nuevos que son:
  • Si el importe es menor o igual que 1000 el descuento es un 0%
  • Si el importe está entre 1000 y 2000 el descuento es de un 10%
  • Si el importe es mayor que 2000 el descuento será de un 20%
En este caso, modificaré el componente calcDescuento, compilaré el programa de servicio SRV1. 
NO cambia la signature del programa de servicio y NO es necesario compilar el resto de programa para que tome el nuevo funcionamiento.


2. Se cambian los parámetros de un componente.

Ahora, por evolución del negocio, se ha pedido que al componente calculoDescuento se incluya un parámetro que sea un indicador de si tiene derecho a un descuento especial
 adicional. Además, la posibilidad de utilizar este descuento sólo estará habilitada en unos pocos de los actuales programas que utilizan el programa de servicio.

La forma de proceder para evitar tener que volver a crear todos los programas que utilizan ese componente sería la siguiente:

  • En el componente calcDescuento se añade el nuevo parámetro pero con opción *NOPASS. De esta forma, no será necesario modificar todas las llamadas de todos los programas que utilicen ese componente si no sólo los programas donde tenga sentido utilizar ese componente.
  • En las líneas de código de este componente, lo primero será determinar si ese parámetro viene "relleno". En caso de que venga, se tomará el valor que se recibe y en caso contrario se tomará el valor por defecto, en este caso, que no tiene derecho a descuento especial.
De esta forma, se creará de nuevo el programa de servicio y no será necesario crear todos los programas que lo utilicen. Solo se deberán crear aquellos donde se quiera utilizar el nuevo parámetro.

PcalcDescuento    B                   EXPORT                           
DcalcDescuento    PI     15      4                                     
D P_Importe              15      4    Const                            
D P_DescEspecial                  n   Const OPTIONS(*NOPASS)           
                                                                       
D w_Descuento     S      15      4                                     
D w_DescEspecial  S               n                                    
 /Free                                                                 
    If %PARMS >=2;                                                     
      w_DescEspecial = P_DescEspecial;                                 
    Else;                                                              
      w_DescEspecial = *Off;                                           
    EndIf;                                                             
    // Aqui vendra el codigo del componente y opera 
    // con w_DescEspecial 
                                                                       
    Return w_Descuento                                                 
 /End-Free                                                             

P                 E                                                    


3. Se añade un nuevo componente al programa de servicio.

Ahora, por necesidades de algunos programas, se ha creado un nuevo componente calcImpuesto que se ha incluido en el mismo programa de servicio y será utilizado sólo por unos pocos programas.

En este caso, si NO utilizamos el lenguaje binder, al crear el programa de servicio, cambiará la signature y estaremos obligados a volver a crear TODOS los programas enlazando de nuevo con el programa de servicio.

Si utilizamos el lenguajes binder podremos evitar tener que compilar todos los programas. Añadiremos una nueva entrada para que genere una nueva signature y con el ello, cuando se cree  el programa de servicio, será válido para todas las signatures previas y por lo tanto NO será necesario volver a crear los programas que lo utilizan.


En próximas entregas, indicaré como se codifica el lenguaje binder para el mantenimiento de programas de servicio en base a estas características.



viernes, 21 de junio de 2013

Tipos de llamadas

Desde la llegada del ILE se dispone de varios formas de hacer llamadas para ejecutar código y es conveniente conocer el funcionamiento de cada una de ellas para definir una correcta estrategia de diseño de aplicaciones utilizando ILE.

Formas de ejecutar código

1. Ejecución de programa.

Existe desde el comienzo de la programación y se corresponde con la ejecución de un programa desde otro programa. En Rpg sería el tradicional CALLHasta la llegada de ILE era la única opción existente. 

El funcionamiento es simple desde un programa llamamos a otro y podemos pasarle parámetros. 

A nivel de sistema operativo, la verificación del programa llamado se realiza en tiempo de ejecución por lo que si, por alguna causa, no concuerdan los parámetros se producirá un error de ejecución. 
La inicialización del programa llamado conlleva bastante tiempo de ejecución ya que debe cargar el programa en memoria, inicializar variables y realizar aperturas de ficheros. Y lo mismo ocurre al finalizar un programa.

Es por ello que cuando desde un programa se llama a otro en múltiples y repetidas ocasiones, incidía notablemente en el rendimiento de la aplicación; por ejemplo, tenemos un programa que procesa un elevado número de registros y por cada registro llama a un programa para un determinado cálculo. Por ello, para reducir el tiempo y mejorar el rendimiento, recurríamos a finalizar el programa llamado con return para evitar los costes de tiempo de inicialización y finalización de programa. 

2. Llamada a módulo de un programa.

Se incorporó con la llegada del ILE y permite "llamar" a un módulo desde otro módulo del mismo programa. En RpgLe sería CALLPRC.

La verificación de la llamada (y sus parámetros) se produce en tiempo de compilación y creación del programa, cuando se "linkan" todos los módulos dentro del mismo programa. 

Al nivel de rendimiento, como se ha verificado, revisado y linkado en tiempo de compilación, el tiempo de carga e inicialización del módulo es irrelevante ya que sería el mismo que la ejecución de una subrutina dentro del programa.

Esta posibilidad de tener llamadas a módulos codificados independientemente pero cuyo rendimiento es como el de una subrutina a permitido dividir los programas en varios módulos para facilitar el desarrollo y el mantenimiento del programa.
Antes de existir ILE teníamos programas monolíticos de miles de líneas de código cuyo desarrollo y sobre todo mantenimiento (ante nuevas funcionalidades o corrección de incidencias) era muy complejo y problemático. Con ILE ese mismo programa se puede dividir en varios módulos (facilitando el desarrollo y el mantenimiento) y que se enlazan finalmente para formar un programa y cuyo rendimiento es exactamente igual que el antiguo programa monolítico.

3. Llamadas a programas de servicio.

También se incorporó con la llegada del ILE y permite "llamar" a un proceso desde un programa. Normalmente encapsulan procesos que van a ser utilizados desde múltiples programas y se corresponderían con una rutina de negocio reutilizable, por ejemplo, un procedimiento que devuelva el total de impuestos a aplicar a un determinado importe.

La verificación de la llamada (y sus parámetros) se produce, parte en tiempo de compilación y creación del programa y parte en tiempo de ejecución. 
Cuando se crea el programa es necesario indicarle que programas de servicio va a utilizar y en ese momento verifica, a través de los prototipos, la correspondencia de parámetros y en base a ello almacena en el programa la SIGNATURE del programa de servicio.  

La signature se como una firma basada en los componentes que tiene almacenados el programa de servicio y en los parámetros de esos mismos componentes. En próximas entregas hablaré de este concepto y del lenguaje binder.

Al nivel de rendimiento, consume mucho más tiempo que llamadas a módulos pero no se acerca al tiempo de inicialización de llamadas de programas
Simplemente, cuando se inicializa un programa que tiene una llamada a un programa de servicio, en ese momento se verifica que la signature que tiene el programa con relación al programa de servicio y la que tiene el programa de servicio son la misma y si es así se ejecuta y en caso contrario da un error.

Adicionalmente, el tiempo de carga es menor que el de llamadas a programas ya que el sistema operativo solo cargará en memoria una instancia del programa de servicio que podrá ser utilizada por todos los programas que lo llamen.

También es necesario indicar que es posible modificar el programa de servicio  sin tener que volver a compilar o a recrear todos los programas que lo utilizan lo cual facilita el desarrollo y mantenimiento.


Resumen

Con la llegada de ILE existen más opciones de llamadas que nos facilitan el desarrollo, mantenimiento y ejecución de aplicaciones y es necesario conocerlas para definir una estrategia conveniente en el desarrollo de aplicaciones. 
Así, por ejemplo, yo utilizaré:

  • En programas de servicio, rutinas de negocio que van a ser llamadas desde múltiples programas.
  • Llamadas de módulos. Cuando divida un programa en multiples módulos para facilitar el desarrollo y mantenimiento. Por ejemplo, un diseño de un programa que tiene cuatro pantallas podría hacerse que cada pantalla esté gestionada en un módulo y después de cree el programa utilizando los cuatro módulos
  • Llamadas entre programas. Pues eso, cuando necesite llamar a otro programa


sábado, 1 de junio de 2013

SQL. Función Row_Number

Esta función permite obtener el ranking de posición de cada uno  de los registros de la sentencia SQL según la clasificación y ordenación que deseemos.


Número de fila de resultado


Con la estructura de de la función en su forma row_number() podremos obtener el número de fila en los resultados de la ejecución de SQL según la ordenación y selección de la sentencia.

Ejemplo:  Sentencia simple
SELECT IdCliente, IdPais, IdTipCli, row_number() over() as Orden,  Nombre, Apellidos FROM Cliente;                            


  



Ejemplo: Sentencia simple con una ordenación
SELECT IdCliente, IdPais, IdTipCli, row_number() over() as Orden,  Nombre, Apellidos FROM Clienteorder by apellidos, nombre





Over Partición

Con esta funcionalidad permite calcular la secuencia en base a clasificaciones por n campos. El formato es row_number() over(partition by campo1, campo2..).

Tendrá secuencias diferentes para todas las combinaciones de campo1, campo2, etc. Imaginemos que se hace la partición por código de país, entonces habrá una secuencia 1, 2, 3, 4, para el país X, otra secuencia 1, 2, 3, 4 ... para el país Y y así sucesivamente para cada unos de los países que tenga el fichero.

Ejemplo: Sentencia simple con una ordenación y calculo de número de fila en base a una clasificación (en este caso por IdPais)
SELECT IdCliente, IdPais, IdTipCli, 
row_number() over(partition by idpais) as Orden,  
Nombre, Apellidos FROM Cliente order by apellidos, nombre;    





Over Order 

Con esta funcionalidad permite calcular la secuencia en base a la ordenación que se le indica. El formato es row_number() over(order by campo1, campo2..).

Generará la secuencia 1,2,3,4 según el orden de campos indicado (independientemente del order by que tuviera la sentencia SQL) 

Ejemplo: Sentencia con una ordenación y calculo la secuencia base a una clasificación (en este caso por IdPais) y en base a la ordenación que se propone (apellidos y nombre)
SELECT IdCliente, IdPais, IdTipCli, 
row_number() over(partition by idpais order by apellidos, nombre) as Orden, Nombre, Apellidos FROM Cliente order by apellidos, nombre   




Ejemplo: Sentencia con una ordenación y calculo de número de fila en base a una clasificación (en este caso por IdPais y IdTipCli) y en base a la ordenación que se propone de los mismos campos
SELECT IdCliente, IdPais, IdTipCli, 
row_number() over(partition by idpais, IdTipCLi order by idpais, IdTipCLi) as OrdenNombre, Apellidos FROM Cliente



jueves, 23 de mayo de 2013

Modulo. Mantenimiento de un registro



Objetivo

Realizar un módulo que presenta una ventana para el mantenimiento de los datos de un registro. Permitirá dar de alta un nuevo registro o realizar las opciones de modificación, consulta o borrado de un registro existente. Lógicamente validará la información introducida por el usuario antes de actualizar la información en la base de datos.
Para los campos de tipo tabla también se habilita el acceso a los programas de lista de selección (F4) en el ejemplo que se mostrará sobre el campo de país y de tipo de cliente.
En este ejemplo, se realizará una pantalla de mantenimiento de un cliente. Será llamado desde la pantalla de lista de clientes.





Tiene el mandato F10 para confirmar  la acción de alta, modificación o borrado. Con F4 accederá a la lista de selección de país y de tipo de cliente. Con F12 no realizará ninguna acción y volverá a la pantalla que le llamó.

Referencias: ILE estrategiaBD Pruebas

Configuración

Este programa utilizará un componente de acceso a base de datos de lista de clientes, los componentes de actualización (alta, baja y modificación) de un registro y los componentes de validación que se encuentran todos ellos en el programa de servicio correspondiente.
  • El nombre del módulo donde esta el ventana de lista de registros para mantenimiento BAN02P1
    • La definición de la pantalla estará definida como BAN02S1
  • Utiliza el programa de servicio BAN01SRV que contiene los componentes de acceso a BD, de actualización y de validación
    • El miembro (/Copy) con la definición del prototipo con los componentes y con la definición de estructuras será BAN01M1CP
  • Llamará a los programas de lista de países (PAN40P1) y lista de tipos de cliente (PAN40P2) 
    Este ejemplo sirve de plantilla para otro proceso similar.


    Fuente de la pantalla. BAN02S1

    Se define la pantalla para presentar el mantenimiento de un registro.

    miércoles, 22 de mayo de 2013

    Modulo. Lista para mantenimiento


    Objetivo


    Realizar un módulo que presenta una ventana con una lista de registros que servirá para el mantenimiento de los mismo. Tendrá opciones para acceder a la pantalla que permite dar de alta un nuevo registro o realizar las opciones de modificación, consulta o borrado de un registro existente. Además incorpora una búsqueda para seleccionar los registros que aparecen en la lista. La lista se cargará por páginas.
    Para los campos de tipo tabla también se habilita el acceso a los programas de lista de selección (F4) en el ejemplo que se mostrará sobre el campo de país y de tipo de cliente.
    En este ejemplo, se realizará una pantalla de lista de registros para mantenimiento para la tabla de clientes.




    Tiene el mandato F9 para dar de alta un nuevo registro. Las opciones sobre el subfichero 2, 4, 5 para realizar las opciones de mantenimiento de modificación, borrado y consulta respectivamente. 
    Tiene en la cabecera los campos de búsqueda para restringir la información que se muestra en la lista.
    Adicionalmente he añadido una opción (8) en el subfichero para acceder a la lista de cuentas del cliente que será otra pantalla similar a esta y que utilizará la misma plantilla con el punto adicional que se presenta información del cliente al que pertenece (maestro-detalle)

    Referencias: ILE estrategiaBD Pruebas

    Configuración

    Este programa utilizará un componente de acceso a base de datos de lista de clientes que se definió en la entrada de acceso a BD a través del uso del programa de servicio que lo contiene .
    • El nombre del módulo donde esta el ventana de lista de registros para mantenimiento BAN01P1
      • La definición de la pantalla estará definida como BAN01S1
    • Utiliza el programa de servicio BAN01SRV que contiene los componentes de acceso a BD.
      • El miembro (/Copy) con la definición del prototipo con los componentes y con la definición de estructuras será BAN01M1CP
    • Llamará a los módulos de mantenimiento de un registro de cliente (PAN02P1) y a la lista de cuentas asociadas a un cliente (PAN03P1)
    • Llamará a los programas de lista de países (PAN40P1) y lista de tipos de cliente (PAN40P2) 
    Este ejemplo sirve de plantilla para otro proceso similar.


    Fuente de la pantalla. BAN01S1

    Se define la pantalla para presentar la lista de registros para mantenimiento.

    lunes, 20 de mayo de 2013

    Modulo. Lista de seleccion (F4)

    Continuando con la serie de entradas relacionadas con el tema de la estrategia de desarrollo en ILE presento una plantilla de programa de selección de un registro.

    Objetivo


    Realizar un programa que presenta una ventana de selección (típica consulta de F4 en formato window) donde se podrá un registro para devolver al programa que le ha llamado.
    En este ejemplo, se realizará una ventana de selección de países.

    Referencias: ILE estrategiaBD Pruebas


    Configuración 

    Este programa utilizará un componente de acceso a base de datos de lista de países similar al que se definió en la entrada de acceso a BD a través del uso del programa de servicio que lo contiene .
    • El nombre del módulo donde esta el ventana de lista de selección BAN40P1
      • La definición de la pantalla estará definida como BAN40S1
    • Utiliza el programa de servicio BAN01SRV que contiene los componentes de acceso a BD.
      • El miembro (/Copy) con la definición del prototipo con los componentes y con la definición de estructuras será BAN01M1CP
    Este ejemplo sirve de plantilla para otro proceso similar.


    Fuente de la pantalla. BAN40S1

    Se define la pantalla para presentar la lista de registro y para seleccionar un registro.



    A                                      DSPSIZ(24 80 *DS3)
    A                                      PRINT
    A          R BAN40S01                  SFL
    A                                      SFLNXTCHG
    A            S_OPCION       1A  B  8  4VALUES(' ' '1')
    A            S_DSPAIS      35A  O  8 12
    A            S_IDPAIS       3A  O  8  8
    A          R BAN40C01                  SFLCTL(BAN40S01)
    A                                      CF03(03 'Salir')
    A                                      RTNCSRLOC(*RECNAME &REGCUR &CAMCUR)
    A                                      OVERLAY
    A                                      SFLCSRRRN(&CURS01)
    A  40N41                               SFLDSP
    A N41                                  SFLDSPCTL
    A  41                                  SFLCLR
    A  40N41                               SFLEND(*MORE)
    A                                      SFLSIZ(0010)
    A                                      SFLPAG(0009)
    A  61                                  SFLMSG('Solo se puede seleccionar u-
    A                                      n registro' 61)
    A                                      WINDOW(BAN40P01)
    A            CURS01         5S 0H
    A            NRR            4S 0H      SFLRCDNBR(CURSOR)
    A            CAMCUR        10A  H
    A            REGCUR        10A  H
    A            WKSTNS        10A  O  1 30DSPATR(HI)
    A                                  2  3DATE
    A                                      EDTCDE(Y)
    A                                      DSPATR(HI)
    A                                  2 40USER
    A                                      DSPATR(HI)
    A            D_DSPAIS      25A  B  4 10DSPATR(HI)
    A                                  4  4'Pais'
    A                                  7  3'Opc'
    A                                      DSPATR(HI)
    A                                      DSPATR(UL)
    A                                  7  8'Pais'
    A                                      DSPATR(HI)
    A                                      DSPATR(UL)
    A                                  5  4'1-Seleccionar'
    A                                  1 18'Lista de paises'
    A                                      DSPATR(HI)
    A                                  1  3'BAN40P1'
    A                                      DSPATR(HI)
    A          R BAN40P01
    A                                      WINDOW(2 15 20 50)
    A                                      WDWBORDER((*DSPATR RI) (*CHAR '    -
    A                                          '))
    A                                 18  5'F3-Salir'
    A          R BAN40R00
    A                                      KEEP
    A                                      ASSUME
    A                                  5  3' ' 


    Se define:

    domingo, 19 de mayo de 2013

    Cgidev2

    Hola de nuevo. Voy a dejar un momento el tema de ILE que estaba tratando en entradas previas y os voy a presentar Cgidev2. En cualquier caso, la misma estrategia que os estaba presentando para 5250 la utilizo para el desarrollo con Cgidev2 y me sirve para reutilizar todos los componentes que puedo :)

    CGIDEV2 es una herramienta Open Source que permite comunicar con un navegador web desde un programa Rpg o Cobol. Por lo tanto permite "crear" páginas web desde estos lenguajes.
    En si es un programa de servicio con un conjunto de componentes que encapsulan APIs del sistema operativo y que permiten procesar protocolo http. Con ellos, desde RPG, podemos "leer" un formulario rellenado en una página web y podremos crear un página web de respuesta.

    Podrás acceder a la página principal de Cgidev2 y donde encontrarás todo tipo de  documentación a través de este enlace.


    En esta entrada definiré un programa sencillo que permitirá obtener una lista de clientes de un fichero. Muestro una imagen de la salida en un navegador web.

    Pruebalo aquí. Ahora prueba poniendo sustituyendo el 0 final en la url por un 1. 

    Instalación


    De la página de Cgidev2 es necesario descargarse la herramienta y las instrucciones de instalación. La instalación creará una biblioteca llamada Cgidev2 con los objetos y el programa de servicio y generará una instancia del servidor web Apache. El servidor web es el que servirá para comunicar entre el navegador web y los programas RPG. 

    Que es necesario

    En un proceso "normal" del iseries cuya salida es 5250, es necesario, para interactuar con el usuario, un fichero de pantalla Dspf y un programa Rpg. 
    Para el entorno web utilizando esta herramienta, es necesario disponer de una plantilla Html y un programa Rpg que además utilice el programa de servicio Cgidev2

    Html es un lenguaje de texto y basado en "marcas" y es son capaces de interpretar los navegadores web para presentar una pantalla. Es sencillo y podéis encontrar ayuda en muchas webs como por ejemplo 3schools.

    Plantilla html

    Es un archivo Html PERO donde se han incluido algunos tags que será interpretados por Cgidev2 en su ejecución. Por lo tanto NO es un html puro. Lo que contiene son definición de secciones (parecido a un formato de registro de un informe Rlu) y variables que se sustituirán en tiempo de ejecución por lo valores asociados. 
    Anexo la plantilla html que ha generado la pantalla.


    viernes, 17 de mayo de 2013

    Indice. ILE

    En este índice están recopiladas las entradas más importantes relacionadas con el tema de ILE así como los ejemplo de código aportado.

    Definición



    Como ejemplo de desarrollo, se realizarán las siguientes funcionalidades basada de un esquema de base de datos de prueba relativas a clientes y cuentas de clientes:

    • Tres programas de lista de selección (F4). Lista de países, de tipos de cliente y de tipos de cuenta. (BAN40P1EJ, BAN40P2EJ, BAN40P3EJ)
    • Un programa ejecutable con la lista de clientes y el mantenimiento de clientes y también el acceso a la lista de cuentas de un cliente y el mantenimiento de una cuenta de clientes (BAN01P1EJ), Este programa tendrá cuatro módulos; para lista de clientes, para mantenimiento de un cliente, para lista de cuentas del cliente y para mantenimiento de una cuenta. 
    • Un programa de servicio con todos los componentes de acceso a base de datos, de actualización de la base de datos y de validación. (BAN01M1SRV)



    Capa de acceso a datos y lógica de negocio


    Capa de presentación visual 

     Se puede descargar todos los programas, módulos y pantalla de esta aplicación de prueba desde este enlace

    Cuando se descargue, todos los fuentes deberían ponerse en un archivo de fuentes QRPGLESRC ya que tiene un CL para poderlo compilar los módulos y programas (previamente hay que compilar las pantallas). Se utilizará el comando:
     CALL BAN_COMPIL PARM('*ALL  ' 'Libfuentes' 'LibObjetos') donde Libfuentes será la biblioteca donde están los fuentes y LibObjetos la biblioteca donde se generarán los objetos.


    Información adicional

    miércoles, 15 de mayo de 2013

    Componente. Validación



    Objetivo


    Crear componentes  que sean capaces de validar determinada información. 
    En este ejemplo, se realizará un componente para validar varios campos.

    Referencias: ILE estrategiaBD Pruebas

    Estos componentes complementan al componente acceso de datos y de actualización de base de datos presentado en entradas anteriores.

    Configuración

    Se utiliza SQL para el desarrollo del código. El componente  formará parte de un programa de servicio y será exportable por lo que podrá ser llamado por el programa que enlace este programa de servicio.
    • Los nombres de los componentes (Val_Nombre, Val_IdPais). Utilizo siempre Val_xxxxxx donde xxxxx es el nombre del campo a validar.
    • El nombre del módulo donde estarán los componentes BAN01M1
    • El miembro (/Copy) con la definición del prototipo con los componentes y con la definición de estructuras será BAN01M1CP
    • El programa de servicio donde estarán los módulos BAN01SRV. Tendrá un miembro asociado con el mismo nombre con la definición (binder) de los componentes a exportar.

    Miembro /Copy. BAN01M1CP

    Se describen las estructuras de datos que dan servicio al componente de acceso a base de datos y el prototipo de llamada. Estarán en un miembro fuente independiente para que sea utilizado como /Copy tanto por el fuente del componente como los fuentes de los posibles programas que lo utilicen.


     *==========================================================
     *    Validar Campo de Nombre de cliente
     *       E01 - No permite blancos
     *==========================================================
    DVal_Nombre       PR              n
    D P_Nombre                      50    Const
    D P_IdError                      3

     *==========================================================
     *    Validar Campo de Pais
     *       E01 - No permite blancos
     *       E02 - Pais no existe
     *==========================================================
    DVal_IdPais       PR              n
    D P_IdPais                       3    Const
    D P_IdError                      3          



    Está compuesto por:
    • (Val_Nombre) Definición de prototipo (interfaz) para validar el campo de nombre del fichero de clientes.
    • (Val_IdPais) Definición de prototipo (interfaz) para validar el campo de Id de Pais del fichero de clientes.

    Al principio del fuente del componente se utiliza el /COPY para “cargar” las estructuras de datos y los prototipos de los componentes. 

    /COPY *LIBL/QRPGLESRC,BAN01M1CP

    Fuente del componente. Val_Nombre en BAN01M1

    Este componente valida que sea correcto el contenido del campo nombre que pertenece al fichero de clientes

    El componente tiene el siguiente código:

    martes, 14 de mayo de 2013

    Componente. Actualización de base de datos


    Objetivo


    Crear un componente que sea capaz de añadir, actualizar o borrar un registro de una entidad de una base de datos. 
    En este ejemplo, se realizará un componente para actualizar información de la tabla de clientes.


    Estos componentes complementan al componente acceso de datos presentado en entradas anteriores.

    Configuración

    Se utiliza SQL para el desarrollo del código. El componente  formará parte de un programa de servicio y será exportable por lo que podrá ser llamado por el programa que enlace este programa de servicio.
    • Los nombres de los componentes (Add_Cliente, Upd_Cliente, Dlt_Cliente). Utilizo siempre Add_xxxxxx, Upd_xxxxx, Dlt_xxxxx donde xxxxx es la entidad para la definición del componente de actualización.
    • El nombre del módulo donde estarán los componentes BAN01M1
    • El miembro (/Copy) con la definición del prototipo con los componentes y con la definición de estructuras será BAN01M1CP
    • El programa de servicio donde estarán los módulos BAN01SRV. Tendrá un miembro asociado con el mismo nombre con la definición (binder) de los componentes a exportar.

    Miembro /Copy. BAN01M1CP

    Se describen las estructuras de datos que dan servicio al componente de acceso a base de datos y el prototipo de llamada. Estarán en un miembro fuente independiente para que sea utilizado como /Copy tanto por el fuente del componente como los fuentes de los posibles programas que lo utilicen.


     *===========================================================
     ** Alta de cliente
     *===========================================================
    DDs_AddClie       DS                  QUALIFIED
    D Nombre                        50
    D Apellidos                    100
    D Direccion                    100
    D IdPais                         3
    D IdTipCli                       1

    DAdd_Cliente      PR            10  0
    D P_DsClieAlt                         Const LikeDs(Ds_AddClie)

     *============================================================
     ** Actualizacion de cliente
     *============================================================
    DDs_UpdClie       DS                  QUALIFIED
    D Nombre                        50
    D Apellidos                    100
    D Direccion                    100
    D IdPais                         3
    D IdTipCli                       1

    DUpd_Cliente      PR
    D P_IdCliente                   10  0 Const
    D P_DsClieMod                         Const LikeDs(Ds_UpdClie)

     *============================================================
     ** Borrado de cliente
     *============================================================
    DDlt_Cliente      PR
    D P_IdCliente                   10  0 Const


    Está compuesto por:
    • (Ds_AddClie) y (Ds_UpdClie)  Estructura de datos con los campos para generar un cliente y para actualizar un cliente respestivamente.
    • (Add_Cliente) Definición de prototipo (interfaz) para generar un nuevo cliente.
    • (Upd_Cliente) Definición de prototipo (interfaz) para actualizar los datos de un cliente
    • (Dlt_Cliente) Definición de prototipo (interfaz) para generar un nuevo cliente.

    Al principio del fuente del componente se utiliza el /COPY para “cargar” las estructuras de datos y los prototipos de los componentes. 

    /COPY *LIBL/QRPGLESRC,BAN01M1CP

    Fuente del componente. Add_Cliente en BAN01M1

    Este componente genera un nuevo cliente en la tabla correspondiente y devuelve el id de cliente (clave primaria) que ha generado


    El componente tiene el siguiente código:

    lunes, 13 de mayo de 2013

    Componente. Acceso a BD

    Objetivo


    Crear un componente que sea capaz de devolver un registro o una lista de registros de una o varias entidades de una base de datos. Debe permitir que se pueda seleccionar un filtro de datos y también indicar la ordenación que se desea. Además debe ser posible indicar que se devuelvan los registros de una determinada página, es decir, desde una determinada posición y un número determinado de registros.
    En este ejemplo, se realizará un componente para obtener información de la tabla de clientes.




    Configuración

    Se utiliza SQL para el desarrollo del código. El componente  formará parte de un programa de servicio y será exportable por lo que podrá ser llamado por el programa que enlace este programa de servicio.
    • El nombre de componente (Obt_LstClientes). Utilizo siempre Obt_Lstxxxxxx donde xxxxx es la entidad para la definición del componente de acceso a base de datos para recuperar una  lista de registros.
    • El nombre del módulo donde estarán los componentes BAN01M1
      Tendrá los siguientes componentes:
      • (Obt_LstClientes) para recuperar la lista de clientes. Exportable
      • (Obt_LstCuentas) para recuperar la lista de cuentas. Exportable
      • (Sentencia_Ini) para inicializar el cursor de la ejecución de la sentencia. INTERNO.
      • (Sentencia_Fin) para finalizar el cursor de la ejecución de la sentencia. INTERNO.
    • El miembro (/Copy) con la definición del prototipo con los componentes y con la definición de estructuras será BAN01M1CP
    • El programa de servicio donde estarán los módulos BAN01SRV. Tendrá un miembro asociado con el mismo nombre con la definición (binder) de los componentes a exportar.

    Miembro /Copy. BAN01M1CP

    Se describen las estructuras de datos que dan servicio al componente de acceso a base de datos y el prototipo de llamada. Estarán en un miembro fuente independiente para que sea utilizado como /Copy tanto por el fuente del componente como los fuentes de los posibles programas que lo utilicen.


          ** Estrutura datos basicos de Clientes
    DDs_BasClie       DS                  QUALIFIED
    D IdCliente                     10  0
    D Nombre                        50
    D Apellidos                     50
    D Direccion                     50
    D IdPais                         3
    D DsPais                        50
    D IdTipCli                       1
    D DsTipCli                      50

    ** Estructura seleccionador de datos
    DDs_SelClie       DS                  QUALIFIED
    D K_IdCliente                   10  0
    D S_DsCliente                   50
    D S_IdPais                       3
    D S_IdTipCli                     1

    ** Prototipo de lista de clientes.
    DObt_LstClientes  PR
    D P_DatosClie                         Dim(99) LikeDs(Ds_BasClie)
    D P_NumReg                       2  0
    D P_TotReg                      10  0
     *Opcionales
    D P_Pag                          6  0 Const OPTIONS(*NOPASS)
    D P_RegCarPag                    3  0 Const OPTIONS(*NOPASS)
    D P_OrderBy                      2    Const OPTIONS(*NOPASS)
    D P_Sel                               LikeDs(Ds_SelClie) Const
    D                                     OPTIONS(*NOPASS)


    Está compuesto por:
    • (Ds_BasClie) Estructura de datos con los campos que se recuperarán de la instrucción SQL y que estarán en el array de datos que se devuelve.
    • (Ds_SelClie) Estructura de datos con los campos que se permite utilizar para seleccionar (se utilizarán en WHERE) para filtrar la sentencia SQL.
      • (K_) Seleccionador de clave primaria del fichero, en este ejemplo, será el código de cliente.
      • (S_) Otros posibles seleccionadores según la definición que se haga en el componente. 
    • (Obt_LstClientes) La definición del prototipo (interfaz) de llamada al componente. Más adelante explicaré los parámetros del mismo.

    Al principio del fuente del componente se utiliza el /COPY para “cargar” las estructuras de datos y los prototipos de los componentes. 

    /COPY *LIBL/QRPGLESRC,BAN01M1CP

    Fuente del componente. Obt_LstClientes en BAN01M1

    Parámetros

    El componente tendrá la siguiente definición de parámetros: