简介
在计算机科学中, 预处理是是程序源代码被翻译为目标代码的过程,例如在对程序进行编译之前,一般都会对源代码进行预处理及优化。决策表预处理器是程序中利用决策表这一方法来处理和简化输入数据,产生能用来输入到其他程序的数据的程序。
决策表决策表是一种精确而紧凑的方法,用于对复杂规则集及其相应的动作进行建模。
决策表,如流程图,if-then-else和switch-case语句,将条件与要执行的操作相关联,但在许多情况下以更优雅的方式执行此操作。
在20世纪60年代和70年代,一系列基于“决策表”的语言,如Filetab,受到业务编程的欢迎。
每个决策对应于一个变量,关系或谓词,其可能的值在条件替代中列出。每个动作是执行的过程或操作,并且条目指定对于条目对应的条件替换集合(或以什么顺序)执行动作。许多决策表包括在他们的条件替代品不关心符号,连字符。使用不关心可以简化决策表,特别是当给定条件对要执行的操作影响不大时。在某些情况下,当没有任何条件影响执行哪些动作时,最初发现的整个条件被认为是无关紧要的。
除了基本的四象限结构之外,决策表在条件替代和行动条目的表示方式上有很大差异。一些决策表使用简单的真/假值来表示条件的替代(类似于if-then-else),其他表可能使用编号的替代(类似于switch-case),甚至有些表甚至使用模糊逻辑或概率表示来进行条件替代。以类似的方式,动作条目可以简单地表示要执行的动作(检查要执行的动作),还是在更高级的决策表中表示要执行的动作的排序(对要执行的操作进行编号)。
软件工程的好处
决策表,特别是与使用域特定语言相结合时,允许开发人员和策略专家从相同的信息,决策表本身工作。
将传统编程语言的语句嵌套到决策表中的嵌套工具也可以用作调试工具。
决策表已被证明比代码更容易理解和审查,并且已被广泛和成功地用于生成复杂系统的规范。1
潜在的困难以Cobol为例
根据10年Cobol决策表处理器的经验,我遇到了一些问题:
决策表可能与源程序的其余部分具有不同的格式,使得难以将程序准备为单个文本。
程序员可能必须记住与Cobol不兼容的关于句子的最大长度,延续线等的特殊规则。
在调试期间,程序员必须参考Cobol程序列表,他的输入数据和他的测试结果。他还可能需要额外的预处理器输入和输出列表,以便Cobol程序中的错误可以追溯到错误的表。这太多了,不能放在桌子上当预处理器检测到错误时,编译步骤经常被跳过。所以Cobol语法检查必须等待所有的表错误被修复,需要额外的转机。
Cobol用户对机器独立感兴趣,但是他的预处理器可能仅适用于一台特定的机器。
它可能与其他预处理器(例如DBMS)或使用程序库不兼容,或支持非标准Cobol功能
问题解决方案可能会分散,因为它们只能被表示为由GO TO所链接的一系列表。
程序员可能会看到处理器产生的代码比手写的代码要差一些可能更严重的一个难点。他可能没有办法改善它。他因此对自己的工作不满意。手工翻译决策表是一小步,最终完全放弃决策。2
代码实现例子以下示例来自ccide程序本身:
这是原来的if-then-else代码(你能找到逻辑错误吗?)
extern int donotgenerate, notimestamp, uselocaltime,noinline,yydebug;
char *xstring;
int main(int argc, char **argv)
{
int narg = 1;
while (argc > narg) {
if(strcmp("-b", argv[narg]) == 0) {
notimestamp = 1;
}else {
if (strcmp("-l", argv[narg]) ==0) {
uselocaltime= 1;
} else {
if(strcmp("-e", argv[narg]) == 0) {
strcat(xstring, "- ");
}else {
if (strcmp("-n", argv[narg]) ==0) {
noinline= 1;
} else {
if(strcmp("-s", argv[narg]) == 0) {
GenSkeleton();
exit(0);
}else {
if (strcmp("-t", argv[narg]) ==0) {
yydebug= 1;
} else {
if(strcmp("-u", argv[narg]) == 0) {
noinline = 1;
donotgenerate = 1;
}else {
if (strcmp("-V", argv[narg]) = 0){
ShowCopyright();
exit(0);
} else {
if(strcmp("-x", argv[narg]) == 0) {
strcat(xstring, "- ");
}else {
Usage();
exit(0);
}
}
}
}
}
}
}
}
}
narg++;
}
}
使用决策表的代码
extern int donotgenerate, notimestamp,uselocaltime, noinline, yydebug;
char *xstring;
//CCIDE_INLINE_CODE:
int main(int argc, char **argv)
{
#define Argis(P) strcmp( #P, argv[narg]) ==0
while( argc>narg ) {
//DECISION_TABLE:
// Y- - - - - - - - - | Argis(-b)
// -Y - - - - - - - - | Argis(-l)
// -- - - - - - - Y - | Argis(-e)
// -- Y - - - - - - - | Argis(-n)
// -- - Y - - - - - - | Argis(-s)
// -- - - Y - - - - - | Argis(-t)
// -- - - - Y - - - - | Argis(-u)
// -- - - - - Y - - - | Argis(-V)
// -- - - - - - - - Y | Argis(-x)
// _________________________________
// X- - - - - - - - - | notimestamp=1;
// -X - - - - - - - - | uselocaltime=1;
// -- X - - X - - - - | noinline=1;
// -- - X - - - - - - | GenSkeleton();
// -- - - X - - - - - | yydebug=1;
// -- - - - X - - - - | donotgenerate=1;
// -- - - - - X - - - | ShowCopyright();
// -- - - - - - X - - | Usage();
// -- - - - - - - X - | checkequal=0;
// -- - - - - - - - X | strcat(xstring,
// -- - X - - X X - - | exit(0);
//END_TABLE:
narg++;
}3