Как я могу переопределить жестко запрограммированную конфигурацию в моей программе Perl? - PullRequest
0 голосов
/ 10 декабря 2008

У меня есть скрипт 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 можно вызывать только один раз (насколько я знаю). Первые 4 аргумента в моем первом фрагменте являются обязательными, последние 7, приведенные выше, являются необязательными. Я думаю, что идеальной ситуацией было бы установить значения по умолчанию, как в моем первом фрагменте кода, а затем каким-то образом переопределить любой из них, которые были установлены, если аргументы были переданы в командной строке. Я думал о том, чтобы сохранить все мои параметры в хэше, а затем использовать этот хэш при настройке каждой переменной со значением по умолчанию, если в хэше не существует записи, но это, кажется, добавляет много дополнительной логики. Есть ли способ вызвать GetOptions в двух разных местах скрипта?

Не уверен, имеет ли это смысл.

Спасибо!

Ответы [ 4 ]

7 голосов
/ 10 декабря 2008

Похоже, вам нужно изменить программу, чтобы использовать файлы конфигурации, а не жестко запрограммированную конфигурацию. Я посвятил этому целую главу Мастеринг Perl . Вы не хотите изменять исходный код для тестирования программы.

В CPAN существует множество модулей Perl, которые упрощают добавление файлов конфигурации. Выберите тот, который лучше всего подходит для ваших входных данных.

Как только вы получите более совершенную модель конфигурации, вы можете легко установить значения по умолчанию, взять значения из нескольких мест (файлы, командная строка и т. Д.) И легко протестировать программу с различными значениями.

6 голосов
/ 10 декабря 2008

Вот другой подход. Он использует массивы имен и хэш для хранения параметров. Это делает все параметры действительно необязательными, но проверяет обязательные, если вы не включите «--debug» в командной строке. Независимо от того, используете ли вы «--debug», вы можете переопределить любое из остальных.

Вы могли бы сделать более явные логические проверки, если это, конечно, важно для вас. Я включил «--debug» в качестве примера того, как опустить основные параметры, такие как «mount_point», если вы все равно собираетесь переопределить переменные «input_file» и «output_file».

Основная идея здесь заключается в том, что, сохраняя наборы имен параметров в массивах, вы можете включать логические проверки для групп с относительно небольшим кодом.

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
3 голосов
/ 10 декабря 2008

Я думаю, что я бы сделал, установив input_directory и др. На "undef", затем поместите их в getopts, а затем проверьте, не являются ли они еще undef, и, если это так, назначьте их, как показано. Если ваши пользователи достаточно технически продвинуты, чтобы понять, «если я приведу относительный путь, относительно которого он равен $mount_point/$sub_dir», то я бы выполнил дополнительный анализ в поисках начального »/".

.
0 голосов
/ 10 декабря 2008

GetOptions можно вызывать с массивом в качестве входных данных. Прочитайте документацию .

...