Keep Coding

Claudia Farias

Feb 13, 2014

Evitando COUNT(*) queries com ActiveRecord::CounterCache

Gravar a informação do tamanho de um relacionamento na tabela é até uma solução trivial para evitar consultas com COUNT e o ActiveRecord traz um recurso para esta simples estratégia. Sem questionar o mérito dessa solução, vou me limitar a dizer que podemos economizar ai uns... 10 centavos em queries, alguns SELECT COUNT(*) whatever a menos no log.

Em associações belongs_to existe a opção :counter_cache trata "pode encontrar o número de objetos pertencentes de forma mais eficiente", guardando e controlando o número de associações relacionadas.

Considere a implementação:

class Topic < ActiveRecord::Base

    belongs_to :subject, counter_cache: true

end

e

class Subject < ActiveRecord::Base

    has_many :topics

end

O counter cache precisa armazenar o número, assim adicionamos o campo, seguindo a convenção [association]_counter, ao objeto a que ela pertence:

class AddTopicsCountToSubject < ActiveRecord::Migration
    def up
        add_column :subjects, :topics_count, :integer, default: 0

        Subject.all.pluck(:id).each do |result|
            Subject.reset_counters(result, :topics)
        end
    end

    def down
        remove_column :subjects, :topics_count
    end
end

Quando uma associação é incluída ou removida, o ActiveRecord::CounterCache dispara métodos como increment_counter e decrement_counter para atualizar o campo. Na migration, reset_counters, bem.. parece óbvio aqui.

No console conseguimos notar uma sutil melhora de performance na chamada do método .size (o método .count sempre executa SELECT COUNT(*)).

Sem o counter_cache:

> Subject.first.topics.size
    Subject Load (0.2ms)  SELECT "subjects".* FROM "subjects" ORDER BY "subjects"."id" ASC LIMIT 1
    (2.3ms)  SELECT COUNT(*) FROM "topics" WHERE "topics"."subject_id" = ?  [["subject_id", 1]]
=> 9

Com o counter_cache ele consulta diretamente pelo campo:

Subject.first.topics.size
    Subject Load (0.1ms)  SELECT "subjects".* FROM "subjects" ORDER BY "subjects"."id" ASC LIMIT 1
=> 9

Quando precisamos contar o número de vários relacionamentos, essas consultas saem bem mais caras que 10 centavos e toda ajuda aqui é bem vinda.

Nov 6, 2013

Sample Blog with NodeJS and EmberJS

I dedicated myself to learn about EmberJS and I started a new application: a sample blog with NodeJS and Moongose. If I liked Ember? No. Ember confuses me too. I couldn't use all features, so I'm still team AngularJS.

NodeJam

Live on getup.

Find the code on my github and feel free to collaborate, improve it, refactor and solve issues. I'll keep learning, so I hope for help.

Sep 24, 2013

Rails Dia-a-Dia #4

Esta série bem poderia ser chamada 'Rails mês-a-mês' para fazer jus a frequência de posts. Estou deixando muitas dicas passarem, mas tenha blogar com três projetos! Vamos lá.

warn

Antes de remover definitivamente um método, com cobertura de testes ou não, podemos ir refatorando gradualmente o código até termos a certeza de que ele poderá ser expurgado do seu código com o build verde. Aplicando um warn ao método, lembramos que ele, em breve, não estará mais disponível.

def your_method
    warn 'message says: this will be deprecated'
    ... 
end

api

Jun 13, 2013

[Fragmento #1] O Codificador Limpo

Programar é um ato de criação. Quando escrevemos um código estamos criando algo do nada. Estamos impondo ordem sobre o caos de uma forma ousada. Estamos ordenando confiantemente, com detalhes precisos, os comportamentos de uma máquina que podeira, de outra forma, causar um prejuízo incalculável. Assim, programar é um ato de suprema arrogância.

Trecho de O Codificador Limpo, de Robert C. Martin. página 22.

Jun 6, 2013

Rails e Concerns

Acontece o tempo todo.

Grandes projetos podem também trazer grandes dores de cabeça. A cada sprint de desenvolvimento, as ideias vão mudando e alterando o código, decisões são revertidas, você descobre algo que não havia previsto ou outra coisa que não era bem como você estava pensando. Ok. Nesse cenário nosso código adquire complexidades difíceis de manter, mesmo com uma boa cobertura de testes. Eu queria ter certeza de que estamos nos valendo de todas os recursos disponíveis para melhorar nosso código nesse sentido, deixando-o mais reusável, redondo e sem brechas.

Concerns

A primeira intenção do Concern é remover duplicidade de código, e junto a isso, ele nos inclina a separar lógica e dados e qualquer dependência que esteja fora do domínio ou que não seja de responsabilidade dos modelos. Concerns podem ser implementados para modelos e controlers (app/models/concerns e app/controllers/concerns). No Rails 3 precisamos criar os diretórios, então incluí-los no application.rb para serem carregados. No Rails 4, isso será padrão e nenhuma configuração precisará ser feita.

config.autoload_paths += %W(#{config.root}/app/models/concerns)

Implementamos um Concern criando um módulo que estende ActiveSupport::Concern. Colocando a responsabilidade em um Concern, desacoplamos um trecho de código que pode ser reutilizado em outros modelos. Podemos adicionar métodos de classe ao modelo adicionando-os no módulo ClassMethods, e tudo dentro do bloco included será incluído na classe que a utiliza também. Removemos o código duplicado e adicionamos a um Concern com esta estrutura:

module OptimusPrime
    extend ActiveSupport::Concern

    included do
        # validates, scopes, relations, etc
        # tudo dentro deste bloco será incluído a classe
    end

    module ClassMethod
        # metodos de classe
    end

    # outros metodos
end

Feito isto, um include do Concern nas classes resolvem nosso problema com o DRY.

class class User < ActiveRecord::Base
    include OptimusPrime
    ...
end

Here Be Dragons


O uso de Concern as vezes é criticado porque um outra abordagem é tentar fazer 'remendos' com implementações específicas para um domínio, onde os concerns poderiam ficar em app/models/{any}/optimus_prime.rb, por exemplo. Esse tipo de implementação tem um risco: pode não passar de uma maquiagem no seu código. Mas ainda para esse disfarce funcionar, você precisa se certificar que está extraindo métodos que fazem sentido estar em um Concern e que façam sentido entre sí, que pertençam ao mesmo domínio. Extrair código para um outro arquivo também é bem chato de manter, mas torna seu código um pouco melhor.

O Bryan do CodeClimate, acredita que Concerns deixam a aplicação gorda, mas gordura de código é aquele trecho legado, em desuso ou que ficou depreciado e precisa ser queimado. Concerns são reusáveis, e estão no Rails para serem usados, e quando bem aplicados, até emagrece.

O Ryan (RailsCast) também não é muito fã de módulos em geral e listou os contras em um gist. São pontos interessantes discutíveis.

Achei que ia conseguir entrar em Service Objects, mas fica para o próximo post.

Referências
http://37signals.com/svn/posts/3372-put-chubby-models-on-a-diet-with-concerns
http://api.rubyonrails.org/classes/ActiveSupport/Concern.html
http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/
http://joshsymonds.com/blog/2012/07/01/rails-concerns-i-starting-with-redcarpet/

Apr 19, 2013

GenghisApp

Encontrei, há alguns meses, uma forma bacana de gerenciar documentos MongoDB, trata-se do Genghisapp. Ele serve uma pequena web app de admin, rodando local ou integrando com Rails, e pode acessar bancos remotos.

Minha aplicação dele, além de administrar meu banco mongo local, é acessar um banco de uma aplicação hospedada no Heroku com o addon MongoLab. Realmente fácil.

Genghisapp

Apr 15, 2013

Foster

Tenho dedicado um tempo, nas minhas horas vagas, em tentar aprender NodeJS, e desse estudo surgiu o Foster, outra aplicação simples que compartilha links com um tipo de curadoria voltado para área de desenvolvimento. A ideia foi totalmente inspirada no Hacker News, mas com um porém, a saber, não necessitar obrigatoriamente de autenticação.

Ainda que simples, implementar o Foster me permitiu estudar e aplicar, além do Node e Express, outros vários recursos, como por exemplo, Backbone, Mongo com Mongoose, Socket.IO, SSE do HTML5, SugarJS, Heroku Scheduler, e outras coisas que acabaram não entrando, como o GruntJS. Agora o plano é fazer um redesign, mas também sem muita pressa e começar a estudar Titanium seguindo a mesma ideia.

É isso, tem um outro post sobre o Foster no Blog do Sorta. Try Foster! Sigam o @FosterTrends no Twitter ou assine o RSS.

Bônus

Duas ferramentas que eu conheci durante os estudos:

Genghis: Um view de admin para MongoDB.
Nodefly: Monitora aplicações Node.

Té mais!

Mar 6, 2013

Aplicações Gordas

O desenvolvedor geralmente é um cara preguiçoso, mas isso nem sempre é algo ruim. Costumamos automatizar soluções para os nosso próprios problemas criando ferramentas verdadeiramente fantásticas.

Pelo mesmo motivo (preguiça), e claro, sabiamente tentando não reinventar a roda, nos valemos de 'plugins' que oferecem recursos poderosos prontos. Genial. O problema: frequentemente acontece que precisamos de uma funcionalidade específica e para isso utilizamos alguma ferramenta que vai muito além do que, de fato, precisamos, cheios de bruxarias e malabarismos.

Meu foco a partir daqui são aplicações Rails.

gem 'bigmac'

O Rails sozinho oferece vários recursos que nem sempre precisamos ou que sequer sabemos que existem. Aliado a isso, nosso Gemfile está cheia daquelas gems com +100 features, mas que na real, você só precisa e usa uma ou duas. Estes recursos não utilizados dentro da aplicação, não passam de lixo ou gordura.

Muitas vezes abusar das gems adiciona uma camada de complexidade que não queremos. No final do seu projeto você vai se sentir como se estivesse em um jogo de Jenga.

Além de trazer uma camada de complexidade, ainda causa uma dependência indesejável. Pense assim: um projeto fica orfão cada vez que uma gem fica depreciada. Cada vez que um projeto fica orfão, morre um koala na Austrália.

Desenvolvedores, além de preguiçosos, conseguem ser extremamente vaidosos com seu código. Exitem gems com finalidade meramente estética. Esse senso de estética do programador também pode comprometer a performace da aplicação. Bonitinho, mas gagueja na resposta.

A Dieta

Não sabemos mais escrever métodos?

Parece exagerado, mas é para gerar reflexão. O que estamos tentando ganhar em tempo, podemos está perdendo em desempenho. Considere se você consegue algum ganho de performance escrevendo suas próprias bibliotecas, em alguns casos. Adicionar uma linha ao Gemfile para resolver um problema de simples resolução, ainda que rico em calorias, é tentador. Sem dúvida, rápido, objetivo ou não.

Aqui vale ponderar sobre a necessidade de plugar uma gem a mais na sua aplicação. Quando é meramente estética, ou quando decidimos com a pressão do prazo estourando, ou estamos com pura e violenta preguiça? Acrescente o fato de que você pode estar perdendo uma puta oportunidade de conhecer e praticar mais sobre vários conceitos bacanas. O quão é relevante manter um regime on rails?

Mar 4, 2013

Métricas do Code Climate

Code Climate é uma ferramenta de análise de código ruby que ajuda a melhorar a qualidade do nosso código. Ele identifica métodos longos e complexos, classes com alto nível de complexidade e blocos duplicados e chama isso de 'Smells'.

Cada projeto no Code Climate recebe uma pontuação média ponderada (GPA) que vai de 0 a 4.0 e aplica uma pontuação e classificação a sua classe que vai de A a F.

CodeClimateScreenShot

O Code Climate utiliza a gema de métricas Flog, uma variante da métrica ABC. A métrica ABC (Atribuições, Branchs e Condições) calcula o número de atribuições, ramificações sem escopo e condições de um trecho de código, ou seja, apenas diz - 'Escreva métodos menores, essa condicional pode ser melhorada? Tente ser mais preciso, e menos verboso no seu código'.

Além de medir complexidade, o Code Climate procura por duplicações e trechos de códigos semelhantes, se baseando no Flay. E medidas de churn e gráficos. Just DRY!

Todos esses trechos de códigos complexos indicam que talvez seu código precise ser refatorado. Mas, claro, aqui vale o julgamento do desenvolvedor. Eu tenho uma disputa bem bacana com o Code Climate para melhorar meu código a cada commit. Somos desenvolvedores tentando fazer um bom código, certo? Podemos nos valer dessas ferramentas na tentativa de fazê-lo bem. Além de tudo, Code Climate é bonitão e ajuda na integração contínua. Uma ferramenta para ser ouvida.

O Code Climate apenas aceita projetos do Github e é free para open source. Plug and Play.