分配表:默认行为

写完前面那篇,感觉十分有价值,突然也想起公司里咋们平时开玩笑的有关架构的评论

分配表是数据,而不是代码,所以它可以在运行时改变,你可以在你想的任何时候插入新的指示到表里;也就是消除了if-else树,更大的价值在于不用在配置里添加了新的内容的时候,又要找到读取,行为函数里,添加读取内容的else if以及一堆或许十分复杂的处理函数,让整个处理过程显得十分的臃肿,可读性比较差;而通过分配表,只需要修改散列表具体的行为函数即可一劳永逸,不需要再担心是否修改完全

分配表和硬编码相比,另一个优势是可以使用同一个read_config函数处理两个不相关并且有完全不同指示的文件,只要每次传递一个不同的分配表给read_config(),可以通过传递带有相同基本语法的文件,就可以达到目的

前面的函数如果遇到无法识别的指示就会崩溃,如果分配表自身携带了对一个无法识别的指示要做什么信息,那会更好,结合回调可以这么写:

sub read_config {
    my ($config_file, $actions, $userparam) = @_;
    open my($pf), $config_file or return;
    while(<$pf>){
        chomp;
        my ($directive, $rest) = split /\s+/, $_, 2;
        my $action = $actions->{$directive} || $actions->{_DEFAULT_};
        if ($action) {
            $action->($directive, $rest, $actions, $userparam);
        }  else{
            die “Unrecognized directive $directive on line $. of $config_file; aborting”;
        }
    }
}

这里的函数在行为表里寻找指定的指示,如果没有,就寻找_DEFAULT_行为,仅当分配表里没有指定的默认行为时才崩溃,比如_DEFAULT_行为:

sub no_such_directive {
    my ($directive) = @_;
    warn “Unrecognized directive $directive at line $.; ignoring.\n”;
}

由于把指示的名称作为第一个参数传递给了行为函数,因此默认的行为知道调用无法识别的指示代表什么;由于no_such_directive函数也得到了传递的整个分配表,因此可以抽取到真实的指示名称并通过模式匹配指出可能的含义

所以default里可以很灵活地添加默认的条目,对于无法识别的时候能够多一些判断,多一些额外的知识信息

发表回复