Posts de January, 2009

[Tiago Peczenyj] Fibonacci: alguns algoritmos efetivos em AWK

Friday, January 30th, 2009

Estava apreciando hoje de manhã um post do Felipe Tonello: Analisando Número de Fibonacci e Recursividade. É um bom artigo sobre aquelas coisas que alguns podem ter visto na faculdade e são sempre uteis: matemática, analise de algoritmos e um pouco de mente aberta.

Imediatamente tratei de testar a velocidade dos dois algoritmos propostos usando AWK (que, por ser interpretado, pode revelar melhor as nuances entre as abordagens). Algoritmos recursivos são interessantes, principalmente quando trabalhamos com linguagens funcionais, porém algumas formas tem um custo computacional muito alto e o calculo de Fibonacci é um exemplo perfeito: para cada termo eu preciso calcular os dois termos anteriores e, então, soma-los, e isso cresce geométricamente, consumindo memória e processamento, sem falar que tenho muita repetição de código desnecessária.

A tecnica de programação dinâmica apresentada cria um cache de resultados, dessa forma evito boa parte do trabalho extra, veja o resultado:

Fibonacci(36) pelo algoritmo recursao simples:14930352 usando 48315633 iteracoes

real    0m51.961s
user    0m23.881s
sys     0m0.012s
Fibonacci(36) pelo algoritmo programacao dinamica:14930352 usando 71 iteracoes

real    0m0.002s
user    0m0.000s
sys     0m0.000s

Usando programação dinâmica eu uso muito menos de 1% do processamento necessário pela forma recursiva tradicional. Parece ótimo, não? Depende, pois eu apenas afastei o problema: ao calcular termos de alta ordem eu terei o mesmo problema, afinal o algoritmo é O[n].

Lembrei de um post do Ronaldo Melo Ferraz, Conceitos de Programação: Tail Recursion enquando estava testando os algoritmos em Erlang e encontrei esta implementação. A adaptação para awk é tranquila e o teste mostrou este resultado:

Fibonacci(36) pelo algoritmo programacao dinamica:14930352 usando 71 iteracoes

real    0m0.002s
user    0m0.000s
sys     0m0.000s
Fibonacci(36) pelo algoritmo tail recursion:14930352 usando 38 iteracoes

real    0m0.001s
user    0m0.000s
sys     0m0.004s

Um resultado ainda mais interessante, pois eu consigo obter o valor do termo com um pouco mais da metade das iterações do que usando programação dinâmica (sem onerar a memória com o cache dos resultados).

Esta analise é muito superficial, a ideia é apenas despertar a curiosidade sobre estes tópicos.

O codigo fonte utilizado nesse benchmark:
function Fib_normal(N) {
return (N > 1)? Fib_normal(N-1) + Fib_normal(N-2) : N
}
function Fib_dinamic(N) {
if (!m[N]) m[N] = (N > 1)? Fib_dinamic(N-1) + Fib_dinamic(N-2) : N
return m[N]
}

function Fib(N) { return Fib_tr(N,0,1); }
function Fib_tr(I,R,N){
return (I==0)? R : Fib_tr(I-1,N,R+N)
}

[Guilherme Cirne] Impressões da Retrospectiva Baseada em Feedback

Tuesday, January 27th, 2009

Fizemos nossa primeira retrospectiva baseada em feedback e o resultado foi muito positivo. Acredito que conseguimos criar um ambiente de muita confiança. Todos se sentiram bem a vontade para dar e receber feedback.

Um ponto interessante que notei é que muitos comentários que normalmente ficavam guardados foram expostos de forma franca, sem que houvesse qualquer tipo de sentimento negativo de quem recebia o feedback.

Outro ponto é que eu, como Scrum Master, e o nosso Product Owner participamos normalmente. É importante que haja transparência e confiança entre todos – independente do papel que cada um exerce – já que no final das contas todos nós somos responsáveis pelo sucesso dos produtos que criamos.

O resultado de uma retrospectiva como essa é que fica bem claro para todos como nossas atitudes e ações ajudam ou atrapalham nosso trabalho em equipe. As pessoas saem realmente motivadas a melhorar. Certamente vamos repetir esse tipo de retrospectiva daqui pra frente.

[Guilherme Cirne] Impressões da Retrospectiva Baseada em Feedback

Tuesday, January 27th, 2009

Fizemos nossa primeira retrospectiva baseada em feedback e o resultado foi muito positivo. Acredito que conseguimos criar um ambiente de muita confiança. Todos se sentiram bem a vontade para dar e receber feedback.

Um ponto interessante que notei é que muitos comentários que normalmente ficavam guardados foram expostos de forma franca, sem que houvesse qualquer tipo de sentimento negativo de quem recebia o feedback.

Outro ponto é que eu, como Scrum Master, e o nosso Product Owner participamos normalmente. É importante que haja transparência e confiança entre todos - independente do papel que cada um exerce - já que no final das contas todos nós somos responsáveis pelo sucesso dos produtos que criamos.

O resultado de uma retrospectiva como essa é que fica bem claro para todos como nossas atitudes e ações ajudam ou atrapalham nosso trabalho em equipe. As pessoas saem realmente motivadas a melhorar. Certamente vamos repetir esse tipo de retrospectiva daqui pra frente.

[Tiago Motta] Cuidado ao cachear named_scope no Rails

Friday, January 23rd, 2009

Deve-se tomar cuidado ao cachear o acesso a um named_scope pois ele tem um carregamento de forma preguiçosa, o famoso lazy load. Assim, o código abaixo gravaria no cache não os atores femininos, mas sim todos os atores.

class Filme    #...  def atores_femininos_cacheado    Rails.cache.fetch("#{self.id}:atores-principais") { self.atores.femininos }  end

class Ator  #...  named_scope :femininos, :conditions => { :sexo => 'F' }

Se você observar o log, verá que o rails executará a query sem as condições definidas na classe Ator para o named_scope :femininos. E que após ser cacheado, será essa a query que deixará de ser executada.

A query para buscar atores femininos do named_scope só será realmente executada quando algum método do objeto retornado pelo método .atores.femininos for chamado. Veja no exemplo abaixo:

@filme = Filme.find_by_id 10filme.atores_femininos_cacheado.last

Ou seja, o cacheamento não está servindo ao propósito definido. Uma solução para isso é cachear diretamente o resultado de um find, como pode ser visto abaixo:

class Filme    #...  def atores_femininos_cacheado    Rails.cache.fetch("#{self.id}:atores-principais") do      Ator.find_all_by_filme_id self, :conditions => { :sexo => 'F' }    end  end

[Tiago Motta] PGError com Rails no Heroku

Wednesday, January 21st, 2009

Essa dica é para quem utiliza o Heroku Garden para desenvolver suas aplicações rails. Ao rodar os specs diretamente da interface web do Heroku pode ser que um dia você se depare com o seguinte erro:

PGError: ERROR: relation "filmes" does not exist: SELECT a.attname, format_type(a.atttypid, a.atttypmod),d.adsrc, a.attnotnullFROM pg_attribute a LEFT JOIN pg_attrdef dON a.attrelid = d.adrelid AND a.attnum = d.adnumWHERE a.attrelid = 'filmes'::regclassAND a.attnum > 0 AND NOT a.attisdroppedORDER BY a.attnum

O erro acontece porque o link para rodar as migrations, que aparece na interface do heroku, não as executa no ambiente de testes. Portanto, é preciso abrir a tela do rake e executar as seguintes linhas antes de rodar seus specs.

db:migratedb:test:prepare

UPDATE

Descobri outro problema do Heroku. O schema.rb é criado e alterado no diretório tmp. Dessa forma para que o PGError não dê novamente em outra atualização do banco, você precisa copiá-lo para o diretório db e então no console do rake rodar:

db:test:clone

[Emerson Macedo] Os 5 níveis do desenvolvedor nos testes automatizados

Thursday, January 15th, 2009

Alguns acontecimentos me fizeram refletir um pouco sobre a relação entre o desenvolvedor de software e os testes automatizados.

Muitas vezes parei pra explicar pra vários colegas de trabalho sobre a importância do assunto, fiz pair-programmming pra ensinar como se faz, em fim, investi muito tempo pra ajudar diversas pessoas com isso. Por incrível que pareça, tem muiiiiiita gente que ainda não entendeu muito bem. Portanto, resolvi classificar a relação entre o desenvolvedor e os testes automatizados em 5 níveis.

São eles:

  1. Ignorante: Esse é o nível no qual o desenvolvedor não sabe direito o que são testes automatizados ou sequer ouviu falar sobre o assunto (acredite, ainda tem gente assim em pleno 2009).
  2. Indiferente: Nesse nível, o desenvolvedor já sabe o que é, mas acha que essa prática/tecnica não serve pra nada. Apenas toma tempo e atrasa a entrega do produto que está sendo desenvolvido. A sensação dele é que sem os testes a entrega seria mais rápida (e a quantidade de bugs tb vão aparecer mais rápido).
  3. Prequiçoso: Nesse nível eu encontro muita gente. É nesse nível onde a ficha caiu mas o camarada não toma coragem pra aprender a fazer os testes automatizados. Ainda existe o medo de perder muito tempo com essa prática e a preguiça impera, impedindo o progresso.
  4. Decidido: Esse pra mim é o nível mais importante. É nessa hora que o desenvolvedor se dá conta que não dá mais pra desenvolver software sem testes automatizados. É nessa hora que o cara pensa: “como eu pude desenvolver sem testes até hoje?”. É nesse momento que inicia-se o aprendizado.
  5. Profissional: Nesse nível, o desenvolvedor já não se sente mais confortável desenvolvendo sem testes automatizados. Desenvolver sem testes o incomoda profundamente. Nesse momento o mesmo está maduro quanto a importância dos testes e a aplicação na prática. O mesmo começa a se tornar um evangelista para os demais desenvolvedores e sempre que pode, fala sobre o assunto. Nesse momento o desenvolvedor pode realmente dizer que é um profissional, pois hoje em dia não se admite mais desenvolver sem ter testes automatizados que garantam qualidade daquilo que se desenvolve.

Em qual nível você está?

[Guilherme Cirne] Retrospectiva Baseada em Feedback

Tuesday, January 13th, 2009

A reunião de retrospectiva ocorre ao final de cada iteração de um projeto ágil. A idéia é o time avaliar o que não está funcionando bem de forma a melhorar dali para frente. Trata-se da melhoria contínua do processo, através do ciclo de inspecionar e adaptar (inspect and adapt).

Existem diversas formas de se fazer uma reunião de retrospectiva. É interessante que a dinâmica dessa reunião seja alterada com uma certa frequência, para que não fique monótona para os participantes, o que poderia diminuir seus benefícios.

Ontem e hoje participei de um treinamento de RH. Para quem acha que esse tipo de evento é uma perda de tempo, sugiro rever seus conceitos. Fizemos uma atividade onde tínhamos que dar feedback uns para os outros. Isso me deu uma idéia para minha próxima retrospectiva.

O que fizemos na atividade (e vamos fazer na retrospectiva) é o seguinte. Cada um lista alguns pontos positivos e negativos sobre si mesmo. Uma pessoa por vez lê os seus pontos e depois só escuta enquanto as demais vão dando feedback sobre eles podendo, inclusive, acrescentar novos pontos. Prossegue-se até que todo mundo tenha dado e recebido feedback de todos os outros.

A grande sacada é a forma de dar o feedback. O que deve ser feito é ilustrar cada ponto com exemplos concretos em situações específicas de quando eles ocorreram. Não se deve fazer um julgamento pessoal do ponto em questão mas sim, no lugar disso, devem ser destacadas as suas consequências observáveis. Dessa forma, a pessoa recebendo o feedback consegue perceber mais claramente como seus comportamentos e atitudes influenciam positiva ou negativamente nas demais pessoas e nos resultados do time e, com isso, fica mais aberta a mudanças.

[Guilherme Cirne] Retrospectiva Baseada em Feedback

Tuesday, January 13th, 2009

A reunião de retrospectiva ocorre ao final de cada iteração de um projeto ágil. A idéia é o time avaliar o que não está funcionando bem de forma a melhorar dali para frente. Trata-se da melhoria contínua do processo, através do ciclo de inspecionar e adaptar (inspect and adapt).

Existem diversas formas de se fazer uma reunião de retrospectiva. É interessante que a dinâmica dessa reunião seja alterada com uma certa frequência, para que não fique monótona para os participantes, o que poderia diminuir seus benefícios.

Ontem e hoje participei de um treinamento de RH. Para quem acha que esse tipo de evento é uma perda de tempo, sugiro rever seus conceitos. Fizemos uma atividade onde tínhamos que dar feedback uns para os outros. Isso me deu uma idéia para minha próxima retrospectiva.

O que fizemos na atividade (e vamos fazer na retrospectiva) é o seguinte. Cada um lista alguns pontos positivos e negativos sobre si mesmo. Uma pessoa por vez lê os seus pontos e depois só escuta enquanto as demais vão dando feedback sobre eles podendo, inclusive, acrescentar novos pontos. Prossegue-se até que todo mundo tenha dado e recebido feedback de todos os outros.

A grande sacada é a forma de dar o feedback. O que deve ser feito é ilustrar cada ponto com exemplos concretos em situações específicas de quando eles ocorreram. Não se deve fazer um julgamento pessoal do ponto em questão mas sim, no lugar disso, devem ser destacadas as suas consequências observáveis. Dessa forma, a pessoa recebendo o feedback consegue perceber mais claramente como seus comportamentos e atitudes influenciam positiva ou negativamente nas demais pessoas e nos resultados do time e, com isso, fica mais aberta a mudanças.

[Guilherme Cirne] Retrabalho Não Combina Com Equipes Ágeis

Friday, January 9th, 2009

Retrabalho significa jogar tempo, dinheiro, etc. fora. Certamente, ninguém quer isso. Para tentar evitar esse retrabalho, normalmente a solução proposta envolve especificar “bem especificado”, planejar “bem planejado”, tudo com muita antecedência. É a velha muscle memory agindo. Sabemos que isso não funciona. Simplesmente porque é impossível prever o futuro.

A solução que eu acredito funcionar é aplicar as práticas de XP. E não basta aplicar uma ou outra, temos que aplicar todas. Juntas elas promovem uma sinergia que não existe quando são utilizadas de forma isolada.

Práticas como TDD, refactoring, integração contínua, programação em par, cliente presente, sentar-se junto, design incremental garantem uma base de código saudável, com design simples. Com isso o custo de mudança permanece constante ou mesmo pode cair com o tempo.

Kent Beck viu em muitos times XP que ao longo do tempo os sistemas desenvolvidos por esses times ficavam cada vez mais flexíveis e fáceis de mudar ao invés do que estamos mais acostumados a ver, que são aqueles sistemas legados cujo custo de mudança cresce exponencialmente com o tempo. Tal afirmativa pode parecer ir contra o senso comum mas faz todo o sentido quando temos as práticas do XP aplicadas corretamente.

O custo de um time XP competente é inegavelmente alto. Mas compensa no longo prazo por permitir que sistemas não precisem ser reescritos do zero a cada x anos. Além disso, outros motivos existem para se ter um time competente. Por exemplo, evitar o custo dos Net Negative Producing Programmers. Ou seja, na minha opinião vale a pena pagar pelos melhores.

Tenho vendido a idéia de que se uma equipe ágil está funcionando bem, nunca haverá retrabalho e sim, simplesmente, trabalho.

[Guilherme Cirne] Retrabalho Não Combina Com Equipes Ágeis

Friday, January 9th, 2009

Retrabalho significa jogar tempo, dinheiro, etc. fora. Certamente, ninguém quer isso. Para tentar evitar esse retrabalho, normalmente a solução proposta envolve especificar “bem especificado”, planejar “bem planejado”, tudo com muita antecedência. É a velha muscle memory agindo. Sabemos que isso não funciona. Simplesmente porque é impossível prever o futuro.

A solução que eu acredito funcionar é aplicar as práticas de XP. E não basta aplicar uma ou outra, temos que aplicar todas. Juntas elas promovem uma sinergia que não existe quando são utilizadas de forma isolada.

Práticas como TDD, refactoring, integração contínua, programação em par, cliente presente, sentar-se junto, design incremental garantem uma base de código saudável, com design simples. Com isso o custo de mudança permanece constante ou mesmo pode cair com o tempo.

Kent Beck viu em muitos times XP que ao longo do tempo os sistemas desenvolvidos por esses times ficavam cada vez mais flexíveis e fáceis de mudar ao invés do que estamos mais acostumados a ver, que são aqueles sistemas legados cujo custo de mudança cresce exponencialmente com o tempo. Tal afirmativa pode parecer ir contra o senso comum mas faz todo o sentido quando temos as práticas do XP aplicadas corretamente.

O custo de um time XP competente é inegavelmente alto. Mas compensa no longo prazo por permitir que sistemas não precisem ser reescritos do zero a cada x anos. Além disso, outros motivos existem para se ter um time competente. Por exemplo, evitar o custo dos Net Negative Producing Programmers. Ou seja, na minha opinião vale a pena pagar pelos melhores.

Tenho vendido a idéia de que se uma equipe ágil está funcionando bem, nunca haverá retrabalho e sim, simplesmente, trabalho.