Só reafirmando o que foi escrito pelo pessoal :
Em 22 de março de 2013 20:27, Marcio - Google <[email protected]> escreveu: > Mongers, > > Mais algumas dúvidas sobre "boas práticas". > > 1. Tenho algumas funções (sub) que são comuns a mais de um aplicativo. > Qual a forma mais simples, prática e elegante de compartilha-las entre > vários scripts, sendo que todos ficam no mesmo diretório? Hoje, tenho o > mesmo código repetido dentro do arquivo de cada script. > > estou assumindo que vc possui um subset de código comum e que será consumido por diversos scripts diferentes. A melhor maneira de fazer isto, é através de módulos ! Cria um namespace para você e organize estes códigos no name espace, mas atenção para o ORGANIZE. Então criei, por exemplo, o MINHAEMPRESA::Util::DB para os códigos de banco de dados, por exemplo. Mas faça isto de maneira muito genérica, evitando coisas muito específicas como por exemplo que o código destes módulos tenha usuários, senhas e diretórios. Estas coisas específicas devem ser parametros. Este módulo pode ser instalado no sistema, ou vc pode colocar ele numa estrutura de diretório e utlizar o 'lib' para especificar onde o script tem que procurar o módulo. Vou dar um exemplo de como um módulo de código comum deve ser genérico. <code> package MINHAEMPRESA::Util::DB; use Moose::Role; use namespace::clean -except => 'meta'; use DBI; use DBIx::Connector; has db_server => ( is => 'rw', isa => 'Str', default => 'localhost' ); has db_user => ( is => 'rw', isa => 'Str' ); has db_password => ( is => 'rw', isa => 'Str' ); has db_database => ( is => 'rw', isa => 'Str' ); has connection => ( is => 'ro', isa => 'Any', lazy => 1, builder => '_builder_conn' ); sub _builder_conn { my $self = shift; my $dsn = sprintf "DBI:mysql:database=%s; host=%s", $self->db_database, $self->db_server; return DBIx::Connector->new( $dsn, $self->db_user, $self->db_password, { 'RaiseError' => 1, 'mysql_enable_utf8' => 1, 'AutoCommit' => 1} ); } sub do { my $self = shift; my $sql = shift; my @data = @_; my $all = $self->connection->run( fixup => sub { $_->do( $sql, undef, @data ) }); return $all; } sub execute { my $self = shift; my $sql = shift; my @data = @_; my $sth = $self->connection->run( fixup => sub { $_->prepare($sql); } ); my $all; $sth->execute( @data ); while ( my $ref = $sth->fetchrow_hashref() ) { push @$all, $ref; } return $all || []; } 42; > 2. Tenho algumas funções (sub) que precisam retornar mais de uma > informação, as vezes até 5. Hoje como não sei fazer isso, > declaro variáveis no inicio do script e antes de chamar a sub, atribuo > "undef" para as variáveis. Dentro da sub eu atribuo os valores que preciso > a elas e depois da sub eu leio essas variáveis. Não me causa problema, só > acho estranho e pouco elegante. Exemplo de retorno: Se deu erro (1 ou 0), > Registro que deu erro (numérico), Descrição do Erro (string), Se conseguiu > cancelar do IPBX (1 ou 0). > Existem várias técnicas, a que você está utilizando tem a desvantagem de utilizar variáveis globais, o que pode ser ok para script (escrevo isto pq como sysadmin e scripts pequenos utilizo bastante), mas considerando a primeira pergunta já não fará sentido utilizar variável global para código reutilizável. Toda informação para a execução de uma sub tem que estar condida nela, desta maneira se ela recebe dados externos, tem que receber via parametros e se tem que retornar dados, também que que ser de maneira apropriada. Estou considerando a tua pergunta do ponto de vista de retorno de resultado, e aí podemos fazer de 2 formas : 1. utilizar o return sempre e somente para retornar o resultado e NUNCA erro (no código que eu coloquei acima, só retorno o resultado da interação com o banco) 2. na passagem de parametros, informar uma referência que deverá conter o resultado, e o retorno será um valor (código) que indica se ocorreu com sucesso a execução; <code> sub foo { my $param_1 = shift; my $param_2 = shift; $param_2 = eval { resultado de algum processamento }; return 501 if $@; return 200; } my $bar; if ( foo($alguma_coisa,\$bar) == 200 ) { # foi executada com sucesso e por isto estou aqui say $bar; } else { # algo não foi bom, então vamos fazer algo diferente } <code> Mas a técnica que eu prefiro é morrer quando ocorre um erro. Se ocorreu um erro grave, o teu consumidor precisa saber disto imediatamente, e ele é quem precisa tratar o erro. Então o mesmo código ficaria assim sub foo_with_die { my $param_1 = shift; my $param_2 = shift; $param_2 = eval { resultado de algum processamento }; die { error_code => 500, error_message => $@ } if $@; return $param_2; } my $bar; try { say foo($alguma_coisa,\$bar) == 200 ); } catch { # algo não foi bom, então vamos fazer algo diferente }; <code> > 3. Declaro as funções (sub) assim: > sub NomeDaSub { > my ($NomeDoPrimeiroParametro, ..., $NomeDoUltimoParametro)=@_; > } > Está certo? Ou tem uma técnica "mais" correta? > O Marcio Ferreira recomendou um excelente link sobre isto, nos avise se você tiver dificuldade em compreender o conteúdo. E com já escreveu o Vinceguerra, a gente não gosta muito de Uppercase nas variáveis e funções. > > > Em tempo, não estão faltando artigos no Equinócio? > Isto significa que você ainda pode contribuir com algo, mas será preenchido sim. Só estamos numa fase de garantir o wiskey das crianças também. > > > [...]'s > > Marcio > > =begin disclaimer > Sao Paulo Perl Mongers: http://sao-paulo.pm.org/ > SaoPaulo-pm mailing list: [email protected] > L<http://mail.pm.org/mailman/listinfo/saopaulo-pm> > =end disclaimer > > -- "o animal satisfeito dorme". - Guimarães Rosa
=begin disclaimer Sao Paulo Perl Mongers: http://sao-paulo.pm.org/ SaoPaulo-pm mailing list: [email protected] L<http://mail.pm.org/mailman/listinfo/saopaulo-pm> =end disclaimer
