写完前面那篇,感觉十分有价值,突然也想起公司里咋们平时开玩笑的有关架构的评论
分配表是数据,而不是代码,所以它可以在运行时改变,你可以在你想的任何时候插入新的指示到表里;也就是消除了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里可以很灵活地添加默认的条目,对于无法识别的时候能够多一些判断,多一些额外的知识信息