2008-10-23 18 views
6

मेरे पास यह पर्ल स्क्रिप्ट है जिसमें कॉन्फ़िगरेशन फ़ाइलों के कई परिभाषित स्थिरांक हैं। उदाहरण के लिए:मैं स्थिरांक में डुप्लिकेशंस कैसे कम कर सकता हूं?

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

मैं "/ etc/APP1" और "/ var/log" के दोहराव को कम करना चाहते हैं, लेकिन वैरिएबल का उपयोग कर काम नहीं करता। पहले परिभाषित स्थिरांक का भी उपयोग करना "निरंतर ब्लॉक का उपयोग" में काम नहीं करता है। उदाहरण के लिए:

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

काम नहीं करता है।

अलग-अलग "उपयोग निरंतर" ब्लॉक का उपयोग करके इस समस्या का समाधान होता है, लेकिन इससे बहुत सारे अनियंत्रित कोड जोड़े जाते हैं।

ऐसा करने का सही तरीका क्या है?

धन्यवाद।

उत्तर

7

शायद मैं इसे इस तरह से लिखते हैं:

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; 

हालांकि, कि अभी भी कोड का एक बहुत कुछ है, लेकिन यह दोहराव को दूर करता है और कि एक जीत है।

आपकी लॉगफाइल संख्यात्मक क्यों हैं? यदि वे 0 से शुरू होते हैं, तो एक सरणी हैश की तुलना में बेहतर विकल्प है। अगर उनका नाम है, तो वे अधिक वर्णनात्मक हैं।

+0

उत्तर के लिए धन्यवाद, लॉग नाम वास्तव में संख्यात्मक नहीं है - मैंने अभी उन्हें उदाहरण के लिए बदल दिया है। –

3

यह दुर्भाग्य से काम नहीं करेगा। इसका कारण यह है कि आप परिभाषित होने से पहले कार्यों ('स्थिरांक') का उपयोग कर रहे हैं। constant->import पर कॉल करने से पहले आप उनका मूल्यांकन करते हैं।

चर का उपयोग करना काम नहीं करता है क्योंकि उपयोग विवरणों का संकलन समय पर मूल्यांकन किया जाता है। चरों को असाइन करना केवल रनटाइम पर किया जाता है, इसलिए उन्हें अभी तक परिभाषित नहीं किया जाएगा।

एकमात्र समाधान जो मैं दे सकता हूं उसे इसे use constant कथनों में विभाजित करना है। इस मामले में, दो कथन करेंगे (एक LOG_DIR और CONF_DIR के लिए, बाकी के लिए दूसरा)।

8

अलग का उपयोग करना "का उपयोग निरंतर" ब्लॉक वैकल्पिक हल इस समस्या है, लेकिन है कि अनावश्यक कोड का एक बहुत कुछ कहते हैं।

क्या यह वास्तव में है?

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

मुझे इसके साथ बहुत सारी समस्याएं नहीं दिखाई देती हैं। आपने केवल एक बिंदु में आधार पथ निर्दिष्ट किया है, जिससे डीआरवाई सिद्धांत का सम्मान किया जा रहा है। आप एक वातावरण चर के साथ BASE_PATH असाइन करते हैं:

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

... आप तो अपने कोड को संपादित किए बिना अपने लगातार पुन: कॉन्फ़िगर करने का एक सस्ता तरीका है। इसके बारे में क्या पसंद नहीं है? "। BASE_PATH"

तुम सच में दोहराव में कटौती चाहते हैं संयोजन, आप अपने आप को और स्थिरांक पहलू यह है कि दूर स्थापित करने के लिए मशीनरी का एक सा जोड़ सकते हैं:

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

लेकिन इस बिंदु पर मुझे लगता है कि संतुलन सही से गंदा हो गया है :) शुरुआत के लिए, अब आप CONF_FILE1 के लिए grep नहीं देख सकते हैं और यह कहां परिभाषित किया गया है।

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

आप जो कर रहे हैं उसके आधार पर, आप स्थिरांक नहीं चाहते हैं। अधिकतर, मैं सामान लिखता हूं जो अन्य लोग अपनी सामग्री को पूरा करने के लिए उपयोग करते हैं, इसलिए मैं इस समस्या को इस तरह हल करता हूं जो अन्य प्रोग्रामर लचीलापन देता है। मैं इन चीजों को तरीकों से बना देता हूं:

sub base_log_dir { '...' } 

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

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

इस तरह से, मैं आसानी से चीजों को बढ़ा या ओवरराइड कर सकता हूं।

ऐसा करने से निरंतर फोल्डिंग का मूल्य खो जाता है, इसलिए आपको यह सोचना होगा कि यह आपके लिए कितना महत्वपूर्ण है।

संबंधित मुद्दे