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.



3 comentarios:

  1. Fernando gracias por tan excelente blog, esperando lo completes con los ejemplos de binder y mas sobre programación avanzada con SQL Embebido.
    Saludos.

    ResponderEliminar
  2. Voy a ver si saco tiempo para volver a actualizar el blog añadiendo lo que me pides

    ResponderEliminar
  3. Hey Fernando, me uno a Javier con las felicitaciones y apoyo la noción que puedas agregas más ejemplos de Sql embebido... Saludos Compa.

    ResponderEliminar