Frage

Ich habe diesen Perl-Skript mit vielen definierten Konstanten von Konfigurationsdateien. Zum Beispiel:

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

Ich möchte Duplizierung von „/ etc / app1“ reduzieren und „/ var / log“, aber Variablen funktioniert nicht. Auch vorher definierten Konstanten funktioniert nicht in der gleichen „verwenden konstanten Block“. Zum Beispiel:

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

funktioniert nicht.

Die Verwendung separat „verwenden Konstante“ Blöcke tut Abhilfe dieses Problem, aber das fügt eine Menge von nicht benötigten Code.

Was ist der richtige Weg, dies zu tun?

Danke.

War es hilfreich?

Lösung

Ich würde wahrscheinlich schreiben Sie es wie folgt aus:

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;

Allerdings, das ist immer noch eine Menge Code, aber es macht die Duplizierung entfernen und das ist ein Gewinn.

Warum sind Ihre Logfiles numerische? Wenn sie mit 0 beginnen, ist ein Array eine bessere Wahl als ein Hash. Wenn sie benannt sind, sind sie mehr beschreibend.

Andere Tipps

  

Die Verwendung separater „verwenden Konstante“ Blöcke   nicht umgehen dieses Problem, aber das   fügt eine Menge von nicht benötigten Code.

Ist es wirklich?

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

Das sehe ich nicht viele Probleme mit. Sie haben den Basispfad nur in einem Punkt festgelegt, wodurch das DRY-Prinzip zu respektieren. Wenn Sie base_path mit einer Umgebungsvariablen zuweisen:

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

... Sie haben dann einen günstigen Weg, um Ihre Konstante neu zu konfigurieren, ohne den Code bearbeiten zu müssen. Was gibt es da nicht um so?

„Base_path“

Wenn Sie wirklich die sich wiederholende reduzieren wollen Verkettung, Sie ein wenig Maschinen hinzufügen könnte die Konstanten selbst und Faktor, der weg zu installieren:

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

Aber an diesem Punkt denke ich, die Balance weg Für einen Start von Correct zu Nasty :) geschwungen hat, können Sie nicht mehr für CONF_FILE1 grep und sehen, wo sie definiert ist.

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

Das wird nicht funktionieren, leider. Der Grund dafür ist, dass Sie Funktionen verwenden ( ‚Konstanten‘), bevor sie definiert sind. Sie bewerten sie vor dem Aufruf von constant->import.

Verwenden von Variablen funktioniert nicht, weil die Verwendung Aussagen zum Zeitpunkt der Kompilierung ausgewertet werden. Zuweisen zu Variablen wird erst zur Laufzeit durchgeführt, so dass sie noch nicht definiert werden.

Die einzige Lösung, die ich geben kann, ist es in mehr use constant Aussagen zu spalten. In diesem Fall werden zwei Anweisungen tun (einen für LOG_DIR und CONF_DIR, ein anderes für den Rest).

Je nachdem, was Sie tun, können Sie nicht Konstanten wollen überhaupt. Meistens schreibe ich Sachen, die andere Leute ihre Sachen zu erledigen zu bedienen, so dass ich dieses Problem lösen in einer Weise, dass andere Programmierer Flexibilität. Ich mache diese Dinge in Methoden:

 sub base_log_dir { '...' }

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

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

Durch die es auf diese Weise tun, kann ich leicht erweitern oder Dinge außer Kraft setzen.

Auf diese den Wert der konstanten Faltung verliert aber, so dass Sie darüber nachdenken, wie wichtig das für Sie ist.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top