• 表格驱动编程在代码中的应用


    1. 毕业设计中的使用

    第一次使用表格驱动编程,是在大学毕业设计的时候。做一个LL(1)的词法分析程序,需要读取终结符、非终结符、以及推导公式。程序会根据以上信息生成FIRST集合和LAST集合,然后根据递归下降分析的方法,就可以判断当前的表达式,是否符合对应的文法规则了。因为在代码中对于推导用到的表格没有写为Hard Code(写死,硬编码),所以可以适应很多的符合规则的文法。

    2. 开源代码中的使用

    第二次遇到表格驱动编程的方法,是在LXGJ,做jpg图像的压缩,用的是jpeg2000。当时还写了一篇文章,总结了一下,具体见 http://www.cnblogs.com/Dennis-mi/p/3871860.html 。这里的代码采用的是动态生成表格的方式,在函数中通过宏来控制表格的大小,来实现动态的支持不同图片格式的解析。

    3. 工作中使用

    在LXGJ的时候,领导布置了一个任务,需要用户选择从不同的来源生成PDF,大致有扫描、文件、图片……,需要做成一个类似于Eclipse(Visual Studio)生成工程的向导类似的。然后明白了需求以后,我就开始写代码了。然后项目经理过来问我做的怎么样了,我把写了好多 if else的代码拿给他看,他说“你怎么能这么写呢,万一需求有变化,怎么改。

    代码类似于

    if( SCAN == type )
    {
        dlg = new ScanDialog();
        dlg.show();
        if(DPI300 == dlg.getDpi())
        {
            .....
        }
    }
    else if(FILE == type)
    { 
        ...
    }
    else if(IMAGE == type)
    {
        ....
    }
    

    以上的代码在遇到规则有变化,或者每一步方式的选项要增加或者减少的时候,修改比较麻烦。
    项目经理的建议

    Dialog choiceDialog[4][5]=
    {
       new ScanDialog(),new DpiDialog(),new xxDialog(),NULL,
       new FileDialog(),new xxDialog(),NULL,NULL,
       new ImageDialog(),new DpiDialog(),new ImageTypeDialog(),new xxDialog(),NULL,
       NULL,NULL,NULL,NULL,NULL,
    }
    

    采用下面的这种写法具有更好的可扩展性和灵活性。如果需要增加一种方式,则可以增加一行,如果需要增加方式中的一个选项,则可以在某行的某列后面增加一个dialog,用NULL表示结束,可以每种方式经过的选项不同。

    4.我的新发现

    在LXSJ的时候,我们需要对APP登录做验证,验证的过程比较多而且规则有可能会变化。这个时候采用表格驱动编程是一种很好的方式。举例说明如下:
    比如我们需要验证

    1、用户是否余额--->有余额允许登录,没有不允许;
    2、用户是否是VIP会员--->是会员允许登录,不管其他条件;
    3、用户如果是合作方的用户--->则合作方决定是否允许登录;
    4、用户如果已经是老用户--->是允许登录,不是不允许登录;

    此时可以采用老办法,用if else来写。但是新的方法是采用表格驱动,具体如下。
    表格的每一项对应一个判断函数,返回 bool 值。

    loginLogicTable[][] =
    {
       /*当前需要进行的判断,成功时的状态,失败时的状态*/
       LOGIN_START,IS_VIP,IS_VIP,
       IS_VIP,LOGIN_SUCCEED,HAS_BALANCE,
       HAS_BALANCE,LOGIN_SUCCEED,IS_REGULAR_CUSTOMER,
       IS_REGULAR_CUSTOMER,LOGIN_SUCEED,IS_PARTER_CUSTOMER,
       IS_PARTER_CUSTOMER,SEND_REQUEST_TO_PARTER,LOGIN_FAILED,
       RECIVE_PARTER_RESPONSE,LOGIN_SUCCEED,LOGIN_FAILED,
    }
    

    以上是此时规则的描述,其中 LOGIN_SUCCEEDLOGIN_FAILED 是最终的状态。
    第一项对应着一个函数,使用这个表格的伪代码如下

    bool isLoginSucceed(userInfo)
    {
        curState = LOGIN_START;
        while( curState != LOGIN_SUCCEED && curState != LOGIN_FAILED)
        { 
            changeArray = findArray(curState); //返回loginLoginTable中的一行
            if(callFunc(changeArray[0])
            { 
                curState=changeArray[1];
            }
            else
            {
               curState = changeArray[2];
            } 
        }
        return curState == LOGIN_SUCCEED;
    }
    

    如果不需要判断是否是合作伙伴的用户了。
    则将

    IS_REGULAR_CUSTOMER,LOGIN_SUCEED,[IS_PARTER_CUSTOMER], 
    //改为
    IS_REGULAR_CUSTOMER,LOGIN_SUCEED,[LOGIN_FAILED],
    

    就可以了,改动非常的方便。
    如果要增加一个判断,比如要增加xyz指令判断。
    则修改如下:

    IS_REGULAR_CUSTOMER,[LOGIN_SUCEED],IS_PARTER_CUSTOMER,
    IS_PARTER_CUSTOMER,SEND_REQUEST_TO_PARTER,LOGIN_FAILED,
    RECIVE_PARTER_RESPONSE,LOGIN_SUCCEED,LOGIN_FAILED,
    /*改为*/
    IS_REGULAR_CUSTOMER,[JUDGE_XYZ_CMD],IS_PARTER_CUSTOMER,
    IS_PARTER_CUSTOMER,SEND_REQUEST_TO_PARTER,LOGIN_FAILED,
    RECIVE_PARTER_RESPONSE,[JUDGE_XYZ_CMD],LOGIN_FAILED,
    [JUDGE_XYZ_CMD],LOGIN_SUCCEED,LOGIN_FAILED,
    

    可以看出,此时的修改很小,而且逻辑很清楚。

  • 相关阅读:
    getopt函数
    Pac的OI回忆录
    Python embed包使用
    Git add . Git add * 的区别
    Linux Python升级版本至2.7.5
    Linux6.3升级zlib
    一: Centos 虚拟机安装
    4.4 SpringCloud__服务注册与发现Eureka__自我保护机制
    4.3 SpringCloud__服务注册与发现Eureka__高可用集群配置
    4.2 SpringCloud__服务注册与发现Eureka__搭建注册中心
  • 原文地址:https://www.cnblogs.com/Dennis-mi/p/8612698.html
Copyright © 2020-2023  润新知