Tagview Tecnologia

    Soluções web

    Recentemente, vi uma discussão no grupo de emails “rails-br” sobre como extender a classe String em uma aplicação Ruby on Rails. Na Tagview, costumamos utilizar muito este recurso em nossos projetos e acredito que fazemos isto de uma maneira bastante limpa e legível. Neste post vou detalhar este processo.

    Vou utilizar no exemplo um código que adiciona um método à classe String. Mas, gostaria de ressaltar que podemos extender qualquer classe do Ruby ou do Rails com este mesmo procedimento. Suponha que queremos adicionar um método de instância à classe String. Este método retornará a própria string, mas sem acentos. Vamos chamo-lo de “no_accent”. Lembrando que nem Ruby nem Rails implementam algum método que faça isto.

    Primeiramente, vamos definir um módulo que contenha este nosso método. Vamos chamá-lo de “StringExtensions”.

    module StringExtensions
      def no_accent
        self.
            gsub(/á/,  'a').     # à => a
            gsub(/á/,  'a').     # á => a
            gsub(/â/,  'a').     # â => a
            gsub(/ã/,  'a').     # ã => a
            gsub(/é/,  'e').     # é => e
            gsub(/ê/,  'e').     # ê => e
            gsub(/í/,  'i').       # í => i
            gsub(/ó/,  'o').     # ó => o
            gsub(/ô/,  'o').     # ô => o
            gsub(/ã/,  'o').     # õ => o
            gsub(/ú/,  'u').     # ú => u
            gsub(/ü/,  'u').     # ü => u
            gsub(/ç/,  'c').      # ç => c
            gsub(/À/,  'A').     # À => A
            gsub(/Á/,  'A').     # Á => A
            gsub(/Â/,  'A').     # Â => A
            gsub(/Ã/,  'A').     # Ã => A
            gsub(/É/,  'E').      # É => E
            gsub(/Ê/,  'E').      # Ê => E
            gsub(/Í/,  'I').        # Í => I
            gsub(/Ó/,  'O').     # Ó => O
            gsub(/Ô/,  'O').     # Ô => O
            gsub(/Õ/,  'O').     # Õ => O
            gsub(/Ú/,  'U').      # Ú => U
            gsub(/Ü/,  'U').      # Ü => U
            gsub(/Ç/,  'C')       # Ç => C
      end
    end
    

    Agora, basta incluir este módulo na classe String, certo? Sim, porém isto não é tão simples. O método de classe “include” é privado. Uma técnica interessante para burlar este problema é o uso do método “send” em cima do objeto que representa a classe String. Este método não é privado e aceita como argumentos: um método a ser chamado e os parametros a serem passados para este método. Assim, podemos incluir nosso módulo StringExtensions a classe String com o seguinte código:

    String.send :include, StringExtensions

    Para adicionar toda esta lógica à nossa aplicação basta criarmos um arquivo string_extensions.rb na pasta “config/initializers”. Neste arquivos adicionaremos nosso módulo e na última linha o código acima. Quando a aplicação for executada os arquivos “.rb” desta pasta serão executados em ordem alfabética e para toda string de nossa aplicação poderemos chamar o método “no_accent”.

    Esta é uma dica bastante simples porém muito útil. Extender classes pode ser um ótimo começo para um código mais clean, facil de manter e componentizável (imagine que em um próximo projeto RoR você pode reutilizar seus initializers).

    Abraços e até a próxima!

    Algo que eu sempre me esqueço quando vou configurar uma nova máquina são as configurações do ~/.gitconfig. Dentre elas:

    [core]
      excludesfile = /home/daniel/global-gitignore

    Essa configuração faz com que o arquivo /home/daniel/global-gitignore funcione como o .gitignore mas para todos os repositórios git, sendo um adicional ao eventual .gitignore do seu projeto.

    [push]
      default = tracking

    Define que, por default, o comando git push faça push na branch “trackada

    [alias]
      co = checkout
      st = status
      ci = commit

    Aliases essenciais que substituem os git checkout minha-branch por git co minha-branch e etc.

    Nada contra o uso do alert no javascript. Ele sem dúvida ajuda. Mas o Firebug tem uma alternativa interessante.

    Basta habilitar o console do firebug e dento do nosso javascript, escrever :

    console.log("minha mensagem");

    Ainda há a possibilidade de usar cores, através dos comandos console.debug, console.info, console.warn e console.error

    É particulamente útil quando estamos dentro de um loop, e ficar dando click em cada alert às vezes atrapalha.

    Um amigo, bastante engajado na comunidade ágil, me recomendou um artigo muito interessante cujo título é  ”The marriage of Lean, Scrum e XPHow to align Agile Across an Organization“, escrito por Geoffrey Bourne. Abaixo segue um pequeno resumo.

    Nos últimos anos vários “sabores” de métodos/metodologias ágeis surgiram: Scrum, Lean, FDD (Feature Driven Development), AUP (Agile Unified Process),  XP (Extreme Programming) e outros. Estes métodos possuem muitas features semelhantes e diferentes e as empresas começam a se perguntar qual método devem adotar.

    Primeiramente, uma organização deve ser vista em três níveis: O Executivo/(PMO), o Gerenciamento de Projetos e os Desenvolvedores/Entregadores. Um executivo focado na estratégia da empresa irá ficar bastante confuso se você começar a evangelizar sobre as virtudes do Extreme Programming (XP) como integração contínua, refatoração, etc, Estes detalhes são “gregos” para um executivo assim como a discussão sobre orientação por objeto. Entretanto este mesmo executivo ficará bastante interessado se você apontar como aumentar o valor das ações através da eliminação de desperdícios e otimização dos processos na orgazinação (Lean).

    Mas a medida que os processos ágeis amadurecem ainda permanece a questão. Qual método agíl devemos adotar para nossa empresa?  Na opiniao do autor, os diversos níveis de uma organização se alinham  com três métodos específicos: Lean, Scrum e Extreme Programming.

    A organização deve ser compreendida como um todo, ao invés de “partes/divisões” separadas. Deve ser considerada um organismo vivo com suas áreas mutualmente dependentes.

    Cada nível tem metas diferentes (onde querem chegar) e objetivos diferentes (como chegam lá). O Executivo foca no nível estratégico e acionário. O gerente de projetos foca no time e na entrega do produto. O desenvolvedor foca na engenharia e nas entregas das tarefas.  Cada grupo tem apenas uma compreensão superficial dos outros níveis. Quando um desenvolvedor recebe como meta a meta do nível executivo como “Cliente em primeiro lugar: Conquiste a confiança do cliente e aumente seu valor de negócio”, este pode até entender a meta, mas não saberá como agir para atingí-la. O mesmo ocorre quando um desenvolvedor tenta convencer um executivo que devem organizar os diretórios do controle de versão SVN da corporação. Com certeza este executivo vai olhar com cara de “blank” para este desenvolvedor pois a reestruturação do SVN não se aplica as metas e objetivos do executivo. Como Dale Carnegie apontou,  a estrada real para o coração de uma pessoa é falar sobre o que ela mais valoriza.

    Ágil, como declarado no movimento do Manifesto Ágil, é um conjunto de princípios – uma filosofia, muito mais do que um processo passo a passo. Processos pesados como Waterfall (cascata) dominaram o mundo do desenvolvimento de software, mas aos poucos gerentes começaram a adotar a idéia de se fazer “mais”com “menos”. Assim foram surgindo processos mais leves focados na colaboração, comunicação e adaptação. Em 2001, o Manifesto Ágil, cristalizou os conceitos comuns dos processos ágeis – Scrum (1995) e XP (1996) e outros. Assim, conforme mencionado anteriormente os três se complementam:

    Estes três tipos de processos ágeis possuem suas forças unicas mas complementarem entre si.

    Lean – Originou-se na linha de produção da Toyota como uma maneira de eliminar o desperdício, otimizar os processos da organização e focar naquilo que realmente tinha valor para o cliente. O sucesso deste processo levou a inovadores a aplicarem Lean no desenvolvimento de software. Os 7 princípios são:

    • Emilinar desperdício – (remover aquilo que não traz valor para o cliente)
    • Aumentar o aprendizado – (melhorar o desenvolvimento do software através do aprendizado contínuo)
    • Decidir o mais tarde possível – (postergue as decisões até que as “assumptions” se tornem fatos)
    • Entreguar o mais rápido possivel – (resultados entregues mais rápidos, feedbacks mais rápidos)
    • Dar poder de decisão para o time  - (permitir que os trabalhadores da linha de frente tomem a maior parte das decisões)
    • Construir Integridade – (integridade, flexibilidade e eficiência)
    • Ver o Todo – (veja o software como um todo e são como a somatória de várias partes)

    Scrum – uma plataforme que facilita a organização da equipe e a geração de trabalho de alta-qualidade sem sacrificar a produtividade. O nome significa um movimento do jogo rugby cuja idéia é a equipe toda levar a bola até o gol. Como Lean, este processo também se originou no setor da manifatura e depois foi levado para o desenvolvimento de software.Scrum se baseia em:

    • Oraganização do time (Scrum Master, Product Owner e Time de desenvolvimento)
    • Rituais (Reuniões Diárias, Retrospectivas, Reviews)
    • Entregas parciais
    • Time-box (definição do tempo para as entregas e reuniões)
    • Envolvimento do cliente durante todo o processo

    Extreme Programming (XP) – metodologia voltada para programadores que enfatiza práticas técnicas para promover “skillful development” através de entregas frequentes de software funcionais.  As 4 práticas fundamentais de XP são:

    • Comunicação – próximo ao cliente, programação em par e desenvolvimento nas instalações do cliente
    • Simplicidade – Desenho simplificado e codificação do necessário
    • Feedback – Releases pequenos para rápidos feedbacks e TDD (Test-Driven-Development)
    • Coragem – Código coletivo e Refatoração (coragem para mexer naquilo que está funcionando)

    Podemos notar que os três níveis (Executivo, Gerenciamento de Projetos e Desenvolvimento) se alinham muito bem com estes três métodos ágeis. Diferentes visões para diferentes audiências. Lean brilha quando aplicado para aqueles com foco nos valores estratégico, organizacional e acionário, enquanto Scrum brilha para os que tem foco na organização do time e no gerenciamento das entregas do projeto. Extreme Programming brilha quando aplicado aqueles com foco tático e no desenvolvimeto com entregas, conforme diagrama abaixo.

    Adotando estes três processos  (System Thinking – aplicá-los por toda a organização e não em um único nível), aumentamos a chance de adoção, produtividade e sucesso em geral. Talvez em um futuro próximo um único processo ágil nasça para endereçar as necessidades de todos os níveis da empresa, enquanto isto não ocorre, estas idéias podem servir de guia para se adotar Agile em sua organização.


    Recentemente um dos nossos clientes nos relatou uma certa demora em algumas páginas importantes. Observando os relatórios do NewRelic, observei de cara uma query que demorava muito. Não foi difícil entender o motivo. Simplesmente faltava um índice na tabela. Um cuidado básico que nós desenvolvedores deveríamos estar atentos mas que muitas vezes acaba fugindo da nossa atenção. Assim que criei o índice, observei uma rapidez significante.

    Existe um plugin que nos ajuda muito nesta tarefa. É o rails_indexes . Ele dá um olhada na aplicação e sugere a criação de índices que ele julga serem importantes. Para instalá-lo, basta dar

    script/plugin install git://github.com/eladmeidar/rails_indexes.git

    Ele sugere um migração para a criação dos índices com o seguinte comando :

    rake db:index_migration

    O próprio autor do plugin diz que se trata de uma sugestão que deve ser analisada com cuidado pelo desenvolvedor ou pelo DBA, mas ele costuma revelar índices importantes que no calor do desenvolvimento, nós acabamos deixando para trás.

    Algo que eu não dava muita importância nos tempos de projetos para o colégio, é a organização de código, de modo que o código fique mais legível, simples e sem necessidade de muitos comentários.

    Por exemplo, o códgio abaixo:

    conditions = Sql::Conditions.new
    if (value = params.get(:section_id)) then conditions.and('videos.section_id = ?', value) end
    if (value = params.get(:source_id)) then conditions.and('videos.source_id = ?', value) end
    if (value = params.get(:category_id)) then conditions.and('collectible_data.category_id = ?', value) end
    if (value = params.get(:source)) then conditions.and('video_sources.name = ?', value) end
    

    Poderia ser escrito dessa forma:

    conditions = Sql::Conditions.new
    if (value = params.get(:section_id))  then conditions.and('videos.section_id = ?',            value)  end
    if (value = params.get(:source_id))   then conditions.and('videos.source_id = ?',             value)  end
    if (value = params.get(:category_id)) then conditions.and('collectible_data.category_id = ?', value)  end
    if (value = params.get(:source))      then conditions.and('video_sources.name = ?',           value)  end
    

    Qual você acha mais legível? Qual você consegue entender mais rápido?

    Você pode reparar que a diferença não tem nada a ver com a sintaxe nesse caso, e sim com espaçamento e identação do código.

    Pode não parecer muita coisa olhando somente para esse trecho de código, mas você não acredita o que alguns espaços em branco, pulos de linha e caracteres separadores podem fazer!

    Mas de que adianta fazer tudo organizado, de modo legível se outra pessoa de sua equipe escrever de um modo completamente desorganizado ou simplesmente diferente?

    Para isso, antes de começar um projeto, ou até mesmo uma equipe, é necessário definir um padrão de código que todos concordem e gostem. Dessa forma você vai conseguir entender o projeto inteiro de uma forma mais rápida e sem depender que o autor da implementação lhe explique o porquê de ter feito aquilo daquela forma.

    Claro que não podemos deixar de escrever comentários em alguns casos, mas é preferível que se faça um código que seja possível entender simplesmente lendo o código em sí, com nomes de variáveis e de métodos apropriados.

    Um método bem interessante do rails é o returning. Apesar de ser bem simples, ele ajuda a manter seu código mais limpo e mais fácil de entender (depois de pegar costume :P ).
    Funciona mais ou menos assim:

    Dado 2 argumentos, um objeto qualquer (arg1) e um bloco, o método repassa o objeto arg1 como parâmetro do bloco e ao final da execução do bloco, retorna o arg1 que pode ter sofrido alteração ou não.

    Por exemplo, o seguinte método:

    def published_titles(posts)
      titles = {}
    
      posts.each do |p|
        titles.merge!(p.id => p.title) if p.published?
      end
    
      titles
    end
    

    Poderia ser reescrito assim:

    def published_titles(posts)
      returning(Hash.new) do |titles|
        posts.each { |p| titles.merge!(p.id => p.title) if p.published? }
      end
    end
    

    É isso. ;)


    UPDATE
    O Ceolin comentou comigo hoje que o returning seria “deprecated” no Rails 3. Isso é porque a partir do Ruby 1.9, a classe Object ganha um novo método (tap) que permite o desenvolvedor interagir em uma chamada de métodos em cadeia, por exemplo:

    Users
      .all .tap {|users| puts "Usuários: #{users.map(&id)}"}
      .last.tap {|user| puts "Último usuário: #{user.name}"}
      .posts
    

    Então, o nosso primeiro método poderia ser escrito, no Ruby 1.9, assim:

    def published_titles(posts)
      Hash.new.tap do |titles|
        posts.each { |p| titles.merge!(p.id => p.title) if p.published? }
      end
    end
    

    Recentemente nossa equipe trabalhou em um grande projeto web de um cliente líder da área editorial que se tornou um caso de sucesso devido a vários fatores, tais como; a expertise da equipe de desenvolvimento, um ótimo Scrum Master,  mas principalmente  devido a excelente atuação do Product Owner. Nestes nove anos de empresa, nunca havia me deparado com um P.O. tão comprometido e com tanto interesse em ver o projeto se concretizar de forma rápida. O histórico de nossa empresa sempre foi ter P.O.s interessados no início mas que com o passar do tempo deixavam de priorizar o projeto e raramente estavam disponíveis para validar e aceitar as estórias entregues. Muitas vezes ficávamos semanas sem obter feedback para podermos prosseguir com a implementação.

    Neste projeto utilizamos Scrum como método ágil para facilitar o gerenciamento das equipes remotas e nossas dailies se transformaram em micro Reviews tamanho o interesse do P.O. em navegar e validar as estórias implementadas.  Diariamente no mesmo horário, ele entrava em contato com nossa equipe, via conferência, para escutar sobre o trabalho realizado, as dificuldades, os impedimentos, mas principalmente para acessar e experimentar as novas funcionalidades. Houve dias que confesso ter desejado que ele não tivesse entrado em contato devido a excessiva carga de trabalho, mas lá estava ele no telefone “E aí pessoal, podemos começar?” Era inacreditável, todos os dias a mesma frase com o mesmo entusiasmo. Esta proximidade diária foi essencial para o esclarecimento de cada pequena regra de negócio que surgia ao nos aprofundarmos nas estórias e muitas vezes, ao ser questionado sobre determinada regra ouvíamos “Nao havia pensado nisto, mas tarde darei um retorno” e no mais tardar no dia seguinte a dúvida estava esclarecida sem retrabalhos de implementação. Este processo se repetiu por quatro meses até a entrega oficial da aplicação. Saldo final – projeto entregue no prazo (curtíssimo), 0% de retrabalho, funcionalidades utilizadas pelos usuários e apenas alguns pequenos bugs.

    Esta nossa experiência nos mostrou que para garantir o sucesso de um projeto devemos buscar e se for o caso “brigar” por um P.O. comprometido, interessado e que envolva as pessoas responsáveis pela utilização, para que o software entregue esteja plenamente de acordo com as necessidades reais dos usuários e que somente a proximidade do dia a dia pode garantir esta aderência. Apesar de acreditar e aplicar Scrum há vários anos em nossa empresa, às vezes devemos realizar pequenas alterações em seus rituais para fazer com que o P.O. não espere o final da sprint de duas ou três semanas para validar e experimentar as funcionalidades. A substituição de algumas dailies por  micro Reviews nos traz feedbacks mais rápidos, evita retrabalhos e nos antecipa mudanças de rumo.

    Depois de vários anos atuando na área, acredito que não vale a pena seguir em frente com um projeto sem um bom P.O.