Algunos consejos:
1. Utiliza siempre las "especificaciones de exportación" (tipo de fuente BND) para definir claramente la interfaz (o lista de procedimientos) del programa de servicio y dale una "signatura" (o identificador de nivel). 2. Añade siempre los nuevos procedimientos al final de la especificación de exportación (igual que lo harías cuando añades un campo nuevo en un fichero). No es necesario cambiar la "signatura". 3. Todos los procedimientos de la interfaz del programa de servicio e incluidos en la "especificación de exportación" deben definirse con la palabra clave EXPORT (como lo haces ahora). 4. Si cambiaras el orden de los procedimientos en las "especificaciones de exportación" sin cambiar la "signatura" los programas que utilicen el programa de servicio no generarán un mensaje de escape, pero empezarán a tener un comportamiento extraño. 5. El orden de los procedimientos en el código fuente no es importante, siempre y cuando se mantenga el orden original en las "especificaciones de exportación". 6. La palabra EXPORT se puede utilizar en procedimientos que no aparezcan en la interfaz del programa de servicio. ¿Qué interés tiene esta técnica? No tiene ningún sentido en un programa de servicio con un único módulo pero cuando esté compuesto por más de un módulo, los procedimientos EXPORT son visibles entre módulos. 7. No construyas programas de servicio ni muy grandes (gigantescos ni muy pequeños). Piensa que el programa que los use tendrá que cargarlos en memoria la primera vez que se necesiten y quedará residente hasta que finalice el trabajo. ¿Qué es grande o pequeño? Es bastante subjetivo y te lo señala tu propia experiencia. 8. Intenta agrupar en un programa de servicio procedimientos con una funcionalidad similar: por ejemplo, funciones de fecha, manejo de cadenas de caracteres, gestión de excepción/errores, listas enlazadas, etc. Con el tiempo, me he dado cuenta que hay una serie de funciones que prácticamente se usan en casi todos los programas: fechas, cadenas de caracteres o manejo de excepciones (entre otras). En estos casos me planteo juntarlas todas en un solo programa de servicio, pero no tengo muy claro si hago bien o mal. Ni en qué me beneficia o perjudica. Un saludo, Javier De: [email protected] [mailto:[email protected]] En nombre de alberto Enviado el: martes, 18 de agosto de 2015 12:05 Para: forum.help400 Asunto: RE: Procedimientos en programas de servicio Buenas. Pues sí que has aclarado. era yo que lo estaba haciendo mal. En las funciones, se define el parámetro a nivel de componente y se pone el EXPORT: P Fun021i B EXPORT D Fun021i PI 8 0 Pues yo me había empeñado en no poner tampoco el EXPORT cuando no había que definir el parámetro, (como cuando retorna más de un valor). P Fun022i B D Fun022i PI Salu2 y gracias De: Javier Mora <[email protected]> Para: "'forum.help400'" <[email protected]> Fecha: 18/08/2015 11:06 Asunto: RE: Procedimientos en programas de servicio Enviado por: [email protected] ________________________________ No he entendido muy bien tu problema. A modo de resumen, RPG no entiende o distingue entre funciones o procedimientos, todo son subprocedimientos. Nosotros podemos diferenciarlos como: funciones o procedimientos. Realmente, lo único que los diferencia es que las primeras pueden formar parte de expresiones. Por ejemplo, una función típico que yo uso frencuentemente es: /** * IsLeapYear() * * Comprobar si el año es bisiesto. * * Parámetro Uso Descripción * * date E Una fecha cualquiera. * * Valor retorno: *ON si el año es bisiesto. * *OFF en caso contrario. */ P IsLeapYear B Export D IsLeapYear PI N D date D Const D year S 10I 0 /FREE year = %Subdt( date: *YEARS ); // Los múltiplos de 100 deben ser divisibles entre 400 If %Rem( year: 100 ) = 0; Return ( %Rem( year: 400 ) = 0 ); Else; Return ( %Rem( year: 4 ) = 0 ); Endif; Return *OFF; /END-FREE P IsLeapYear E Que me devuelve *ON si el año de la fecha pasada es bisiesto u *OFF en caso contrario. Un procedimiento típico en mi instalación podría ser este: /** * ConvertCase() * * Convertir a mayúsculas o minúsculas una cadena de caracteres. * * Parámetro Uso Descripción * * inStr E Expresión de tipo cadena para convertir a * mayúsculas/minúsculas. * inStrSize E Tamaño en bytes de la cadena de entrada. * outStr S Cadena que recibirá la cadana convertida. * outStrSize E Tamaño en bytes de la variable que recibirá * la cadena convertida. * o_option E Tipo de conversión: * 0 = a mayúsculas (valor por defecto) * 1 = a minúsculas * o_ccsid E Identificador del juego de caracteres con * el que está codificada la cadena 'inStr'. * * Valor retorno: Ninguno. */ P ConvertCase B Export D ConvertCase PI D inStr Const Like( TypeBuffer2 ) D Options( *VARSIZE ) D inStrSize Const Like( INT4_T ) D outStr Like( TypeBuffer2 ) D Options( *VARSIZE ) D outStrSize Const Like( INT4_T ) D o_option Const Like( INT4_T ) D Options( *NOPASS ) D o_ccsid Const Like( INT4_T ) D Options( *NOPASS ) D PARM_OPTION C 5 D PARM_CCSID C 6 D rcb DS LikeDs( NLS_reqCtlBlk_ccsid_T ) D error DS LikeDs( ERRC0100_T ) D minLen S Like( INT4_T ) /FREE // Si no se indica el tamaño de la cadena de entrada ni // la de destino no es necesario realizar la conversión // ni ninguna otra cosa. If inStrSize <= 0 Or outStrSize <= 0; //Si interesa, ¡aquí podría lanzarse una excepción! Return; Endif; // Si la cadena de entrada sólo contiene blancos, no hay // conversión, se devuelven los mismos blancos. If %Subst( inStr: 1: inStrSize ) = *BLANKS; %Subst( outStr: 1: outStrSize ) = *BLANKS; Return; Endif; // Configurar el bloque de control para la conversión. rcb = *ALLx'00'; rcb.reqType = 1; // Conversión por CCSID If %Parms() >= PARM_CCSID; rcb.ccsid = o_ccsid; Else; rcb.ccsid = 0; // Usar el CCSID del trabajo Endif; If %Parms() >= PARM_OPTION; rcb.caseReq = o_option; Else; rcb.caseReq = STR_TO_UPPER; Endif; // El tamaño más corto de los parámetros determina cuantos // caracteres se van a convertir minLen = Min( inStrSize: outStrSize ); // Convertir los datos Clear error; QlgConvertCase( rcb : %Subst( inStr: 1: minLen ) : outStr : minLen : error ); If outStrSize > minLen; %Subst( outStr: minLen+1: outStrSize-minLen ) = *BLANKS; Endif; Return; /END-FREE P ConvertCase E Como puedes ver tiene 6 parámetros y uno es de salida (outStr). En otros procedimientos podrían ser más. En ambos casos (función y procedimiento) se define el subprocedimiento como EXPORT y también se añaden a la lista de procedimientos exportados (tipo de funente BND). Espero haber aclarado un poco tus dudas. Saludos, Javier De: [email protected] [mailto:[email protected]] En nombre de alberto Enviado el: martes, 18 de agosto de 2015 9:18 Para: forum.help400 Asunto: Procedimientos en programas de servicio Buenas. Estoy reorganizando el tema de subprogramas, rutinas o como le queramos decir, y estoy haciendo funciones con ellos y creando programas de servicio. Para las funciones con un valor EXPORT, no hay problema, pero claro, tengo muchos subprogramas de estos que me devuelven varios parámetros, vamos, que son procedimientos normales, no funciones. Estos no sé cómo meterlos (ni si se puede) en programa de servicio, ya que al no tener un campo EXPORT no los puedo meter en el fuente *BND. No he encontrado ningún ejemplo que lo haga, ni tampoco he encontrado nada que me diga que no se puede hacer. Me podéis decir si se puede hacer, y en caso afirmativo, cómo? Simplemente, crear un programa de servicio con un procedimiento que devuelva varios parámetros. Gracias____________________________________________________ Únete a Recursos AS400, nuestra Comunidad ( http://bit.ly/db68dd ) Forum.Help400 © Publicaciones Help400, S.L.
____________________________________________________ Únete a Recursos AS400, nuestra Comunidad ( http://bit.ly/db68dd ) Forum.Help400 © Publicaciones Help400, S.L.

