Opa! Boas dicas Buss e Blabos!!! Fico devendo a pizza! :)
Vou melhorar aqui o que eu já tenho e vamos conversando! Sobre outros módulos, eu realmente não quero tentar instalar e etc porque eu sei que eu não vou conseguir mexer nesse servidor mesmo que o POC funcione, acho difícil que alguém me autorize a mexer (instalar um módulo) em um servidor sem suporte do fornecedor (tenho um dinossauro de Unix que mexe nele quando as coisas explodem e olhe lá...) E mesmo com a possível dificuldade de manipulação de datas com a api do posix eu prefiro ela que ter que calcular as coisas todas em shell, eheheh :) Além do mais, eu acho que eu posso pegar alguns atalhos no sentido de limpar a forma como eu to desenhando esse script Outros incrementos virão! :) Força e Honra Senhores! Geraldo Netto Sapere Aude => Non dvcor, dvco São Paulo, Brasil, -3gmt site: http://exdev.sf.net/ 2014-02-28 14:28 GMT-03:00 Blabos de Blebe <[email protected]>: > Eu tava escrevendo uma resposta, mas o buss foi mais rápido então cortando > os overlaps, com bastante licença poética: > > Primeiro as masturbações estilísticas: > >> #!/usr/bin/perl > > Eu prefiro usar: > > #!/usr/bin/env perl > > Porque, se o script for usado num ambiente onde espera-se outro perl que não > o do /usr/bin, como num perlbrew por exemplo, você não fica com a versão > antiga do perl hardcoded. > > Mas no seu caso, não acredito que vá ocorrer esse caso de uso, então pode > ficar como está, numa boa. Não está errado. > >> use strict; >> use warnings; > > Bom garoto! > > Ambas as pragmas são mandatórias, caso você esteja escrevendo algo > minimamente decente. Tem gente que gosta também do: > > use diagnostics; > > que te dá ainda mais informação em caso de problemas. > >> use POSIX; > > Aqui, a explicação longa é longa (call @garu), mas resumidamente, você está > importando alguns símbolos desnecessários automaticamente pro namespace > corrente. > > Isso é completamente irrelevante pro seu caso, mas vc poderia fazer assim: > > use POSIX (); > > que significa, adicione o módulo POSIX mas não importe nenhum símbolo. Ou > ainda: > > use POSIX qw{ strftime } > > que significa, adicione o módulo POSIX e importe somente o símbolo (função) > strftime. Nesse caso, ao usar a sub, vc não precisaria mais prefixar com > POSIX:: > > Do meu ponto de vista, tanto faz: > > use POSIX (); > POSIX::strftime(); > > ou > > use POSIX qw( strftime ); > strftime(); > > > Eu também prefiro nomear_funcoes_em_minusculas_com_underscore do que > comCameCaseIgualAoJava. > > > *** > > > Sobre a sua dúvida na captura e tratamento dos parâmetros tem algumas > sutiliezas que podem levar a erros. > > *** Primeiramente, acessar elementos versus acessar slice de um array > > A forma de acessar um escalar dentro de um array é indicando que ele é um > escalar, e dizendo qual índice você quer, ou seja, para acessar o terceiro > elemento do array foo, temos: > > my $elemento = $foo[ 2 ]; > > que significa mais ou menos, pegue o escalar ($) que está no array foo na > posição 3 (índice 2). > > Quando você faz: > > $a = @_[3]; > > Você está pedindo, me dê um array (@) contendo os elementos que estão "nos > índices" 3 do array _. Isso é um slice, que normalmente é usado pra pegar > pedaços de array. > > No seu caso, como você tá pedidndo uma lista com apenas um elemento, também > funciona mas experimente testar o seguinte: > > my $a = @_[1,2]; > > > Dito isso, quando vc faz: > > $foo = @_[0], a menos que você saiba exatamente o que está fazendo, isso > está errado. Não é questão de estilo aqui. O correto seria: > > $foo = $_[0]; ## Me dê o escalar que está no índice zero do array _ > > > *** Acessando parâmetros de funções > > Os parâmetros de funções são passados no array _, ou seja, @_. > > Ele faz aliasing das variáveis passadas, ou seja, ao lidar com $_[] > diretamente, você pode causar efeitos colaterais externos inesperados. > > Por exemplo, nesse oneliner apenas para efeitos didáticos: > > perl -e 'sub foo { $_[0]++ } $a=1; foo($a); print $a . $/' > > Por isso é boa prática criar uma cópia local dos argumentos dentro da > função. Isso pode ser feito de varias maneiras, conforme o caso: > > > ## Crie uma cópia do @_ chamada @args; > my @args = @_; > > > ## Crie uma lista com dois escalares, atribua os dois primeiros elementos do > @_ a cada um deles e descarte o resto; > my ( $first, $second ) = @_; > > > ## Crie uma lista contendo dois escalares, um array, guarde os dois > primeiros elementos de @_ nos escalares e o resto no array @tail > my ( $first, $second, @tail ) = @_ > > > ## Remova o primeiro elemento de @_ e coloque-o no escalar criado > my $first = shift; ## Equivalente a my $first = shift @_; > my $second = shift; # Pegue o "novo primeiro" elemento de @_ > > A vesão com shift remove definitivamente o primeiro elemento do array. O > segundo elemento passa a ser o primeiro, e assim sucessivamente. O tamanho > do array é reduzido em 1. > > Minhas fontes não confiáveis apontam que a versão com shift é menos > eficiente. Por favor me corrijam quem estiver com as fontes corretas. > > Eu prefiro usar as duas primeiras formas. my @args = @_; ou my ( $first, > $second ) = @_; > > *** > > Conforme o buss apontou, separe uma instrução por linha: > > sub calcularDeslocamentoAno { > my ( $ano ) = @_; > > die 'ano invalido' > unless defined $ano; > > return $ano > 99 ? $ano - 1900 : $ano; > } > > Veja como fica mais claro pro próximo cara que for dar manutenção nisso. > > *** > > Use qx ao invés de ` pra invocar comandos externos > > sub calcularDiaInicioHorarioVerao { > my $dia_inicio = qx{ cal 10 2013 | tail -4 | head -1 | cut -d' ' -f7 }; > } > > Considerações finais: > > 1) Seu código está até bem razoável. Compartimentarizado em funções que só > fazem uma coisa. Ele está claro no que ele pretende fazer. Isso é muito bom. > Té melhor que muito programador "experiente" que tem por aí. > > 2) Tem uns requintes de Perl 4, mas fazendo os ajustes indicados, que não > são nada complicados, seu código vai rejuvenecer uns 20 anos!!! > > 3) Não é porque você executa comandos do Shell que o seu código Perl fica > ruim. Nada disso. É parte da linguagem e perfeitamente normal, > principalmente, porque você deixa bem claro o que você está fazendo e de > forma organizada. Acessar o shell continua sendo elegante. > > Feio é fazer algazarra. > > Existem módulos pra rodar comandos externos, com mil funcionalidades, mas > acredito que não são necessários no seu caso. > > 4) DateTime, pode se mais indicado do que calcular datas na mão, mas ele não > é "Core" (http://perldoc.perl.org/corelist.html), portanto pode ser difícil > de instalar no seu sistema com ambiente restrito. Você tem que medir se o > custo de instalar vale o benefício que ele fornece ou ainda se o risco do > seu código falhar é alto ou baixo. Isso é uma análise sua. > > Eventualmente eu pelo menos comentaria no código que o DateTime poderia ser > uma solução mais adequada. Vai que o ambiente muda no futuro e ele possa ser > instalado mais facilmente. > > 5) Tente escrever testes automatizados que validem a sua aplicação. > > > > Bom, espero que tenhamos te ajduado. Qualquer coisa avisa. > > > []'s > > > > > > > > > > 2014-02-28 13:31 GMT-03:00 Bruno Buss <[email protected]>: > >> Oi Geraldo, >> >> Respostas inline :-) >> >> >> 2014-02-28 11:59 GMT-03:00 Geraldo Netto <[email protected]>: >> >>> Bom Dia Pessoal! >>> >>> Consegui evoluir no código com a api do posix mesmo >>> crio as datas com POSIX::strftime >>> e calculo o horário de verão pegando a saida do comando cal no shell >>> >>> yep, eu sei que é feito, mas resolve o meu problema de um jeito rápido... >>> por hora, a idéia é só gerar o "okay" da gerencia p/ matar umas 4 >>> versões shell que fazem o mesmo trabalho, mas precisam de alguns >>> parâmetros diferentes e alguma intervenção humana especificamente no >>> período de horário de verão >> >> >> Thumbs up por resolver o problema! :D >> >> Entretanto, o que a galera quer passar aqui, e' que mesmo que você >> realmente acredite que esta resolvendo seu problema de forma simples e >> rápida agora... não esta'. Ou melhor, o jeito rápido agora *provavelmente* >> ira' te causar uma baita dor de cabeça soon(tm). >> >> Tente utilizar o DateTime, e' uma solução ordens de grandeza melhor e não >> e' tao difícil assim :-) >> >>> >>> >>> a minha dúvida é primária, suponho... >>> mas eu não entendi o porque usar o shift >>> se eu posso verificar com o defined() se o @_[<número>] está definido? >> >> >> O shift serve para voce retirar e retornar o 1o elemento da lista de >> argumentos/parâmetros que foi passada para sua função. >> >> E' uma das formas idiomáticas de se fazer isso, a outra seria "my ($v_a, >> $v_b, $v_c) = @_;". >> Pessoalmente prefiro com shift :-) >> >>> >>> >>> Aceito sugestões e Mais uma vez, Valeu mesmo pela força! :P >>> >>> >>> BTW, código todo a seguir: >>> >>> #!/usr/bin/perl >>> >>> use strict; >>> use warnings; >>> >>> use POSIX; >>> >>> >>> # a inicia a data em 1900 entao, se for passado 95 => 1995 >>> sub calcularDeslocamentoAno { >>> die "ano invalido" unless defined(@_[0]) && return ($_[0] > 99 ? >>> $_[0] - 1900 : $_[0]); >>> } >> >> >> Então para você o ano 50 e' o mesmo que o ano 1950? :P >> Ou se eu passar para você o ano 1800, ele retorna -100. >> >> Outra coisa, você realmente não precisa colocar o return na mesma linha do >> die... >> Por exemplo: >> >> sub calcularDeslocamentoAno{ >> my $ano = shift; >> >> #Rejeitando coisas que nossa funcao nao sabe tratar. >> die "ano invalido" unless defined $ano && $ano >= 1900; >> >> return $ano - 1900; >> } >> >>> >>> >>> sub criarData { >>> die "parametros invalidos" unless (defined(@_[0]) && >>> defined(@_[1]) && defined(@_[2])); >>> #Usage: POSIX::strftime(fmt, sec, min, hour, mday, >>> mon, year, wday = -1, yday = -1, isdst = -1) >>> return POSIX::strftime("%Y,%m,%d", 0, 0, 0, @_[0], (@_[1] -1), >>> &calcularDeslocamentoAno(@_[2]), 0, 0); >>> } >> >> >> Idealmente você estaria tratando: >> * Se o 1o parâmetro e' um dia que esta' no mês (posso tentar usar stftime >> passando o dia 31 de Fev?) >> * Se o 1o parâmetro e' um dia valido at all (dia igual a 44 por exemplo). >> * Lembrar que o dia e o mês são 0-based, ou seja Janeiro => 0, Fev => 1, >> etc. >> ... >> >> Voce tambem poderia fazer: >> sub criarData { >> my ($dia, $mes, $ano) = @_; >> die "parametros invalidos" unless defined $dia && >> defined $mes && >> defined $ano; >> ... >> } >> >> Detalhe: O DateTime tem funções de formatação de data tao boas quanto ;-) >> >>> >>> >>> sub calcularDiaInicioHorarioVerao { >>> my $dia_inicio = `cal 10 2013 | tail -4 | head -1 | cut -d' ' -f7`; >>> } >>> >>> sub calcularDiaFimHorarioVerao { >>> my $dia_fim = `cal 2 2014 | tail -4 | head -1 | cut -d' ' -f7`; >>> } >> >> >> Alguém já disse em substituir isso tudo por DateTime? :P >> >>> >>> >>> sub trim { >>> my $s = shift; >>> $s =~ s/^\s+|\s+$//g; >>> return $s; >>> } >>> >>> print &criarData(2, 5, 2014); >>> print &trim($dia_inicio); >>> print &trim($dia_fim); >> >> >> Não sei exatamente qual Perl você ta usando, mas acredito que não e' >> necessário prefixar as chamadas de funções com &. Inclusive isso e' >> considerado não legal hoje em dia :-) >> >> [ ]'s >> >> PS: Utilize uma ferramenta tipo pastebin ou Gist (do GitHub) para copiar e >> enviar codigos em listas de e-mail :-) >> >>> >>> >>> Geraldo Netto >>> Sapere Aude => Non dvcor, dvco >>> São Paulo, Brasil, -3gmt >>> site: http://exdev.sf.net/ >>> >>> 2014-02-26 23:41 GMT-03:00 Geraldo Netto <[email protected]>: >>> > Opa! >>> > >>> > Tudo okay Pessoal? >>> > >>> > Eu sou o Geraldo, um ghost reader da SPPM (e algumas outras PMs) >>> > e eu ando trabalhando vagarosamente num projetinho >>> > que eu dependo de verificação do horário de verão >>> > >>> > A idéia é separar o ano em 3 partes: >>> > >>> > fim do horário de verão (terceiro domingo de fevereiro) >>> > fora do horário de verão >>> > início do horário de verão (terceiro sábado de fevereiro) >>> > >>> > E baseado nisso, lançar um shell que vai receber o timezone, data de >>> > início e de fim >>> > p/ fazer a coleta de dados pelo hp openview (comando ovpmbatch) >>> > >>> > Só que... >>> > -eu tenho um servidor tru64 (sem suporte) >>> > -rodando perl 5.8 (2002 pelo o que o version diz...) >>> > -sem sudo/root/possibilidade de instalação de pacotes de terceiros >>> > -<inclua-aqui-todas-as-limitações-que-vocês-imaginarem-de-infra> >>> > -meu "core business" é análise de desempenho de software, >>> > então o código não pode ser muito "perlish" >>> > porque alguém pode precisar dar manutenção depois de mim >>> > >>> > Embora eu ainda não tenha código real (só comecei a brincar) >>> > Eu estou pensando em ir com a api do posix, especificamente a >>> > função/método strftime >>> > >>> > Eventualmente vocês teriam alguma sugestão? >>> > >>> > >>> > Grande Abraço! >>> > >>> > Geraldo Netto >>> > Sapere Aude => Non dvcor, dvco >>> > São Paulo, Brasil, -3gmt >>> > site: http://exdev.sf.net/ >>> =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 >> >> >> >> >> -- >> Bruno C. Buss >> http://www.brunobuss.net >> >> >> 2014-02-28 11:59 GMT-03:00 Geraldo Netto <[email protected]>: >> >>> Bom Dia Pessoal! >>> >>> Consegui evoluir no código com a api do posix mesmo >>> crio as datas com POSIX::strftime >>> e calculo o horário de verão pegando a saida do comando cal no shell >>> >>> yep, eu sei que é feito, mas resolve o meu problema de um jeito rápido... >>> por hora, a idéia é só gerar o "okay" da gerencia p/ matar umas 4 >>> versões shell que fazem o mesmo trabalho, mas precisam de alguns >>> parâmetros diferentes e alguma intervenção humana especificamente no >>> período de horário de verão >>> >>> a minha dúvida é primária, suponho... >>> mas eu não entendi o porque usar o shift >>> se eu posso verificar com o defined() se o @_[<número>] está definido? >>> >>> Aceito sugestões e Mais uma vez, Valeu mesmo pela força! :P >>> >>> >>> BTW, código todo a seguir: >>> >>> #!/usr/bin/perl >>> >>> use strict; >>> use warnings; >>> >>> use POSIX; >>> >>> >>> # a inicia a data em 1900 entao, se for passado 95 => 1995 >>> sub calcularDeslocamentoAno { >>> die "ano invalido" unless defined(@_[0]) && return ($_[0] > 99 ? >>> $_[0] - 1900 : $_[0]); >>> } >>> >>> sub criarData { >>> die "parametros invalidos" unless (defined(@_[0]) && >>> defined(@_[1]) && defined(@_[2])); >>> #Usage: POSIX::strftime(fmt, sec, min, hour, mday, >>> mon, year, wday = -1, yday = -1, isdst = -1) >>> return POSIX::strftime("%Y,%m,%d", 0, 0, 0, @_[0], (@_[1] -1), >>> &calcularDeslocamentoAno(@_[2]), 0, 0); >>> } >>> >>> sub calcularDiaInicioHorarioVerao { >>> my $dia_inicio = `cal 10 2013 | tail -4 | head -1 | cut -d' ' -f7`; >>> } >>> >>> sub calcularDiaFimHorarioVerao { >>> my $dia_fim = `cal 2 2014 | tail -4 | head -1 | cut -d' ' -f7`; >>> } >>> >>> sub trim { >>> my $s = shift; >>> $s =~ s/^\s+|\s+$//g; >>> return $s; >>> } >>> >>> print &criarData(2, 5, 2014); >>> print &trim($dia_inicio); >>> print &trim($dia_fim); >>> >>> Geraldo Netto >>> Sapere Aude => Non dvcor, dvco >>> São Paulo, Brasil, -3gmt >>> site: http://exdev.sf.net/ >>> >>> 2014-02-26 23:41 GMT-03:00 Geraldo Netto <[email protected]>: >>> > Opa! >>> > >>> > Tudo okay Pessoal? >>> > >>> > Eu sou o Geraldo, um ghost reader da SPPM (e algumas outras PMs) >>> > e eu ando trabalhando vagarosamente num projetinho >>> > que eu dependo de verificação do horário de verão >>> > >>> > A idéia é separar o ano em 3 partes: >>> > >>> > fim do horário de verão (terceiro domingo de fevereiro) >>> > fora do horário de verão >>> > início do horário de verão (terceiro sábado de fevereiro) >>> > >>> > E baseado nisso, lançar um shell que vai receber o timezone, data de >>> > início e de fim >>> > p/ fazer a coleta de dados pelo hp openview (comando ovpmbatch) >>> > >>> > Só que... >>> > -eu tenho um servidor tru64 (sem suporte) >>> > -rodando perl 5.8 (2002 pelo o que o version diz...) >>> > -sem sudo/root/possibilidade de instalação de pacotes de terceiros >>> > -<inclua-aqui-todas-as-limitações-que-vocês-imaginarem-de-infra> >>> > -meu "core business" é análise de desempenho de software, >>> > então o código não pode ser muito "perlish" >>> > porque alguém pode precisar dar manutenção depois de mim >>> > >>> > Embora eu ainda não tenha código real (só comecei a brincar) >>> > Eu estou pensando em ir com a api do posix, especificamente a >>> > função/método strftime >>> > >>> > Eventualmente vocês teriam alguma sugestão? >>> > >>> > >>> > Grande Abraço! >>> > >>> > Geraldo Netto >>> > Sapere Aude => Non dvcor, dvco >>> > São Paulo, Brasil, -3gmt >>> > site: http://exdev.sf.net/ >>> =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 >> >> >> >> >> -- >> Bruno C. Buss >> http://www.brunobuss.net >> >> =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 >> > > > =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 > =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
