Perl 프로그램에서 하드 코딩 된 구성을 어떻게 무시할 수 있습니까?
-
21-08-2019 - |
문제
사용될 디렉토리 및 파일의 상단 근처에 변수를 설정하는 Perl 스크립트가 있습니다. 또한 몇 가지 변수를 명령 줄 인수로 설정해야합니다. 예시:
use Getopt::Long;
my ($mount_point, $sub_dir, $database_name, $database_schema);
# Populate variables from the command line:
GetOptions(
'mount_point=s' => \$mount_point,
'sub_dir=s' => \$sub_dir,
'database_name=s' => \$database_name,
'database_schema=s' => \$database_schema
);
# ... validation of required arguments here
################################################################################
# Directory variables
################################################################################
my $input_directory = "/${mount_point}/${sub_dir}/input";
my $output_directory = "/${mount_point}/${sub_dir}/output";
my $log_directory = "/${mount_point}/${sub_dir}/log";
my $database_directory = "/db/${database_name}";
my $database_scripts = "${database_directory}/scripts";
################################################################################
# File variables
################################################################################
my $input_file = "${input_dir}/input_file.dat";
my $output_file = "${output_dir}/output_file.dat";
# ... etc
이것은 내 개발자, 테스트 및 생산 환경에서 잘 작동합니다. 그러나 개발 및 테스트를 위해 특정 변수 (디버거로 들어 가지 않고)를 더 쉽게 무시할 수 있도록 노력했습니다. (예를 들어, input_file = "/tmp/my_input_file.dat"을 설정하려면). 내 생각은 getoptions 기능을 사용하여 다음과 같은 것을 처리하는 것이 었습니다.
GetOptions(
'input_directory=s' => \$input_directory,
'output_directory=s' => \$output_directory,
'database_directory=s' => \$database_directory,
'log_directory=s' => \$log_directory,
'database_scripts=s' => \$database_scripts,
'input_file=s' => \$input_file,
'output_file=s' => \$output_file
);
getOptions는 한 번만 (내가 아는 한)라고 불릴 수 있습니다. 내 첫 Snippit의 첫 4 가지 인수는 필요하며, 마지막 7 개는 바로 선택 사항입니다. 이상적인 상황은 첫 번째 코드 Snippit에서와 같이 기본값을 설정 한 다음 명령 줄에서 인수가 전달 된 경우 설정된 모든 것을 무시하는 것입니다. 해시에 모든 옵션을 해시에 저장 한 다음 해시에 항목이 존재하지 않는 한 기본값으로 각 변수를 설정할 때 해시를 사용하는 것에 대해 생각했지만 많은 추가 로직을 추가하는 것 같습니다. 스크립트의 두 곳에서 getOptions를 호출하는 방법이 있습니까?
그것이 의미가 있는지 확실하지 않습니다.
감사!
해결책
여기에 또 다른 접근법이 있습니다. 이름의 배열과 해시를 사용하여 옵션을 저장합니다. 모든 옵션을 진정으로 선택 사항으로 만들지 만 명령 줄에 "-debug"를 포함하지 않는 한 필요한 옵션을 확인합니다. "-debug"를 사용하든 상관없이 다른 사람을 무시할 수 있습니다.
물론 그것이 중요한지 더 명시적인 논리 검사를 할 수 있습니다. 어쨌든 "input_file"및 "output_file"변수를 무시하려는 경우 "mount_point"와 같은 기본 옵션을 생략하는 방법의 예로 "-debug"를 포함 시켰습니다.
여기서 주요 아이디어는 옵션 이름 세트를 배열로 유지함으로써 코드가 비교적 작은 그룹에 대한 논리 검사를 포함시킬 수 있다는 것입니다.
use Getopt::Long;
my @required_opts = qw(
mount_point
sub_dir
database_name
database_schema
);
my @internal_opts = qw(
input_directory
output_directory
log_directory
database_directory
database_scripts
input_file
output_file
);
my @opt_spec = ("debug", map { "$_:s" } @required_opts, @internal_opts);
# Populate variables from the command line:
GetOptions( \(my %opts), @opt_spec );
# check required options unless
my @errors = grep { ! exists $opts{$_} } @required_options;
if ( @errors && ! $opts{debug} ) {
die "$0: missing required option(s): @errors\n";
}
################################################################################
# Directory variables
###############################################################################
my $opts{input_directory} ||= "/$opts{mount_point}/$opts{sub_dir}/input";
my $opts{output_directory} ||= "/$opts{mount_point}/$opts{sub_dir}/output";
my $opts{log_directory} ||= "/$opts{mount_point}/$opts{sub_dir}/log";
my $opts{database_directory} ||= "/db/$opts{database_name}";
my $opts{database_scripts} ||= "$opts{database_directory}/scripts";
################################################################################
# File variables
################################################################################
my $opts{input_file} ||= "$opts{input_directory}/input_file.dat";
my $opts{output_file} ||= "$opts{output_directory}/output_file.dat";
# ... etc
다른 팁
하드 코딩 된 구성 대신 구성 파일을 사용하도록 프로그램을 변경 해야하는 것 같습니다. 나는 전체 장을 바쳤다 마스터 링 Perl 이에. 프로그램을 테스트하기 위해 소스 코드를 변경하고 싶지 않습니다.
CPAN에는 구성 파일을 쉽게 추가 할 수있는 기능을 만드는 많은 Perl 모듈이 있습니다. 입력 데이터에 가장 적합한 것을 선택하십시오.
더 나은 구성 모델을 제자리에 올리면 기본값을 쉽게 설정하고 여러 장소 (파일, 명령 줄 등)에서 값을 가져오고 다른 값으로 프로그램을 쉽게 테스트 할 수 있습니다.
내가 할 일이 설정되었다고 생각합니다 input_directory
et al은 "undef"로, 그리고 나서 그것들을 getopts에 넣은 다음 나중에 그것들이 여전히 undef인지 테스트 한 다음 그림대로 할당하는 경우를 테스트하십시오. 사용자가 기술적으로 정교하다면 "내가 상대적인 경로를 제공한다면 그것은 $mount_point/$sub_dir
", 나는 초기"/"를 찾기 위해 추가 파싱을 할 것입니다.
배열로 입력 데이터로 GetOptions를 호출 할 수 있습니다. 읽기 선적 서류 비치.