Testes de Controller – a Saga

Semana passada comecei finalmente um projeto do zero usando Rails 3.1. A experiência foi novidade para mim, que por causa de uma série de legados (e também por questão de performance) estava preso no Rails 2.3, e não tive a oportunidade de ver como os testes funcionam no Rails 3.

Mas antes de chegar no assunto, vamos rever que o Rails não é puramente MVC. O “Controller” do Rails agrega coisas que deveriam ser feitas na view (basicamente, buscar o objeto para ser exibido). Para mais detalhes, ver meu post anterior.

Por esse motivo, e unicamente por este motivo, eu não acredito ser possível fazer teste unitários de controllers.

Um teste unitário deve, em teoria, testar um pedaço do sistema, isoladamente de outras partes. Como fazer um teste unitário de algo que é, essencialmente, um “glue code”, ou seja, um código que une regras de negócio (Models) e interfaces (Views)?

Antes do Rails 3, eu usava uma abordagem mais “integrada” para esses specs. No controller, eu usava a palavra-chave do rspec-rails “integrate_views”, e testava o par “controller-view”. Os specs ficavam mais ou menos assim:

describe PeopleController do
  integrate_views

it 'should show people on "index"' do
    sessions[:user_id] = Factory(:user).id
    Factory :person, :name => "Foo Bar Baz"
    get :index
    response.should be_success
    response.body.should include("Foo Bar Baz")
  end

it 'should render "new" view if validation failed" do
    sessions[:user_id] = Factory(:user).id
    post :create, :person => { }
    response.should render_template("new")
  end
end

Claramente, isso não é um teste unitário, mas há um grande ganho nessa abordagem: se eu resolver mudar a variável “@users” para “@records”, e atualizar a view, não preciso mexer em nenhum spec. Na prática mesmo, eu não preciso mexer em nenhum SPEC se eu mudar o layout, adicionar mais informações na view, buscar mais registros no controller e atualizá-los na view, enfim, em qualquer momento eu sei, exatamente, se o teste está falhando ou passando, sem as fragilidades que mocks podem oferecer.
(more…)

Model View Controller

Ultimamente, Rails tem se popularizado, e com ele o famoso (e já antigo) MVC. Porém, como todas as coisas, a prática acabou sobrepondo a teoria, então achei que seria interessante falar um pouco sobre MVC, já que parece-me que algumas confusões começaram a acontecer. Esse post é imensamente baseado nesse post do Martin Fowler sobre arquiteturas GUI, então seria interessante ler ele também.

Enfim, vamos lá: no Rails, quando fazemos um “scaffold”, é criada uma combinação de coisas para nós: uma “migration”, que cria uma tabela no banco. Um “model”, que basicamente é o mapeamento dessa tabela para um objeto. Um “controller”, que faz a busca do registro certo e repassa para a renderização da tela. Por exemplo, a ação “edit”:

  def edit
    @foo = Foo.find(params[:id])
    render :action => 'edit' #Isso é redundante, mas deixa explícito um aspecto importante.
  end

Além disso, há uma série de boas-práticas, tais como não concentrar código de regra de negócio no controller, não colocar lógica nas views, enfim. Porém, essas “regra gerais” pecam em um ponto:

Rails não é 100% MVC…
(more…)

Redes Sociais

Bom, dei uma parada sobre os posts mais técnicos, mas estou preparando um sobre alguns estudos que fiz em Scala. Até lá, vou falar de um assunto que ultimamente tem me deixado meio pensativo: redes sociais.

Para os que me conhecem mais a fundo, sabem que eu sou meio “alérgico” a redes sociais. Aderi ao twitter e ao facebook depois que muita gente já estava usando, e não tenho linkedin, nem google buzz ou google+. Só que eu acho que algumas pessoas estão “perdendo o fio” do que é cada rede social. Usei o twitter, sempre, mais como uma forma de me manter atualizado tecnicamente do que para encontrar amigos-afinal, eu não vejo o motivo de ficar trocando mensagens de 140 caracteres com amigos meus (e deixar isso disponibilizado para o mundo). Aliás, cabe aqui uma observação interessante: a língua, o idioma, é absolutamente frágil. Por isso existem tantas formas de dizer algo, de falar ou pronunciar uma palavra, um sentido… por isso o “teste de Turing” ainda não foi vencido, por isso que é tão difícil processar linguagem natural, por isso que existem trocadilhos e poesias-todos, abusando de características da linguagem que podem dar duplo-sentido, dupla-interpretação, etc.

Isso, na linguagem falada. A linguagem escrita é MUITO pior.

Porque, na linguagem escrita, você não tem aspectos simples como o olhar da pessoa, sorrisos, movimento corporal, tom de voz, e às vezes é difícil de dar a entender que uma coisa é sarcasmo quando se está escrevendo (antes, se usava itálico, tipo “Hahaha, claro que eu vou fazer isso!”). E em 140 caracteres, é MUITO mais difícil. Especialmente em português, que é um idioma que notavelmente se escreve demais (“Right click” vs “Clique com o botão esquerdo do mouse” é um exemplo bem notável). Percebo isso no twitter quando eu não gosto de algo e posto lá: pra não ser subentendido, eu preciso escrever mais de 140 caracteres…
(more…)

Ensaio Sobre Graduação

Depois de assistir a palestra do Tenderlove no RubyConfBR (e ficar impressionado porque estava estudando EXATAMENTE os assuntos de Automatos há pouco tempo atrás), vi uns tweets sobre graduação. Na verdade, foi principalmente o tweet do @dannluciano que trouxe uma série de respostas de outros tweets que eu concordo até certo ponto, e discordo de muitos outros pontos.

Proponho uma pergunta: qual é a idéia da graduação, nos tempos como hoje? Explicando, em tempos de Wikipedia, de Google, aonde entra uma graduação? Acho que aqui, temos que separar duas coisas: Faculdade, Universidade, e Colegial Técnico.

Pra maior parte das pessoas (e infelizmente, para nosso país e o mercado de trabalho e governo dele), a graduação é um “upgrade” da formação média, e o “colegial técnico” fica meio perdido nesse meio do caminho… além disso, muitos professores (e infelizmente eu conheço isso, tendo trabalhado numa universidade federal) ainda acham, nos dias da Wikipedia, que são donos do conhecimento, e ninguém chega ao conhecimento sem o intermédio deles.

Os que me acompanham no Twitter devem ter visto que eu prestei o Poscomp. Num dos livros que peguei, havia a seguinte frase:

Função injetora é aquela que, para dois elementos distintos a, a’ ∈ A, f(a) ≠ f(a’)

Uhn… então, eu resolvi ir para a Wikipedia:

Uma função diz-se injectiva (ou injetora) se e somente se quaisquer que sejam x1 e x2 pertencentes ao domínio da função, se x1 é diferente de x2 implica que f(x1) é diferente de f(x2)

Há um “Link” para “domínio”, e há um gráfico mostrando graficamente essa explicação. Não precisa ser um gênio para entender que a explicação da Wikipedia está mais simples e melhor explicada e exemplificada. Ok. Mas, e isso é importante notar, eu não chegaria ao artigo da Wikipedia sem o livro, sem o poscomp, e não teria entendido a palestra do Tenderlove sem ter estudado para o Poscomp (ainda que eu tenha usado os livros como “grandes índices” e a Wikipedia como forma de aprender, propriamente dita).
(more…)

Sou um Anti-Identação

O título desse post parece estranho, mas vamos lá. De fato, eu sou um anti-identação, não gosto de ver meu código identado.

Não estou dizendo que eu não idento meu código-longe disso. Apenas que eu prefiro evitar a identação sempre que for possível. Mas vamos por partes…

Primeira coisa, isso começou há algum tempo quando uma pessoa propôs o seguinte problema: montar uma lista encadeada (Linked List) com as seguintes regras:

1) A lista deve validar se ela está vazia, e lançar um erro caso tente-se retirar um item da lista vazia
2) Cada método pode ter, no máximo, uma linha
3) Não se pode usar “if” em momento algum

Claro que é uma bela loucura, mas depois que eu consegui resolver esse código, pensei: se eu consegui resolver um problema desses com apenas uma linha por método, será que meus códigos não tem coisa demais?

Aí, comecei a experimentar isso em código de produção. Isso meio que criou um estilo de codificar bem interessante, e vou tentar mostrar aqui com alguns exemplos:
(more…)

Orientado a Objetos versus Funcional

Bom, esses dias estava estudando Scala. Uma linguagem multi-paradigma, mas que parece mais “funcional” do que “imperativa”. Scala cai numa posição ainda nebulosa para a maior parte das pessoas (e acho até que para o mercado também). Afinal, imutabilidade é “programação funcional”? Scala não faz nada que impede “side-effects” no código, como Haskell por exemplo, então ela é funcional mesmo?

Como mesmo eu não tenho muitos conhecimentos em linguagens funcionais, resolvi propor um problema para mim mesmo: implementar uma árvore binária em Ruby, e depois portá-la para Scala, tentar uma abordagem imutável em Scala, e depois portar para Haskell. O código está no github, mas algumas coisas vão ser discutidas aqui.

Primeiramente, a árvore imutável é feita recriando a árvore inteira. Claro, não podemos re-criar apenas um nó e apontar, digamos, a referencia de seu pai para esse novo nó, porque o pai é imutável (assim como qualquer outro aspecto do programa).

class Node[A <% Ordered[A]](value: A = None, left: Option[Node[A]] = None, right: Option[Node[A]] = None) {
    def insertNew(newValue: A): Node[A] = value match {
        case v if(newValue < v) => insertLeft(newValue)
        case _ => insertRight(newValue)
    }

    private def insertLeft(newValue: A) = new Node(value, newChild(left, newValue), right)
    private def insertRight(newValue: A) = new Node(value, left, newChild(right, newValue))
    private def newChild(child: Option[Node[A]], newValue: A) = child match {
        case Some(child) => Some(child insertNew newValue)
        case None => Some(new Node(newValue))
    }
}

(more…)

Testando Javascript no Rails

Continuando os estudos com Javascript e Ruby, esses dias tive um problema bem chato: existe uma gem (muito boa, por sinal) para Rails chamada “cells“, que basicamente cria uma camada, semelhante a “mini controllers” para coisas específicas em Rails (tipo “sidebar”, “carrinhos de compra”, “menus” e outras funcionalidades que são, basicamente, fragmentos de “views”, normalmente feitas com a combinação “partials+helpers” mas que ficam relativamente difíceis de testar). Junto com o Cells, foi criado o Apotomo, uma gem para criar “widgets”, e aí que está o problema: testar um widget. Claro, é possível testá-lo com integration test, mas “unit-tests”, quando envolvem Javascript+Rails, envolvem HTML Fixtures, linguagens de teste diferentes, enfim, nada produtivo.

Aí, entrou a gem Johnson. Basicamente, é um interpretador Javascript dentro de Ruby, de forma que seja possível rodar código JS dentro do Ruby (e o resultado vem como uma Ruby String, ou um Numeric, enfim). Já falei sobre isso quando estudei “The Ruby Racer” e os testes com V8 no Ruby, até me interessei pelo “env.js”, porém na época a versão que rodava com Johson estava muito ruim ainda (e infelizmente, ainda está)

Porém, o novo Env.JS (1.3) já roda no Johnson. E está muito melhor.
(more…)

Em Patópolis, Programe como os Patos

Este é um post sobre “Duck Typing”, e finalmente eu escrevi ele (estava enrrolando para fazê-lo). Acho esse post bem importante porque eu percebi, com a experiência em Ruby, que poucas pessoas sabem lidar com o dinamismo da linguagem (e aproveitá-la ao máximo).

Então, vamos falar um pouco sobre Duck Typing. O básico, a maioria já sabe:

def imprimir(objeto)
  print objeto.falar
end

Ou seja, na declaração do método eu não defino nenhuma regra do que aquele objeto pode receber; apenas chamo os métodos que eu o objeto passado como parâmetro deveria implementar, e confio que vai dar certo. Parece simples, e até um pouco inseguro, então tem gente que prefere fazer umas checagens antes (tipo usando objeto.is_a?(Pessoa) ou objeto.respond_to?(:falar)), mas eu acho que isso quebra a idéia de Duck Typing. Para mim, tudo se resume a uma palavra: Protocolo.

(more…)

Regras de Negócio e Rails

Bom, esse post é resultado de uma conversa que tivemos no Grupo de Usuários de Ruby de SP. Mas, antes de entrar no que interessa, vamos divagar um pouco sobre “Model” e “Rails”.

Muitos programadores Rails sabem a regra “Controllers magros, Models gordos”. É interessante também saber um pouco sobre o porque dessa regra, mas antes disso, vamos discorrer sobre o que é o “Model” de Rails, comparando com o “Model” da maior parte dos frameworks Java (lembrando que eu não sou programador Java, se eu falar qualquer besteira, me corrijam).

Pegando por exemplo o Hibernate, normalmente há uma classe que mapeia um objeto para uma tabela, e outra classe que faz as buscas (chamada normalmente de Facade). Então, teríamos um diagrama como: JDBC -> Model -> Facade. Já no caso do Rails, o mapeador ActiveRecord já abstrai a parte de “ter que mapear um objeto para uma tabela”, e também já nos oferece formas de buscar esses registros. Resultado, que o “Model” do Rails é meio que uma junção de “Model” e “Facade” do Java, e isso sozinho. Parece então óbvio que regras de negócio vão para ele, não é? Senão, qual o uso de uma classe vazia?

Bom, minha abordagem não é bem essa. E para isso, eu uso o princípio das CRC Cards, da metodologia XP.
(more…)

AgileBrazil 2011 – parte 3

Por fim, essa parte é sobre Fortaleza. É um post nada técnico, mas acho que vale a pena comentar.

Fortaleza, logo nos primeiros dias, mostrou a minha insanidade. Sinceramente. Escancarou a insanidade que é viver em São Paulo, nessa selva de pedra, completamente desumana. Para começar, logo no primeiro dia, o taxista conversando conosco (às 0h), e, do nada, vê que passou o hotel e resolve dar ré… numa avenida. E tudo bem, um outro carro passou por ele como se nada tivesse acontecido.

A população tem um olhar mais vivo por lá. Os passos são sadios, calmos, não apressados e ansiosos como em São Paulo. Aliás, as pessoas olham para você. Parece bobo, e de fato é, mas tente andar na Paulista e impressione-se em ver como as pessoas não fazem contato visual. Nem na Berrini, ou qualquer um desses “centros comerciais” de São Paulo.

Mercado, e as pessoas comentando: “o quê, você vai embora às sete?”. Detalhe, o mercado fecha oficialmente às sete mas, seis e meia, o pessoal já está arrumando as coisas, afinal o mercado fecha às sete, não às oito ou “até o último cliente”.
(more…)