Why is it a bad idea to write configuration data in code?

前端 未结 10 2145
陌清茗
陌清茗 2020-12-05 23:46

Real-life case (from caff) to exemplify the short question subject:

$CONFIG{\'owner\'} = q{Peter Palfrader};
$CONFIG{\'email\'} = q{peter@palfrader.org};
$CO         


        
相关标签:
10条回答
  • 2020-12-06 00:24

    Excuse the long code listing. Below is a handy Conf.pm module that I have used in many systems which allows you to specify different variables for different production, staging and dev environments. Then I build my programs to either accept the environment parameters on the command line, or I store this file outside of the source control tree so that never gets over written.

    The AUTOLOAD provides automatic methods for variable retrieval.

    # Instructions:
    # use Conf;
    # my $c = Conf->new("production");
    # print $c->root_dir;
    # print $c->log_dir;
    
    package Conf;
    use strict;
    our $AUTOLOAD;
    
    my $default_environment = "production";
    
    my @valid_environments  = qw(
        development
        production
    );
    
    #######################################################################################
    # You might need to change this.
    sub set_vars {
        my ($self) = @_;
    
        $self->{"access_token"} = 'asdafsifhefh';
    
        if ( $self->env eq "development" ) {
           $self->{"root_dir"}       = "/Users/patrickcollins/Documents/workspace/SysG_perl";
           $self->{"server_base"}    = "http://localhost:3000";
        }
    
        elsif ($self->env eq "production" ) {
           $self->{"root_dir"}       = "/mnt/SysG-production/current/lib";
           $self->{"server_base"}    = "http://api.SysG.com";
           $self->{"log_dir"}        = "/mnt/SysG-production/current/log"
        }  else {
                die "No environment defined\n";
        }
    
        #######################################################################################
        # You shouldn't need to configure this.
    
        # More dirs. Move these into the dev/prod sections if they're different per env.
        my $r = $self->{'root_dir'};
        my $b = $self->{'server_base'};
    
        $self->{"working_dir"} ||= "$r/working";
        $self->{"bin_dir"}     ||= "$r/bin";
        $self->{"log_dir"}     ||= "$r/log";
    
        # Other URLs. Move these into the dev/prod sections if they're different per env.
    
        $self->{"new_contract_url"}   = "$b/SysG-training-center/v1/contract/new";
        $self->{"new_documents_url"}  = "$b/SysG-training-center/v1/documents/new";
    
    }
    
    #######################################################################################
    # Code, don't change below here.
    
    sub new {
        my ($class,$env) = @_;
        my $self = {};
        bless ($self,$class);
    
        if ($env) {
                $self->env($env);
        } else {
                $self->env($default_environment);
        }
    
        $self->set_vars;
        return $self;
    }
    
    sub AUTOLOAD {
        my ($self,$val) = @_;
        my $type = ref ($self) || die "$self is not an object";
        my $field = $AUTOLOAD;
    
        $field =~ s/.*://;
    
        #print "field: $field\n";
    
        unless (exists $self->{$field} || $field =~ /DESTROY/ )
        {
           die "ERROR: {$field} does not exist in object/class $type\n";
        }
    
        $self->{$field} = $val if ($val);
        return $self->{$field};
    
    }
    
    sub env {
        my ($self,$in) = @_;
        if ($in) {
                die ("Invalid environment $in") unless (grep($in,@valid_environments));
                $self->{"_env"} = $in;
        }
        return $self->{"_env"};
    }
    
    1;
    
    0 讨论(0)
  • I agree with Tim Anderson. Somebody here confuses configuration in code as configuration not being configurable. This is corrected for compiled code.

    Both a perl or ruby file is read and interpreted, as is a yml file or xml file with configuration data. I choose yml because it is easier on the eye than in code, as grouping by test environment, development, staging and production, which in code would involve more .. code.

    As a side note, XML contradicts the "easy on the eye" completely. I find it interesting that XML config is extensively used with compiled languages.

    0 讨论(0)
  • 2020-12-06 00:29

    Reason 1. Aesthetics. While no one gets harmed by bad smell, people tend to put effort into getting rid of it.

    Reason 2. Operational cost. For a team of 5 this is probably ok, but once you have developer/sysadmin separation, you must hire sysadmins who understand Perl (which is $$$), or give developers access to production system (big $$$).

    And to make matters worse you won't have time (also $$$) to introduce a configuration engine when you suddenly need it.

    0 讨论(0)
  • 2020-12-06 00:30

    One major issue with this approach is that your config is not very portable. If a functionally identical tool were built in Java, loading configuration would have to be redone. If both the Perl and the Java variation used a simple key=value layout such as:

    owner = "Peter Palfrader"
    email = "peter@peter@palfrader.org"
    ...
    

    they could share the config.

    Also, calling eval on the config file seems to open this system up to attack. What could a malicious person add to this config file if they wanted to wreak some havoc? Do you realize that ANY arbitrary code in your config file will be executed?

    Another issue is that it's highly counter-intuitive (at least to me). I would expect a config file to be read by some config loader, not executed as a runnable piece of code. This isn't so serious but could confuse new developers who aren't used to it.

    Finally, while it's highly unlikely that the implementation of constructs like p{...} will ever change, if they did change, this might fail to continue to function.

    0 讨论(0)
  • 2020-12-06 00:35

    My main problem with configuration in many small scripts I write, is that they often contain login data (username and password or auth-token) to a service I use. Then later, when the scripts gets bigger, I start versioning it and want to upload it on github.

    So before every commit I need to replace my configuration with some dummy values.

    $CONFIG{'user'} = 'username';
    $CONFIG{'password'} = '123456';
    

    Also you have to be careful, that those values did not eventually slip into your commit history at some point. This can get very annoying. When you went through this one or two times, you will never again try to put configuration into code.

    0 讨论(0)
  • 2020-12-06 00:37
    $CONFIG{'unhappy_employee'} = `rm -rf /`
    
    0 讨论(0)
提交回复
热议问题