Почему записывать данные конфигурации в код - плохая идея?

Половина решения, __ набор __ на классе не работает, все еще. Решением является пользовательский класс свойства, реализовывая и свойство и staticmethod

class ClassProperty(object):
    def __init__(self, fget, fset):
        self.fget = fget
        self.fset = fset

    def __get__(self, instance, owner):
        return self.fget()

    def __set__(self, instance, value):
        self.fset(value)

class Foo(object):
    _bar = 1
    def get_bar():
        print 'getting'
        return Foo._bar

    def set_bar(value):
        print 'setting'
        Foo._bar = value

    bar = ClassProperty(get_bar, set_bar)

f = Foo()
#__get__ works
f.bar
Foo.bar

f.bar = 2
Foo.bar = 3 #__set__ does not
22
задан daxim 11 May 2011 в 19:17
поделиться

4 ответа

Есть много причин, чтобы избежать конфигурации в коде, и я рассмотрю некоторые из них в главе о конфигурации в Мастеринг Perl .

  • Никакие изменения конфигурации не должны приводить к риску нарушения программы. Это, конечно, не должно нести риск нарушения этапа компиляции.
  • Люди не должны редактировать источник, чтобы получить другую конфигурацию.
  • Люди должны иметь возможность использовать одно и то же приложение без использования общей группы настроек, вместо этого переустанавливать приложение просто для изменения конфигурации.
  • Людям должно быть разрешено создавать несколько различных конфигураций и запускать их партиями без необходимости редактировать исходный код.
  • Вы должны иметь возможность протестировать свое приложение при других настройках без изменения кода.
  • Люди не должны учиться программировать, чтобы иметь возможность использовать ваш инструмент.
  • Вы должны только свободно связывать свои структуры данных конфигурации с источником информации, чтобы облегчить последующие архитектурные изменения.
  • Вы действительно хотите интерфейс вместо прямого доступа на уровне приложений.

Я подытожил это в своем классе Мастеринг Perl , сказав людям, что первое правило программирования - создавать ситуацию, когда вы выполняете меньше работы, и люди оставляют вас в покое. Когда вы помещаете конфигурацию в код, вы тратите больше времени на решение проблем установки и реагирование на поломки. Если вам не нравятся подобные вещи, дайте людям возможность изменить настройки, не заставляя вас больше работать.

27
ответ дан 29 November 2019 в 03:40
поделиться

Плохая идея помещать данные конфигурации в скомпилированный код , потому что пользователь не может их легко изменить. Для сценариев, просто убедитесь, что он полностью отделен от остальных, и хорошо документируйте.

6
ответ дан 29 November 2019 в 03:40
поделиться

Моя основная проблема с настройкой во многих небольших скриптах, которые я пишу, заключается в том, что они часто содержат данные для входа (имя пользователя и пароль или токен) в службу, которую я использую. Затем, когда скрипты становятся больше, я начинаю их версию и хочу загрузить их на github.

Поэтому перед каждым коммитом мне нужно заменить мою конфигурацию на несколько фиктивных значений.

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

Также вы должны быть осторожны, чтобы эти значения в какой-то момент не попали в историю ваших коммитов. Это может стать очень раздражающим. Когда вы проделали это один или два раза, вы больше никогда не попытаетесь вставить конфигурацию в код.

0
ответ дан 29 November 2019 в 03:40
поделиться

Извините за длинный список кодов. Ниже приведен удобный модуль Conf.pm, который я использовал во многих системах и который позволяет указывать разные переменные для разных производственных, промежуточных и сред разработки. Затем я строю свои программы так, чтобы они либо принимали параметры среды в командной строке, либо я сохраняю этот файл вне дерева управления исходным кодом, чтобы никогда не перезаписывать его.

AUTOLOAD предоставляет автоматические методы для поиска переменных.

# 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;
-1
ответ дан 29 November 2019 в 03:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: