Question

J'ai ce script Perl avec beaucoup de constantes définies de fichiers de configuration. Par exemple:

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

Je souhaite réduire la duplication de " / etc / app1 " et " / var / log " , mais l’utilisation de variables ne fonctionne pas. L'utilisation de constantes précédemment définies ne fonctionne pas non plus dans le même "utiliser un bloc constant". Par exemple:

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

ne fonctionne pas.

Utilisation séparée " utiliser constante " Blocs fait pour contourner ce problème, mais cela ajoute beaucoup de code inutile.

Quelle est la bonne façon de faire cela?

Merci.

Était-ce utile?

La solution

Je l'écrirais probablement comme ceci:

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 { 

Je l'écrirais probablement comme ceci:

<*>

Cependant, cela reste beaucoup de code, mais cela supprime la duplication et c'est une victoire.

Pourquoi vos fichiers de log sont-ils numériques? S'ils commencent par 0, un tableau est un meilleur choix qu'un hachage. S'ils sont nommés, ils sont plus descriptifs.

=> "$ETC/config

Je l'écrirais probablement comme ceci:

<*>

Cependant, cela reste beaucoup de code, mais cela supprime la duplication et c'est une victoire.

Pourquoi vos fichiers de log sont-ils numériques? S'ils commencent par 0, un tableau est un meilleur choix qu'un hachage. S'ils sont nommés, ils sont plus descriptifs.

.xml" } 1 .. 5;

Cependant, cela reste beaucoup de code, mais cela supprime la duplication et c'est une victoire.

Pourquoi vos fichiers de log sont-ils numériques? S'ils commencent par 0, un tableau est un meilleur choix qu'un hachage. S'ils sont nommés, ils sont plus descriptifs.

Autres conseils

  

Utilisation séparée " utiliser constante " des blocs   contourner ce problème, mais que   ajoute beaucoup de code inutile.

Est-ce vraiment?

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

Je ne vois pas beaucoup de problèmes avec ça. Vous avez spécifié le chemin de base en un seul point, respectant ainsi le principe DRY. Si vous affectez BASE_PATH avec une variable d’environnement:

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

... vous disposez alors d'un moyen peu coûteux de reconfigurer votre constante sans avoir à modifier votre code. Qu'y a-t-il à ne pas aimer ça?

Si vous voulez vraiment réduire les répétitions "BASE_PATH". " Lors de la concaténation, vous pouvez ajouter un peu de machines pour installer les constantes vous-même et en tenir compte:

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

Mais à ce stade, je pense que la balance a basculé de Correct à Nasty :) Pour commencer, vous ne pouvez plus grep pour CONF_FILE1 et voir où il est défini.

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

Cela ne va pas marcher, malheureusement. La raison en est que vous utilisez des fonctions ('constantes') avant qu'elles ne soient définies. Vous les évaluez avant l'appel à constant- > importer .

L'utilisation de variables ne fonctionne pas car les instructions use sont évaluées au moment de la compilation. L'affectation de variables est effectuée uniquement à l'exécution, elles ne seront donc pas encore définies.

La seule solution que je puisse donner est de le scinder en plusieurs instructions utiliser constante . Dans ce cas, deux instructions suffiront (une pour LOG_DIR et CONF_DIR , une autre pour les autres).

En fonction de ce que vous faites, vous pourriez ne pas vouloir de constantes du tout. La plupart du temps, j'écris des trucs que d'autres personnes utilisent pour le faire, alors je résous ce problème d'une manière qui donne aux programmeurs une flexibilité. Je transforme ces choses en méthodes:

 sub base_log_dir { '...' }

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

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

En procédant de cette façon, je peux facilement étendre ou remplacer des éléments.

Ce faisant, cependant, perd la valeur du pliage constant. Vous devez donc réfléchir à l’importance que cela revêt pour vous.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top