Domanda

Ho questo script Perl con molte costanti definite di file di configurazione. Ad esempio:

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",
};

Voglio ridurre la duplicazione di " / etc / app1 " e " / var / log " , ma l'utilizzo delle variabili non funziona. Anche l'uso di costanti precedentemente definite non funziona nello stesso "usa blocco costante". Ad esempio:

use constant {
LOG_DIR                             => "/var/log/",
FILE_FILENAME                       => LOG_DIR . "file1.log" 
};

non funziona.

Uso della "costante" distinta " blocchi risolve questo problema, ma ciò aggiunge molto codice non necessario.

Qual è il modo corretto per farlo?

Grazie.

È stato utile?

Soluzione

Probabilmente lo scriverei così:

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 { 

Probabilmente lo scriverei così:

<*>

Tuttavia, è ancora molto codice, ma rimuove la duplicazione e questa è una vittoria.

Perché i tuoi file di registro sono numerici? Se iniziano con 0, un array è una scelta migliore di un hash. Se sono nominati, sono più descrittivi.

=> "$ETC/config

Probabilmente lo scriverei così:

<*>

Tuttavia, è ancora molto codice, ma rimuove la duplicazione e questa è una vittoria.

Perché i tuoi file di registro sono numerici? Se iniziano con 0, un array è una scelta migliore di un hash. Se sono nominati, sono più descrittivi.

.xml" } 1 .. 5;

Tuttavia, è ancora molto codice, ma rimuove la duplicazione e questa è una vittoria.

Perché i tuoi file di registro sono numerici? Se iniziano con 0, un array è una scelta migliore di un hash. Se sono nominati, sono più descrittivi.

Altri suggerimenti

  

Uso della "costante" distinta " blocchi   risolve questo problema, ma quello   aggiunge molto codice non necessario.

Davvero?

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",
};

Non vedo molti problemi con questo. È stato specificato il percorso di base in un solo punto, rispettando così il principio DRY. Se si assegna BASE_PATH con una variabile di ambiente:

use constant BASE_PATH => $ENV{MY_BASE_PATH} || "/etc/app1";

... hai quindi un modo economico di riconfigurare la tua costante senza dover modificare il tuo codice. Cosa c'è che non va di questo?

Se vuoi davvero ridurre il ripetitivo " BASE_PATH. & Quot; concatenazione, potresti aggiungere un po 'di macchinari per installare le costanti tu stesso e tenerne conto:

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";

Ma a questo punto penso che il bilancio si sia spostato da Corretto a Cattivo :) Per cominciare, non puoi più grep per CONF_FILE1 e vedere dove è definito.

use constant +{
    map { sprintf <*>, '/var/log' } (
        LOG_DIR            => "%s/",
        LOG_FILENAME       => "%s/file1.log",
    ),
    map { sprintf <*>, '/etc/app1' } (
        LOG4PERL_CONF_FILE => "%s/log4perl.conf",
        CONF_FILE1         => "%s/config1.xml",
        CONF_FILE2         => "%s/config2.xml",
        CONF_FILE3         => "%s/config3.xml",
        CONF_FILE4         => "%s/config4.xml",
        CONF_FILE5         => "%s/config5.xml",
    ),
};

Purtroppo non funzionerà. La ragione di ciò è che stai usando le funzioni ('costanti') prima che vengano definite. Li valuti prima della chiamata a constant- > import .

L'uso delle variabili non funziona perché le istruzioni use vengono valutate al momento della compilazione. L'assegnazione alle variabili viene eseguita solo in fase di esecuzione, quindi non saranno ancora definite.

L'unica soluzione che posso dare è dividerlo in più usare costanti . In questo caso, faranno due affermazioni (una per LOG_DIR e CONF_DIR , un'altra per il resto).

A seconda di ciò che stai facendo, potresti non volere affatto costanti. Principalmente, scrivo cose che altre persone usano per fare le loro cose, quindi risolvo questo problema in modo da dare flessibilità ad altri programmatori. Trasformo queste cose in metodi:

 sub base_log_dir { '...' }

 sub get_log_file
      {
      my( $self, $number ) = @_;

      my $log_file = catfile( 
        $self->base_log_dir, 
        sprintf "foo%03d", $number
        );
      }

In questo modo, posso facilmente estendere o ignorare le cose.

In questo modo, tuttavia, si perde il valore della piegatura costante, quindi è necessario pensare a quanto sia importante per te.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top