我有这个Perl脚本,有很多已定义的配置文件常量.例如:
use constant { LOG_DIR => "/var/log/", LOG_FILENAME => "/var/log/file1.log", LOG4PERL_CONF_FILE => "/etc/app1/log4perl.conf", CONF_FILE1 => "/etc/app1/config1.xml", CONF_FILE2 => "/etc/app1/config2.xml", CONF_FILE3 => "/etc/app1/config3.xml", CONF_FILE4 => "/etc/app1/config4.xml", CONF_FILE5 => "/etc/app1/config5.xml", };
我想减少"/ etc/app1"和"/ var/log"的重复,但使用变量不起作用.使用先前定义的常量也不能在相同的"使用常量块"中工作.例如:
use constant { LOG_DIR => "/var/log/", FILE_FILENAME => LOG_DIR . "file1.log" };
不起作用.
使用单独的"使用常量"块可以解决此问题,但这会增加许多不需要的代码.
这样做的正确方法是什么?
谢谢.
使用单独的"使用常量"块可以解决此问题,但这会增加许多不需要的代码.
真的吗?
use constant BASE_PATH => "/etc/app1"; use constant { LOG4PERL_CONF_FILE => BASE_PATH . "/log4perl.conf", CONF_FILE1 => BASE_PATH . "/config1.xml", CONF_FILE2 => BASE_PATH . "/config2.xml", CONF_FILE3 => BASE_PATH . "/config3.xml", CONF_FILE4 => BASE_PATH . "/config4.xml", CONF_FILE5 => BASE_PATH . "/config5.xml", };
我没有看到很多这方面的问题.您仅在一个点中指定了基本路径,从而遵守DRY原则.如果为BASE_PATH分配环境变量:
use constant BASE_PATH => $ENV{MY_BASE_PATH} || "/etc/app1";
...然后,您可以通过廉价的方式重新配置常量,而无需编辑代码.有什么不喜欢这个?
如果你真的想要减少重复的"BASE_PATH."连接,你可以添加一些机器来自己安装常量并将其分解:
use strict; use warnings; use constant BASE_PATH => $ENV{MY_PATH} || '/etc/apps'; BEGIN { my %conf = ( FILE1 => "/config1.xml", FILE2 => "/config2.xml", ); for my $constant (keys %conf) { no strict 'refs'; *{__PACKAGE__ . "::CONF_$constant"} = sub () {BASE_PATH . "$conf{$constant}"}; } } print "Config is ", CONF_FILE1, ".\n";
但是在这一点上,我认为平衡已经从正确转向讨厌了:)首先,你不能再为CONF_FILE1寻找并查看它的定义.
我可能会这样写:
use Readonly; Readonly my $LOG_DIR => "/var/log"; Readonly my $LOG_FILENAME => "$LOG_DIR/file1.log"; Readonly my $ETC => '/etc/app1'; Readonly my $LOG4PERL_CONF_FILE => "$ETC/log4perl.con"; # hash because we don't have an index '0' Readonly my %CONF_FILES => map { $_ => "$ETC/config$_.xml" } 1 .. 5;
然而,这仍然是很多代码,但它确实消除了重复,这是一个胜利.
为什么您的日志文件是数字的?如果它们以0开头,则数组是比散列更好的选择.如果它们被命名,它们就更具描述性.