序言
本文分享一个通过数据库(ORACLE)的存储过程,遵循“对修改封闭,对增加开放”的开闭原则,实现的可扩展性极强的灵活接口方案。
背景
本人从事离散型MES系统的开发工作,近期负责了一个PCBA(电子、手机)行业的MES系统二开工作。PCBA行业使用ATE工具(自动测试工具)进行写号、查号、置标志位等工作,写号查号等相关数据需要与MES系统进行数据交互,同时MES系统也需要管控ATE工具的作业流程。如查号必须在写号后,没有写号的工具不能进行查号等流程管控。由于ATE工具的测试不须人员参与,所以MES系统需要开发相关接口给ATE工具端调用,进行数据交互和流程管控等工作。
MES系统前期已有途程检查,分配IMEI、MAC、BT数据,过站等相关基础接口可供ATE工具调用,基本能满足要求。但在面对某些客户定制化的需求时(如上传软件版本、记录测试内容),就必须在原有接口的基础上增加或修改程序,然后把C#编写的dll封装成COM组件(因为ATE工具使用C++编写的),更新文档,再通知ATE工具编写人员重新连入新版本进行编写和调试,最后再更新现有工具的所有版本。别看流程描述起来比较简单,但实际操作起来涉及到沟通、部门协作等问题,非常繁琐累人。
基于上述原因,笔者思考是否有一个方案能够灵活面对客户的定制化需求,又不需涉及到太多变更,特别是重新编译、重新连入和更新等操作。有志者事竟成,经过一番研究与思考后,笔者决定采用“存储过程”来进行实现。
整体方案
方案详述
为了更好的讲述该方案,下面将以代码(或伪代码)的方式进行讲述。
接口方法调用存储过程
public bool SetATEData(string iCmdType, string iText, out string oText, out string oErrMessage) { return ExecProc.ProcInputPara(iCmdType, iText, out oText, out oErrMessage); }
对该方法的详细介绍如下:
Bool SetATEData(String iCmdType, String iText, String oText, String oErrMessage)
参数说明
iCmdType----传入的接口代码,如1001;可自定义
iText-----------传入此接口参数列表,采用键值对的方式传入,以“|”分隔,例如:
“Field1=Value1|Field2=Value2|Field3=Value3|... … ”(也可定义其他分隔符,如有需要,请考虑转义字符)
oText----------如接口需要返回参数的列表,采用键值对的方式输出,以“|”分隔,例如:
“Key1=Value1| Key2=Value2| Key3=Value3|... … “,可为空
oErrMessage----当方法返回false时,传出具体的出错信息
注:
ExecProc.ProcInputPara(iCmdType, iText, out oText, out oErrMessage)是笔者写的一个静态方法,用于调用存储过程。实际应用中需要自行编写。为了做好记录,笔者也会上传该静态类,仅供参考。
存储过程统一入口
根据传入的iCmdType查询对应的存储过程名称,若存在则动态执行该存储过程。
储存存储过程的表格结构如下所示:
存储过程的代码(ORACLE 11g版本)如下所示:
CREATE OR REPLACE PROCEDURE PROCDLLBASE (ICMDTYPE IN VARCHAR2,ITEXT IN VARCHAR2,OTEXT OUT VARCHAR2,OERRMSG OUT VARCHAR2,ORESULT OUT INTEGER)ASv_Sql varchar2(4000);v_ProcName TBLPROCGROUP.PROCNAME%TYPE;i_ProcCount integer;BEGIN SELECT COUNT(1) INTO i_ProcCount from TBLPROCGROUP where PROCID=ICMDTYPE; IF i_ProcCount=0 THEN OERRMSG:='CMDTYPE2PROC_NOT_FOUND'; ORESULT:=0; RETURN; END IF; SELECT PROCNAME INTO v_ProcName from TBLPROCGROUP where PROCID=ICMDTYPE; v_Sql:='begin '|| v_ProcName || '(:itext,:otext,:oerrmsg,:oresult);end;'; EXECUTE IMMEDIATE v_Sql using in ITEXT,out OTEXT,out OERRMSG,out ORESULT; EXCEPTION WHEN OTHERS THEN ROLLBACK; OERRMSG:='CMDTYPE2PROC_UNKNOWN_ERROR'; ORESULT:=0; RETURN;END PROCDLLBASE;
子存储过程
根据业务需求编写对应的存储过程,并将iCmdType与存储过程名称关联后储存至TBLPROCGROUP表格中。
子存储过程中涉及到输入参数的解析,输入参数的非空性校验及重复性校验,这些都是保证系统稳健性的需要。
总结
通过上述方案,当客户再有其他需求时,只需根据业务逻辑创建存储过程并分配iCmdType与之关联即可实现接口的扩展。
ATE工具开发人员也只需要按照文档的格式传参并解析输出参数即可,免却编译程序,封装COM组件及更新的繁琐流程。