免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: pacman2000
打印 上一主题 下一主题

一个程序员在AS400银行核心系统开发中的技术总结 [复制链接]

论坛徽章:
5
2015亚冠之阿尔艾因
日期:2015-08-10 02:23:34操作系统版块每日发帖之星
日期:2015-08-13 06:20:002015七夕节徽章
日期:2015-08-21 11:06:1715-16赛季CBA联赛之山西
日期:2016-04-13 02:36:59操作系统版块每日发帖之星
日期:2016-04-14 06:20:00
31 [报告]
发表于 2016-04-11 01:33 |只看该作者
先占个位。。。

论坛徽章:
5
2015亚冠之阿尔艾因
日期:2015-08-10 02:23:34操作系统版块每日发帖之星
日期:2015-08-13 06:20:002015七夕节徽章
日期:2015-08-21 11:06:1715-16赛季CBA联赛之山西
日期:2016-04-13 02:36:59操作系统版块每日发帖之星
日期:2016-04-14 06:20:00
32 [报告]
发表于 2016-04-11 01:34 |只看该作者
*面向对象实现

在核心系统这样大型的软件系统设计中,面向对象的设计方法,有助于分解复杂度,既保持抽象统一,又有灵活性。这里说的面向对象设计方法,不是指使用面向对象的编程语言就可以,而是指设计系统的思想。系统架构不进化,即使用Java这样的面向对象编程语言,也一样只会写出流水账似的程序。

面向对象的设计,主要体现在封装、继承、多态。封装表现为,系统应当进行合理的层次划分和粒度划分,识别出哪些是对象,并绑定对象的功能和属性。对照来看,产品工厂就是一种面向对象设计的典型场景。存贷等产品,对应编程语言的类,是一种抽象封装。用这个产品开立的具体账户,就是这个类的实例。产品可以定义各种使用功能,这个对应类的成员函数。产品的功能用到各种参数做逻辑控制,这个对应类的成员变量。最简单的基本产品,可以组合成组合产品,这个类似于多个类组合成新的类。产品的定义有层次关系,例如存款产品--定期存款产品--整存整取--人民币整存整取--人民币一年期整存整取,这个就像类的继承关系。上层产品的参数和功能会继承到下层产品中。如果在产品继承时,下层产品差异化了功能的实现行为,这就是多态。产品工厂在RPGLE中的实现方法并不复杂。将参数按记录方式保存,取产品参数后,如果有账户层定制,读取账户参数值覆盖掉产品参数值,就实现了参数的继承。通过产品号的规则,可以体现产品层次关系,方便判断具体产品是否归属于某一类。产品的功能实现多态,可以按字符串方式保存组件名字,动态调用即可。

不过在Firebird中通过技术写法体现面向对象多态实现,在联机交易主控流程中更为明显。核心系统的联机交易,有一些步骤是所有交易共有的,如获取交易日期时间,获取流水号,机构柜员检查等等。因此,有必要定义通用的交易流程,简化交易应用程序的编写。一方面避免交易应用程序的处理遗漏,另一方面当需要新增或改动共有处理时,防止出现所有交易全面修改的情况。以前的系统,通常很少有共有交易流程,依赖于每个交易应用程序本身的检查处理完备性。在Firebird的主控中,细分出交易流程层,引入面向对象编程方法,将每个交易公共的步骤集中处理。交易主流程中,由两种类型的方法组成,一种是非覆盖方法,各交易不能取代重写,程序名为PPLMNN1到PPLMNN9,另一种是覆盖方法,默认程序名为SPLMNV1到SPLMNV9,可以由交易根据情况单独定制(根据程序名实现对应)。例如020001交易,交易处理程序名为T020001A,则交易主流程中可覆盖的多态方法名字则为T020001A1到T020001A9,分别覆盖SPLMNV1到SPLMNV9,如果未生成对应的多态程序,主控会调用默认程序,一旦生成了多态程序,无需进行配置,主控就会识别并调用交易自定义的多态程序。
下面展示在主控中如何组织交易主流程,实现识别覆盖方法。

  1. /*BEGIN***************************************************************/
  2. /*程序名称:TRANFUNC_H                                             */
  3. /*功能描述:通用交易声明                                           */
  4. /*                                                                   */
  5. /*设计人员:PACMAN          开发人员:PACMAN                     */
  6. /*设计日期:2011-11-11      开发日期:2011-11-11                 */
  7. /*-------------------------------------------------------------------*/
  8. /*维护人员:                                                       */
  9. /*维护日期:                                                       */
  10. /*维护内容:                                                       */
  11. /*                                                                   */
  12. /*END*****************************************************************/

  13. #ifndef TRANFUNC_H
  14. #define TRANFUNC_H

  15. #include "msginfo_h"

  16. typedef void (Tran1)(rpg_msg_info* msg, char* in, char* out);
  17. #pragma linkage(Tran1, OS)
  18. typedef void (Tran2)(rpg_msg_info* msg, char* in, char* out, char* fe);
  19. #pragma linkage(Tran2, OS)

  20. #endif
复制代码
这段头文件声明了两类RPGLE程序给主控调用,一类是参数不带收费数组的,一类是参数带收费数组的。根据处理内容的不同,主控流程中的方法都可以归到这两类中。

  1. /*BEGIN***************************************************************/
  2. /*程序名称:TRANFUNC                                               */
  3. /*功能描述:调度交易主流程程序                                     */
  4. /*                                                                   */
  5. /*设计人员:PACMAN          开发人员:PACMAN                     */
  6. /*设计日期:2011-11-11      开发日期:2011-11-11                 */
  7. /*-------------------------------------------------------------------*/
  8. /*维护人员:                                                       */
  9. /*维护日期:                                                       */
  10. /*维护内容:                                                       */
  11. /*                                                                   */
  12. /*END*****************************************************************/

  13. #include <stdlib.h>
  14. #include <stdio.h>
  15. #include <string.h>
  16. #include <except.h>
  17. #include <mih/triml.h>
  18. #include <mih/rslvsp.h>

  19. #include "dscppgm/cpyrgt_h"
  20. #include "config_h"
  21. #include "tranfunc_h"
  22. #include "msginfo_h"

  23. extern void DBCTL(char*);
  24. extern int trim_str(char *buf, const char *str, int len);
  25. extern void get_msginfo(msg_info *, const rpg_msg_info *);

  26. extern msg_info msginfo;
  27. static int rsl_flag;
  28. static char rsl_pgm[FILENM_LEN+1];

  29. void RSLVSP_PGM_HDLR(_INTRPT_Hndlr_Parms_T *errmsg)
  30. {
  31.   if(strncmp(errmsg->Msg_Id, "MCH3401", 7) == 0)
  32.   {
  33.     strcpy(msginfo.msgid, "EPLMNPGNF ");
  34.     sprintf(msginfo.msgtext, "调用程序%s未找到", rsl_pgm);
  35.     rsl_flag = 1;
  36.   }
  37.   else
  38.   {
  39.     strcpy(msginfo.msgid, "EPLMNPGER ");
  40.     sprintf(msginfo.msgtext, "查找程序%s时出错%7.7s",
  41.             rsl_pgm, errmsg->Msg_Id);
  42.     rsl_flag = 2;
  43.   }
  44. }

  45. int execute_rslvsp(char* pgm_nm, int type, Tran1** pt1, Tran2** pt2)
  46. {
  47.   rsl_flag = 0;
  48.   strcpy(rsl_pgm, pgm_nm);
  49.   #pragma exception_handler (RSLVSP_PGM_HDLR,rsl_flag,0,_C2_MH_ESCAPE,\
  50.                              _CTLA_HANDLE_NO_MSG)
  51.   if(type == 1)
  52.     *pt1 = rslvsp(_Program, pgm_nm, "*LIBL", _AUTH_OBJ_MGMT);
  53.   else
  54.     *pt2 = rslvsp(_Program, pgm_nm, "*LIBL", _AUTH_OBJ_MGMT);
  55.   #pragma disable_handler
  56.   return rsl_flag;
  57. }

  58. void clear_msg(void)
  59. {
  60.   msginfo.msgid[0]='\0';
  61.   msginfo.msgtext[0]='\0';
  62. }

  63. int check_msgid(void)
  64. {
  65.   if (triml(msginfo.msgid, ' ')!=0)
  66.   {
  67.     if (strncmp(msginfo.msgid, "EPLMNREST", 9)==0)
  68.       return 1;
  69.     else
  70.       return -1;
  71.   }
  72.   return 0;
  73. }

  74. int execute_overpgm(char* overwt, char* dft, int type,
  75.                     char* in, char* out, char* fe)
  76. {
  77.   Tran1 *tran1;
  78.   Tran2 *tran2;
  79.   rpg_msg_info rpginfo;
  80.   int ret;

  81.   memset(&rpginfo, ' ', sizeof(rpginfo));
  82.   if (type==1)
  83.   {
  84.     ret=execute_rslvsp(overwt, 1, &tran1, &tran2);
  85.     if (ret==1)
  86.     {
  87.       clear_msg();
  88.       ret=execute_rslvsp(dft, 1, &tran1, &tran2);
  89.     }
  90.     if (ret!=0)
  91.       return -2;
  92.     tran1(&rpginfo, in, out);
  93.   }
  94.   else
  95.   {
  96.     ret=execute_rslvsp(overwt, 2, &tran1, &tran2);
  97.     if (ret==1)
  98.     {
  99.       clear_msg();
  100.       ret=execute_rslvsp(dft, 2, &tran1, &tran2);
  101.     }
  102.     if (ret!=0)
  103.       return -2;
  104.     tran2(&rpginfo, in, out, fe);
  105.   }
  106.   get_msginfo(&msginfo, &rpginfo);
  107.   return check_msgid();
  108. }

  109. int execute_pgm(char* pgm_nm, int type, char* in, char* out, char* fe)
  110. {
  111.   Tran1 *tran1;
  112.   Tran2 *tran2;
  113.   rpg_msg_info rpginfo;
  114.   int ret;

  115.   memset(&rpginfo, ' ', sizeof(rpginfo));
  116.   if (type == 1)
  117.   {
  118.     ret=execute_rslvsp(pgm_nm, 1, &tran1, &tran2);
  119.     if (ret!=0)
  120.       return -2;
  121.     tran1(&rpginfo, in, out);
  122.   }
  123.   else
  124.   {
  125.     ret=execute_rslvsp(pgm_nm, 2, &tran1, &tran2);
  126.     if (ret!=0)
  127.       return -2;
  128.     tran2(&rpginfo, in, out, fe);
  129.   }
  130.   get_msginfo(&msginfo, &rpginfo);
  131.   return check_msgid();
  132. }

  133. int process_tran(const char* tr_cd, char* tr_pgm,
  134.                  char* in, char* out, char* fe, char flg)
  135. {

  136.   char pgms[9][FILENM_LEN+1];
  137.   char trpgm[FILENM_LEN+1];
  138.   int ret=0, i;

  139.   if (trim_str(trpgm, tr_pgm, FILENM_LEN) > FILENM_LEN-1)
  140.   {
  141.     strcpy(msginfo.msgid, "EPLMNPGTL ");
  142.     sprintf(msginfo.msgtext, "交易程序名%s太长", trpgm);
  143.     return -2;
  144.   }

  145.   /*给该交易的每个覆盖方法赋值*/
  146.   for (i=0; i<9; i++)
  147.     sprintf(pgms[i], "%s%1d", trpgm, i+1);

  148.   for (;;)
  149.   {
  150.     /* 交易初始化*/
  151.     if (ret==0)
  152.       ret = execute_pgm("PPLMNN1", 1, in, out, fe);

  153.     /* 覆盖方法1交易预处理 */
  154.     if (ret==0)
  155.       ret = execute_overpgm(pgms[0], "SPLMNV1", 1, in, out, fe);

  156.     /* 柜员归属检查 */
  157.     if (ret==0)
  158.       ret = execute_pgm("PPLMNN2", 1, in, out, fe);

  159.     /* 覆盖方法2交易机构柜员检查*/
  160.     if (ret==0)
  161.       ret = execute_overpgm(pgms[1], "SPLMNV2", 1, in, out, fe);

  162.     /* 生成交易流水号*/
  163.     if (ret==0)
  164.       ret = execute_pgm("PPLMNN3", 1, in, out, fe);

  165.     /* 覆盖方法3交易收费计算*/
  166.     if (ret==0)
  167.       ret = execute_overpgm(pgms[2], "SPLMNV3", 2, in, out, fe);

  168.     /* 费用核对*/
  169.     if (ret==0)
  170.       ret = execute_pgm("PPLMNN4", 2, in, out, fe);

  171.     /* 调用交易程序*/
  172.     if (ret==0)
  173.       ret = execute_pgm(trpgm, 1, in, out, fe);

  174.     /* 调用费用收费并进行传票重整服务*/
  175.     if (ret==0)
  176.       ret = execute_pgm("PPLMNN5", 1, in, out, fe);

  177.     /* 覆盖方法4写输出接口*/
  178.     if (ret==0)
  179.       ret = execute_overpgm(pgms[3], "SPLMNV4", 1, in, out, fe);

  180.     /* 返回处理*/
  181.     if (ret==0)
  182.       ret = execute_pgm("PPLMNN6", 1, in, out, fe);

  183.     if (ret==0 && flg==DEBUG_NO)
  184.       DBCTL(DB_COMMIT);
  185.     else
  186.       DBCTL(DB_ROLLBACK);

  187.     if (ret!=1)
  188.       break;
  189.     clear_msg();
  190.   }

  191.   return ret;
  192. }
复制代码
这段程序中,最重要的是rslvsp()这个系统函数,这个函数用来在指定的库列表中获取系统对象指针。在这里我们用来获取覆盖方法的*PGM程序对象。通过外面用#pragma exception_handler的包围,指定了RSLVSP_PGM_HDLR()作为rslvsp()的异常捕获函数,当捕获MCH3401时,即不存在程序对象。execute_rslvsp()这个函数的功能,就实现了获取指定名字的*PGM,设置指针变量,返回是否找到的标志。execute_overpgm()实现了如果有交易自定义覆盖方法程序存在,则调用,否则调用默认的程序。execute_pgm()实现了调用非覆盖方法。最后的process_tran()实现了交易主流程,依次按流程组织调用非覆盖方法和覆盖方法,进行事务回滚或提交。
    注意交易主流程中,识别是否出现交易重新执行的特殊错误代码EPLMNREST,如果出现则原事务回滚并重新开始执行整个交易流程。这能解决一些特定场景,例如第三方来账如果入账不成功,需要直接挂待销账。通过修改输入结构的某些字段值,并返回EPLMNREST错误代码,这样在核心系统一次交易即可实现入账或挂账功能。

论坛徽章:
5
2015亚冠之阿尔艾因
日期:2015-08-10 02:23:34操作系统版块每日发帖之星
日期:2015-08-13 06:20:002015七夕节徽章
日期:2015-08-21 11:06:1715-16赛季CBA联赛之山西
日期:2016-04-13 02:36:59操作系统版块每日发帖之星
日期:2016-04-14 06:20:00
33 [报告]
发表于 2016-04-11 01:56 |只看该作者
非常奇怪,写的文章贴进来被系统自动吃掉了。这一篇只能先看博客里贴的了。
http://blog.chinaunix.net/uid-283313-id-5699224.html

论坛徽章:
5
2015亚冠之阿尔艾因
日期:2015-08-10 02:23:34操作系统版块每日发帖之星
日期:2015-08-13 06:20:002015七夕节徽章
日期:2015-08-21 11:06:1715-16赛季CBA联赛之山西
日期:2016-04-13 02:36:59操作系统版块每日发帖之星
日期:2016-04-14 06:20:00
34 [报告]
发表于 2016-04-13 02:36 |只看该作者
*交易和组件写法

Firebird核心系统的整体结构,是由主控--交易--组件这几个层次组成的。联机交易主控由C程序编写,异步交易主控和日终批量主控由CL和RPGLE程序编写。主控通过交易码调用相应的交易RPGLE程序,交易程序又通过CALLP调用不同模块的组件RPGLE程序,完成整个处理逻辑。交易程序和组件程序都总结了一套模版样例,下面就介绍样例程序的写法。

在介绍交易和组件程序写法之前,先介绍统一由/COPY引入的通用程序,这部分程序放在DSCPPGM中。注意/COPY不宜滥用,一定要结合命名规范,否则极易导致程序可读性差。
首先是HEAD。这个文件定义了copyright和几个日期fmt规则。

  1.      **BEGIN***************************************************************
  2.      **程序名称:程序公共控制头                                         *
  3.      **功能描述:程序公共控制头                                         *
  4.      **                                                                   *
  5.      **版本:2014-10-21_1                                               *
  6.      **                                                                   *
  7.      **设计人员:PACMAN          开发人员:AUTOGEN                    *
  8.      **设计日期:2011-08-30      开发日期:2011-08-30                 *
  9.      **                                                                   *
  10.      **END*****************************************************************
  11.      **
  12.      HCOPYRIGHT('Firebird V2.1 corebanking system, CSW SHANGHAI')
  13.      HDATFMT(*ISO) TIMFMT(*ISO) DATEDIT(*YMD)
复制代码
然后是ENUM,这个文件是引入枚举常量定义,在数据字典和枚举值部分已经有了介绍,这里就不重复了。
接下来是PGDS,这个文件定义了每个程序都会引入的PSDS和INFDS结构定义,错误结构定义,错误信息数组,接口数组条数,以及特殊用途变量等。

  1.      **BEGIN***************************************************************
  2.      **程序名称:程序公共控制头                                         *
  3.      **功能描述:程序公共控制头                                         *
  4.      **                                                                   *
  5.      **版本:2014-11-23_1                                               *
  6.      **                                                                   *
  7.      **设计人员:PACMAN          开发人员:AUTOGEN                    *
  8.      **设计日期:2011-08-30      开发日期:2011-08-30                 *
  9.      **                                                                   *
  10.      **END*****************************************************************
  11.      **
  12.      **公共常量
  13.      **输出传票数组条数
  14.      DC_NBOTVC         C                   CONST(100)
  15.      **输入券别数组条数
  16.      DC_NBINCS         C                   CONST(30)
  17.      **输入费用数组条数
  18.      DC_NBINFE         C                   CONST(30)
  19.      **输出费用数组条数
  20.      DC_NBOTFE         C                   CONST(30)
  21.      **替换错误参数条数
  22.      DC_NBMSDS         C                   CONST(9)
  23.      **记录被锁错误信息
  24.      DC_MGLOCK         C                   CONST('记录被锁')
  25.      **********************************************************************
  26.      **错误处理结构
  27.      **程序状态结构
  28.      DRPGPSDS         SDS
  29.      D PG_MAINPROC             1     10A
  30.      D PG_STATUS              11     15A
  31.      D PG_PRVSTAT             16     20A
  32.      D PG_SRCLINE             21     28A
  33.      D PG_ROUTINE             29     36A
  34.      D PG_PARMNUM             37     39S 0
  35.      D PG_MSID                40     46A
  36.      D PG_PGMLIB              81     90A
  37.      D PG_EXCPDT              91    170A
  38.      D PG_LSERRFL            175    184A
  39.      D PG_JOBDATE            191    198A
  40.      D PG_FLINFO             209    243A
  41.      D PG_JOBNAME            244    253A
  42.      D PG_JOBUSER            254    263A
  43.      D PG_JOBNUM             264    269S 0
  44.      D PG_RUNDATE            276    281S 0
  45.      D PG_RUNTIME            282    287S 0
  46.      D PG_SRCFILE            304    313A
  47.      D PG_SRCLIB             314    323A
  48.      D PG_SRCMBR             324    333A
  49.      D PG_PGMNAME            334    343A
  50.      D PG_MODNAME            344    353A
  51.      D PG_SRCLNADD           354    355B 0
  52.      D PG_FLILNADD           356    357B 0
  53.      D PG_USRPRF             358    367A
  54.      D PG_EXTERR             368    371I 0
  55.      **文件状态结构
  56.      DFILESDS          DS                  BASED(FILEDSP)
  57.      D FL_FILE                 1      8A
  58.      D FL_OPNIND               9      9A
  59.      D FL_EOFIND              10     10A
  60.      D FL_STATUS              11     15S 0
  61.      D FL_OPCODE              16     21A
  62.      D FL_ROUTINE             22     29A
  63.      D FL_SRCLINE             30     37A
  64.      D FL_RECORD              38     45A
  65.      D FL_MSID                46     52A
  66.      D FL_SRCLNADD            77     78B 0
  67.      D FL_ODPTYPE             81     82A
  68.      D FL_FILENAME            83     92A
  69.      D FL_LIBRARY             93    102A
  70.      D FL_SPLFILE            103    112A
  71.      D FL_SPLLIB             113    122A
  72.      D FL_RCDLEN             125    126I 0
  73.      D FL_KEYLEN             127    128I 0
  74.      D FL_MEMBER             129    138A
  75.      D FL_TYPE               147    148I 0
  76.      D FL_RCDNUM             156    159I 0
  77.      D FL_SPLNUM             160    163I 0
  78.      D FL_OVERFLOW           188    189I 0
  79.      D FL_BASEDMBRS          211    212I 0
  80.      D FL_OPENID             214    215B 0
  81.      D FL_RCDFMTLEN          216    217I 0
  82.      D FL_CCSID              218    219I 0
  83.      D FL_FBSIZE             367    370I 0
  84.      D FL_KEYNUM             387    388I 0
  85.      D FL_FBKEYLEN           393    394I 0
  86.      D FL_MBRNUM             395    396I 0
  87.      D FL_RRN                397    400I 0
  88.      D FL_KEY                401   2400A
  89.      **文件状态结构指针
  90.      DFILEDSP          S               *
  91.      **********************************************************************
  92.      **公共结构
  93.      **引入数据字典
  94.      DDICT           E DS                  EXTNAME(DICT) QUALIFIED TEMPLATE
  95.      **公共错误信息接口
  96.      DPMG            E DS                  EXTNAME(MESG) QUALIFIED
  97.      **错误信息替换数组
  98.      DA_MSDS           S                   DIM(C_NBMSDS) LIKE(DICT.@@MSDS)
  99.      **********************************************************************
  100.      **特殊变量
  101.      **是否执行过错误处理程序
  102.      DPG_ERYNFG        S                   LIKE(DICT.@@YNFG) INZ(YNFG_NO)
  103.      **是否程序已执行初始化
  104.      DPG_FRYNFG        S                   LIKE(DICT.@@YNFG) INZ(YNFG_YES)
复制代码
最后是通用处理过程PGCM,这个程序定义了错误捕获程序以及检查,退出等通用过程,并以#开头的过程名,与交易中普通@开头过程名以示区分。

  1.      **BEGIN***************************************************************
  2.      **程序名称:程序公共子程序                                         *
  3.      **功能描述:程序公共子程序                                         *
  4.      **                                                                   *
  5.      **版本:2014-10-21_1                                               *
  6.      **                                                                   *
  7.      **设计人员:PACMAN          开发人员:AUTOGEN                    *
  8.      **设计日期:2011-08-30      开发日期:2011-08-30                 *
  9.      **                                                                   *
  10.      **END*****************************************************************
  11.      **
  12.      **********************************************************************
  13.      ** #EXIT返回
  14.      **********************************************************************
  15.      C     #EXIT         BEGSR
  16.      **
  17.      C                   EVAL      PG_FRYNFG = YNFG_NO
  18.      C/IF DEFINED(USELR)
  19.      C                   EVAL      *INLR = *ON
  20.      C/ENDIF
  21.      C                   RETURN
  22.      **
  23.      C                   ENDSR
  24.      **********************************************************************
  25.      ** #ERR 取错误信息
  26.      **********************************************************************
  27.      C     #ERR          BEGSR
  28.      **
  29.      C                   EVAL      PMG.MSFLNM = PG_SRCMBR
  30.      C                   IF        PMG.BKMSDS = *BLANKS
  31.      C                   CALL      'SCNCMMG'
  32.      C                   PARM                    PMG
  33.      C                   PARM                    A_MSDS
  34.      C                   ENDIF
  35.      C                   EXSR      #EXIT
  36.      **
  37.      C                   ENDSR
  38.      **********************************************************************
  39.      ** #CHKMSG检查程序返回信息
  40.      **********************************************************************
  41.      C     #CHKMSG       BEGSR
  42.      **
  43.      C                   IF        PMG.BKMSID <> *BLANKS
  44.      C                   EXSR      #EXIT
  45.      C                   ENDIF
  46.      **
  47.      C                   ENDSR
  48.      **********************************************************************
  49.      ** *PSSR程序异常处理
  50.      **********************************************************************
  51.      C     *PSSR         BEGSR
  52.      **
  53.      C                   IF        PG_ERYNFG = YNFG_NO
  54.      C                   EVAL      PG_ERYNFG = YNFG_YES
  55.      C                   EVAL      PMG.MSFLNM = PG_SRCMBR
  56.      C                   EVAL      PMG.MSCDLN = PG_SRCLINE
  57.      C                   EVAL      PMG.BKMSID = 'F' + PG_MSID
  58.      C                   EVAL      PMG.BKMSDS = PG_EXCPDT
  59.      C                   EVAL      PMG.OTMSDS = PG_STATUS+' '+PG_PGMLIB+' '+
  60.      C                                          PG_PGMNAME
  61.      C                   EXSR      #EXIT
  62.      C                   ENDIF
  63.      **
  64.      C                   ENDSR
  65.      **********************************************************************
  66.      ** #FLEX文件异常处理
  67.      **********************************************************************
  68.      C     #FLEX         BEGSR
  69.      **
  70.      C                   EVAL      PMG.MSFLNM = PG_SRCMBR
  71.      C                   EVAL      PMG.MSCDLN = FL_SRCLINE
  72.      C                   EVAL      PMG.BKMSID = 'F' + FL_MSID
  73.      C                   IF        FL_STATUS = 1218
  74.      C                   CALL      'GETOBJTXT'
  75.      C                   PARM      FL_LIBRARY    V_FLEXLIB        10
  76.      C                   PARM      FL_FILENAME   V_FLEXOBJ        10
  77.      C                   PARM      '*FILE'       V_FLEXTYP         7
  78.      C                   PARM      *BLANKS       V_FLEXTEXT       50
  79.      C                   EVAL      PMG.BKMSDS = %TRIM(V_FLEXTEXT) +
  80.      C                                          %TRIM(FL_FILENAME) + '.' +
  81.      C                                          %TRIM(FL_MEMBER) + C_MGLOCK +
  82.      C                                          ',' + PG_EXCPDT
  83.      C                   ELSE
  84.      C                   EVAL      PMG.BKMSDS = PG_EXCPDT
  85.      C                   ENDIF
  86.      C                   EVAL      PMG.OTMSDS = PG_FLINFO
  87.      C                   EXSR      #EXIT
  88.      **
  89.      C                   ENDSR
复制代码
交易程序样例以6位交易码000000为例,交易程序名为T000000A,有两个输入T000000I1,T000000I2,两个输出T000000O1,T00000O2。其中I2和O2是数组。
T000000I1程序如下。

  1.      A                                      REF(DICT)
  2.      A          R RT000000I1
  3.      A            BKBRNO    R               REFFLD(@@BRNO)
  4.      A                                      COLHDG('机构')
  5.      A                                      TEXT('机构')
复制代码
T000000I2程序如下。

  1.      A                                      REF(DICT)
  2.      A          R RT000000I2
  3.      A            BKTLNO    R               REFFLD(@@TLNO)
  4.      A                                      COLHDG('柜员')
  5.      A                                      TEXT('柜员')
复制代码
T000000O1程序如下。

  1.      A                                      REF(DICT)
  2.      A          R RT000000O1
  3.      A            BKTRWB    R               REFFLD(@@TRWB)
  4.      A                                      COLHDG('交易流水号')
  5.      A                                      TEXT('交易流水号')
复制代码
T000000O1程序如下。

  1.      A                                      REF(DICT)
  2.      A          R RT000000O2
  3.      A            BKACNO    R               REFFLD(@@ACNO)
  4.      A                                      COLHDG('账号')
  5.      A                                      TEXT('账号')
复制代码
交易程序T000000A程序如下。

  1.      **BEGIN***************************************************************
  2.      **程序名称:交易程序模板                                           *
  3.      **功能描述:交易程序开发规范                                       *
  4.      **                                                                   *
  5.      **设计人员:CSWWM           开发人员:CSWWM                      *
  6.      **设计日期:2011-08-30      开发日期:2011-08-30                 *
  7.      **-------------------------------------------------------------------*
  8.      **维护人员:CSWYJ                                                  *
  9.      **维护日期:2014-10-17                                             *
  10.      **维护内容:按新规范改写                                           *
  11.      **                                                                   *
  12.      **END*****************************************************************
  13.      H/COPY DSCPPGM,HEAD
  14.      **********************************************************************
  15.      **引入数据字典枚举常量
  16.      D/COPY DSCPPGM,ENUM
  17.      **引入公共程序体
  18.      D/COPY DSCPPGM,PGDS
  19.      **********************************************************************
  20.      **决定是否以*LR=*ON结束,统一使用激活组管理则保持注释
  21.      D*/DEFINE USELR
  22.      **定义常量
  23.      DC_I1             C                   CONST('交易程序模版')
  24.      DC_MGBRNO         C                   CONST('机构号')
  25.      DC_NBI2           C                   CONST(20)
  26.      DC_NBO2           C                   CONST(20)
  27.      *************************
  28.      **引入调用服务原型
  29.      D/COPY CETPEXP,SCETPSVP
  30.      D/COPY CNCMSVC,SCNCMTAP
  31.      **定义参照外部结构的结构、数组 
  32.      DT_INHD         E DS                  EXTNAME(INHD)      QUALIFIED TEMPLATE
  33.      DT_INFE         E DS                  EXTNAME(INFE)      QUALIFIED TEMPLATE
  34.      DT_INCS         E DS                  EXTNAME(INCS)      QUALIFIED TEMPLATE
  35.      DT_OTHD         E DS                  EXTNAME(OTHD)      QUALIFIED TEMPLATE
  36.      DT_OTVC         E DS                  EXTNAME(OTVC)      QUALIFIED TEMPLATE
  37.      DT_I1           E DS                  EXTNAME(T000000I1) QUALIFIED TEMPLATE
  38.      DT_I2           E DS                  EXTNAME(T000000I2) QUALIFIED TEMPLATE
  39.      DT_O1           E DS                  EXTNAME(T000000O1) QUALIFIED TEMPLATE
  40.      DT_O2           E DS                  EXTNAME(T000000O2) QUALIFIED TEMPLATE
  41.      *************************
  42.      **定义参照内部结构、变量(LIKE)的结构、数组
  43.      DPIN              DS                  QUALIFIED
  44.      D INHD                                LIKEDS(T_INHD)
  45.      D INFE                                DIM(C_NBINFE) LIKEDS(T_INFE)
  46.      D INCS                                DIM(C_NBINCS) LIKEDS(T_INCS)
  47.      D I1                                  LIKEDS(T_I1)
  48.      D I2                                  DIM(C_NBI2) LIKEDS(T_I2)
  49.      **
  50.      DPOT              DS                  QUALIFIED
  51.      D OTHD                                LIKEDS(T_OTHD)
  52.      D OTVC                                DIM(C_NBOTVC) LIKEDS(T_OTVC)
  53.      D O1                                  LIKEDS(T_O1)
  54.      D O2                                  DIM(C_NBO2) LIKEDS(T_O2)
  55.      *************************
  56.      **临时变量(无法参照定义)的结构体
  57.      DD_VARS           DS
  58.      **定义参照数据字典(LIKE)的变量 
  59.      D V_BKTRWB                            LIKE(DICT.@@TRWB)
  60.      **定义无法参照(自定义)的临时变量 
  61.      D V_NUM                          5P 0
  62.      **********************************************************************
  63.      **定义程序入口
  64.      C     *ENTRY        PLIST
  65.      C                   PARM                    PMG
  66.      C                   PARM                    PIN
  67.      C                   PARM                    POT
  68.       /FREE

  69.        EXSR @INIT;
  70.        EXSR @CHEK;
  71.        EXSR @MAIN;
  72.        EXSR @RETN;
  73.        EXSR #EXIT;

  74.        //---------------------------------------
  75.        //程序初始化
  76.        //---------------------------------------
  77.        BEGSR @INIT;
  78.          //初始化公共定义的结构
  79.          CLEAR PMG;
  80.          CLEAR A_MSDS;
  81.          //初始化交易自有输出接口,注意已在覆盖方法中初始化过OTHD,OTVC的不要清
  82.          CLEAR POT.O1;
  83.          CLEAR POT.O2;
  84.          //初始化自定义结构
  85.          CLEAR D_VARS;
  86.        ENDSR;

  87.        //---------------------------------------
  88.        //检查输入接口值的正确性
  89.        //---------------------------------------
  90.        BEGSR @CHEK;
  91.          //机构号必输
  92.          IF PIN.I1.BKBRNO = *BLANKS;
  93.             EVAL PMG.BKMSID = 'EIOND';
  94.             EVAL A_MSDS(1)  = C_I1;
  95.             EVAL A_MSDS(2)  = C_MGBRNO;
  96.             EXSR #ERR;
  97.          ENDIF;

  98.        //---------------------------------------
  99.        //程序的主流程
  100.        //---------------------------------------
  101.        BEGSR @MAIN;
  102.          //变更
  103.          CLEAR TPSVF1;
  104.          CLEAR TPSVF2;
  105.          EVAL TPSVF1.BKBRNO = PIN.I1.BKBRNO;
  106.          CALLP SCETPSV(PMG:TPSVF1:TPSVF2);
  107.          EXSR  #CHKMSG;
  108.          //调用某模块记账服务
  109.          //CALLP SCETPAC(PMG:TPSVF1:POT.OTVC);
  110.          //EXSR  #CHKMSG;
  111.        ENDSR;

  112.        //---------------------------------------
  113.        //程序返回处理
  114.        //---------------------------------------
  115.        BEGSR @RETN;
  116.          //登记返回数组条数
  117.          CLEAR TPSVF1;
  118.          EVAL CMTAF1.RDYNFG = YNFG_NO;
  119.          EVAL CMTAF1.WTYNFG = YNFG_YES;
  120.          EVAL CMTAF1.FDFLNM = 'O2RECD';
  121.          EVAL CMTAF1.FDSQNU = V_NUM;
  122.          CALLP SCNCMTA(PMG:CMTAF1);
  123.          EXSR  #CHKMSG;
  124.        ENDSR;

  125.       /END-FREE
  126.      C/COPY DSCPPGM,PGCM
复制代码
在交易程序中,如果需要调用模块组件,那么会用/COPY引入组件的PROTOTYPE声明和组件参数结构定义,这部分在组件样例中介绍。
交易的参数统一为3个。先是PMG,错误信息结构,用于将出错信息返回主控,判断交易是否成功,组织出错报文。再是PIN,输入复合结构,依次由INHD输入应用头,INFE输入费用数组,INCS输入券面数组,I1,I2等交易自身结构组成。最后是POT,输出复合结构,依次由OTHD输出应用头,OTVC输出记账传票数组,O1,O2等交易自身结构组成。这部分可以参见报文格式一节内容。
程序中将所有临时变量都定义在D_VARS结构下,这样方便一开始的初始化,可以用CLEAR D_VARS直接清值。
交易程序中调用了组件程序模版SCETPSV,同样第一个参数要是PMG,这样结合#CHKMSG,可以让出错信息层层传递返回。接着是组件自己的参数。如果是记账组件,那么最后一个参数必须是传票数组POT.OTVC层层传递,以实现将交易所有产生的记账传票流水按套顺序重组,返回前端打印。现有的很多系统,只能体现交易所有借贷传票,无法体现传票先后顺序,也不能按会计原理进行最小成套归类,并保证每套不会出现多借多贷,而Firebird则做到了这一点。
在返回处理过程中,特别注意如果是输出有数组,需要在这段中调用SCNCMTA设置输出数组实际有值的条数,主控会根据实际条数去简化返回报文。

组件程序样例SCETPSV,除了固定的PMG参数外,有F1,F2两个自有参数。组件由SCETPSVP组件声明,SCETPSVF1,SCETPSVF2两个参数结构定义,SCETPSV组件程序这几个部分组成。
SCETPSVF1参数文件如下。

  1.      A                                      REF(DICT)
  2.      A          R RSCETPSVF1
  3.      A            BKBRNO    R               REFFLD(@@BRNO)
  4.      A                                      COLHDG('机构号')
  5.      A                                      TEXT('机构号')
复制代码
SCETPSVF2参数文件如下。

  1.      A                                      REF(DICT)
  2.      A          R RSCETPSVF2
  3.      A            MTTLNO    R               REFFLD(@@TLNO)
  4.      A                                      COLHDG('柜员号')
  5.      A                                      TEXT('柜员号')
复制代码
SCETPSVP组件声明文件如下。

  1.      **BEGIN***************************************************************
  2.      **程序名称:服务程序模板原型                                       *
  3.      **功能描述:服务程序模版原型及参数接口定义                         *
  4.      **                                                                   *
  5.      **版本:2014-10-21_1                                               *
  6.      **                                                                   *
  7.      **设计人员:CSWWM           开发人员:CSWWM                      *
  8.      **设计日期:2011-08-30      开发日期:2011-08-30                 *
  9.      **-------------------------------------------------------------------*
  10.      **维护人员:CSWYJ                                                  *
  11.      **维护日期:2014-10-17                                             *
  12.      **维护内容:按新规范改写                                           *
  13.      **                                                                   *
  14.      **END*****************************************************************
  15.      **常量定义
  16.      DC_NBTPSVF2       C                   CONST(50)
  17.      *************************
  18.      **参数接口定义
  19.      DTPSVF1         E DS                  EXTNAME(SCETPSVF1) QUALIFIED
  20.      DT_TPSVF2       E DS                  EXTNAME(SCETPSVF2) QUALIFIED TEMPLATE
  21.      DTPSVF2           DS                  QUALIFIED
  22.      D RECD                                LIKE(DICT.@@RECD)
  23.      D ARR                                 DIM(C_NBTPSVF2) LIKEDS(T_TPSVF2)
  24.      *************************
  25.      **程序原型定义
  26.      DSCETPSV          PR                  EXTPGM('SCETPSV')
  27.      D PMG                                 LIKEDS(PMG)
  28.      D TPSVF1                              LIKEDS(TPSVF1)
  29.      D TPSVF2                              LIKEDS(TPSVF2)
复制代码
这里要注意的是,组件的数组与交易接口数组不同,全部是带上RECD实际记录条数的复合结构。这样才能知道最大容量的数组,实际存放了多少条有效记录。
组件程序SCETPSV文件如下。

  1.      **BEGIN***************************************************************
  2.      **程序名称:组件程序模板                                           *
  3.      **功能描述:组件程序开发规范                                       *
  4.      **                                                                   *
  5.      **设计人员:CSWWM           开发人员:CSWWM                      *
  6.      **设计日期:2011-08-30      开发日期:2011-08-30                 *
  7.      **-------------------------------------------------------------------*
  8.      **维护人员:                                                       *
  9.      **维护日期:                                                       *
  10.      **维护内容:                                                       *
  11.      **                                                                   *
  12.      **END*****************************************************************
  13.      H/COPY DSCPPGM,HEAD
  14.      **********************************************************************
  15.      **在F表中声明的程序操作的数据表,且同时声明数据表的操作方式
  16.      **数据表声明顺序如下:
  17.      **1)、声明操作方式为只读(I)的数据表;
  18.      **2)、声明操作方式为读(I)、写(A)的数据表;
  19.      **3)、声明操作方式为更改(U)的数据表;
  20.      **4)、声明操作方式为更新(U)、写(A)的数据表;
  21.      **5)、声明操作方式为只写(O)的数据表;
  22.      FACNBRMF   UF   E           K DISK    INFSR(#FLEX) INFDS(S_CNBRMF)
  23.      F                                     QUALIFIED
  24.      FACNTLMF   UF A E           K DISK    INFSR(#FLEX) INFDS(S_CNTLMF)
  25.      F                                     QUALIFIED COMMIT
  26.      **********************************************************************
  27.      **引入数据字典枚举常量
  28.      D/COPY DSCPPGM,ENUM
  29.      **引入程序公共结构
  30.      D/COPY DSCPPGM,PGDS
  31.      *************************
  32.      **文件结构定义
  33.      DS_CNBRMF         DS                  LIKEDS(FILESDS)
  34.      DK_CNBRMF         DS                  LIKEREC(ACNBRMF.RACNBRMF:*KEY)
  35.      DR_CNBRMF         DS                  LIKEREC(ACNBRMF.RACNBRMF:*INPUT)
  36.      DW_CNBRMF         DS                  LIKEREC(ACNBRMF.RACNBRMF:*OUTPUT)
  37.      DS_CNTLMF         DS                  LIKEDS(FILESDS)
  38.      DR_CNTLMF         DS                  LIKEREC(ACNTLMF.RACNTLMF:*INPUT)
  39.      *************************
  40.      **决定是否以*LR=*ON结束
  41.      D*/DEFINE USELR
  42.      **常量定义
  43.      DC_F1             C                   CONST('组件程序模版')
  44.      DC_MGBRMF         C                   CONST('机构表')
  45.      DC_MGBRNO         C                   CONST('机构号')
  46.      *************************
  47.      **引入调用服务原型
  48.      D/COPY CETPEXP,SCETPSVP
  49.      **定义参照外部结构(EXTNAME)的结构、数组 
  50.      **定义参照内部结构、变量(LIKE)的结构、数组
  51.      *************************
  52.      **临时变量结构
  53.      DD_VARS           DS
  54.      **定义参照数据字典(LIKE)的变量 
  55.      D V_BKBRNO                            LIKE(DICT.@@BRNO)
  56.      **定义无法参照的临时变量 
  57.      D V_NUM                          5P 0
  58.      ********************************************************************
  59.      **程序入口定义
  60.      C     *ENTRY        PLIST
  61.      C                   PARM                    PMG
  62.      C                   PARM                    TPSVF1
  63.      C                   PARM                    TPSVF2
  64.       /FREE

  65.        EXSR  @INIT;
  66.        EXSR  @CHEK;
  67.        EXSR  @MAIN;
  68.        EXSR  #EXIT;

  69.        //---------------------------------------------------------
  70.        //程序初始化
  71.        //---------------------------------------------------------
  72.        BEGSR  @INIT;
  73.          //初始化公共定义的结构
  74.          CLEAR  PMG;
  75.          CLEAR  A_MSDS;
  76.          //初始化文件读取操作结构,除文件异常结构外
  77.          CLEAR  K_CNBRMF;
  78.          CLEAR  R_CNBRMF;
  79.          CLEAR  R_CNTLMF;
  80.          //初始化自定义结构
  81.          CLEAR  D_VARS;
  82.        ENDSR;

  83.        //---------------------------------------------------------
  84.        //检查接口传递值的正确性
  85.        //---------------------------------------------------------
  86.        BEGSR  @CHEK;
  87.          //机构号为空
  88.          IF  TPSVF1.BKBRNO = *BLANKS;
  89.            PMG.BKMSID = 'EIOND';
  90.            A_MSDS(1) = C_F1;
  91.            A_MSDS(2) = C_MGBRNO;
  92.            EXSR  #ERR;
  93.          ENDIF;
  94.        ENDSR;

  95.        //---------------------------------------------------------
  96.        //程序的主流程
  97.        //---------------------------------------------------------
  98.        BEGSR  @MAIN;
  99.          K_CNBRMF.BKBRNO = TPSVF1.BKBRNO;
  100.          FILEDSP = %ADDR(S_CNBRMF);
  101.          CHAIN  %KDS(K_CNBRMF) ACNBRMF.RACNBRMF R_CNBRMF;
  102.          IF  NOT %FOUND(ACNBRMF);
  103.            PMG.BKMSID = 'ENTRD';
  104.            A_MSDS(1) = C_MGBRMF;
  105.            A_MSDS(2) = C_MGBRNO + K_CNBRMF.BKBRNO;
  106.            EXSR  #ERR;
  107.          ENDIF;
  108.          EVAL-CORR W_CNBRMF = R_CNBRMF;
  109.          UPDATE  ACNBRMF.RACNBRMF  W_CNBRMF;
  110.          EVAL-CORR TPSVF2.ARR(1) = W_CNBRMF;
  111.        ENDSR;

  112.       /END-FREE
  113.      C/COPY DSCPPGM,PGCM
复制代码
这里值得注意的是,组件程序本身也要/COPY引入组件声明,以为声明包含了原型定义,以及参数结构定义。另外,由于引入了异常处理程序,现在应用程序编写起来就清晰多了,无需考虑各种文件操作的异常报错处理,是不是很方便呢。

至此,组件和交易模版介绍完了,按照这个模版,就可以编写实际使用的各个模块程序,挂在交易主控中执行了。

论坛徽章:
5
2015亚冠之阿尔艾因
日期:2015-08-10 02:23:34操作系统版块每日发帖之星
日期:2015-08-13 06:20:002015七夕节徽章
日期:2015-08-21 11:06:1715-16赛季CBA联赛之山西
日期:2016-04-13 02:36:59操作系统版块每日发帖之星
日期:2016-04-14 06:20:00
35 [报告]
发表于 2016-07-09 09:58 |只看该作者
操作系统V7R3的主要变化:

    7.3
     CL语言
    没有新增的内容。

    C/C++语言
    新增了对C++11标准的支持。通过LANGLVL(*EXTENDED0X)可以开放使用。

    RPG语言
    增加了完全自由格式的写法。第一行**FREE表示整个文件全部按照自由格式编写。代码可以从第1列开始,无代码行长度限制。文件内不能出现固定格式,但可以通过/COPY,/INCLUDE引入固定格式片段。
    新增%SCANR函数,字符串从右往左查找子串出现的位置。
    %SCAN增加参数,可以指定查找到源字符串的第多少个字符为止。例如%SCAN('abc' : string : 1 : 10),在string的第1到第10位子串中查找'abc'。
    放宽DS结构对IO操作的限制。所有EXTNAME或者LIKEREC定义的结构,如果用*ALL修饰,则可以用于任何READ,WRITE,UPDATE等IO操作。用LIKEREC参照文件记录格式名定义的结构,如果文件的输出与输入记录格式完全相同,那么LIKEREC的结构也可以用于任何IO操作。
    增加了*NULL的支持。

论坛徽章:
0
36 [报告]
发表于 2016-08-30 16:36 |只看该作者
大神还会继续更新么

论坛徽章:
5
2015亚冠之阿尔艾因
日期:2015-08-10 02:23:34操作系统版块每日发帖之星
日期:2015-08-13 06:20:002015七夕节徽章
日期:2015-08-21 11:06:1715-16赛季CBA联赛之山西
日期:2016-04-13 02:36:59操作系统版块每日发帖之星
日期:2016-04-14 06:20:00
37 [报告]
发表于 2016-08-30 22:04 |只看该作者
shaohua2208 发表于 2016-08-30 16:36
大神还会继续更新么

已经写完了呀。还有个AS400系统的安装和环境搭建文档,和开发关系不大,可以参考一下。

论坛徽章:
5
2015亚冠之阿尔艾因
日期:2015-08-10 02:23:34操作系统版块每日发帖之星
日期:2015-08-13 06:20:002015七夕节徽章
日期:2015-08-21 11:06:1715-16赛季CBA联赛之山西
日期:2016-04-13 02:36:59操作系统版块每日发帖之星
日期:2016-04-14 06:20:00
38 [报告]
发表于 2016-09-01 00:47 |只看该作者

附件为AS400操作系统V6R1通过HMC的安装步骤图文说明,以及系统参数设置说明。
安装完后以2989第二语言为开发环境。

AS400操作系统V6R1安装.zip

1.65 MB, 下载次数: 95

系统参数调整.zip

12.89 KB, 下载次数: 61

论坛徽章:
0
39 [报告]
发表于 2016-10-17 16:16 |只看该作者
学习了,谢谢分享。

论坛徽章:
0
40 [报告]
发表于 2017-01-03 17:06 |只看该作者
谢谢分享!内容我喜欢!

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP