Go to English Blog

Method Chaining e estilo de código

Leia em 2 minutos

Estilo de código é um assunto extremamente subjetivo. E, para tornar as discussões ainda mais calorosas, é afetada por toda nossa experiência com outras linguagens e preferências pessoais. E aqui vai o meu estilo de código para method chaining que uso no Ruby e JavaScript.

O que é method chaining

Method chaining nada mais é que o nome dado às chamadas de método sequenciais, que normalmente atua no resultado do método anterior. É uma das técnicas usadas para se criar interfaces fluentes.

Para criar uma interface fluente usando method chaining você precisa sempre retornar um objeto. Este objeto pode ser o próprio objeto que iniciou as chamadas, ou se um novo objeto.

Imagine, por exemplo, que vamos criar uma classe para envio de e-mails.

class Mail
  attr_accessor :subject, :to, :from, :body

  def deliver
    # deliver e-mail
  end
end

Para enviar um email, temos que instanciar a classe e definir cada uma das propriedades do objeto receptor e, finalmente, executar o método Mail#deliver.

mail = Mail.new
mail.subject = 'Lunch'
mail.from = 'john@example.org'
mail.to = 'mary@example.org'
mail.body = 'Hi there, Mary! Wanna grab some lunch?'
mail.deliver

E como seria possível criar uma interface fluente para esse mesmo exemplo? A maneira mais simples seria criar métodos que retornam o próprio contexto self.

class Mail
  def subject(subject)
    @subject = subject
    self
  end

  def from(from)
    @from = from
    self
  end

  def to(to)
    @to = to
    self
  end

  def body(body)
    @body = body
    self
  end

  def deliver
    # deliver e-mail
    self
  end
end

Sim, ficou mais verboso. Nós poderíamos automatizar a definição de métodos com metaprogramação, mas esse não é o objetivo deste artigo, então vamos continuar como estamos.

Perceba que cada um dos métodos retorna self. Assim, podemos chamar sequencialmente os métodos até enviar a mensagem… o que nos leva o estilo de código que quero mostrar neste artigo!

Estilo de código no Ruby

Method chaining fica extremamente difícil de ler quando muitos métodos são chamados em uma única linha.

mail = Mail.new.subject('Hello').from('john@example.org').to('mary@example.org').body('Lunch').deliver

Em vez de fazer isso, no Ruby você pode quebrar as chamadas em múltiplas linhas.

mail = Mail.new.
  subject('Hello').
  from('john@example.org').
  to('mary@example.org').
  body('Lunch').
  deliver

Perceba que cada chamada de método é terminada com um . no fim da linha, com exceção da última chamada de método. Um dos problemas desse estilo de código é que se o método Mail#deliver precisar ser executado antes, você terá que se lembrar de adicionar o . no fim de sua linha e, normalmente, esquecemos de fazer isso na primeira vez que rodamos o código.

Até o Ruby 1.8 essa era a única forma possível de fazer method chaining. Mas desde o Ruby 1.9 você também pode adicionar o ponto no começo da linha, o que acho que torna o código mais fácil de ler e menos propenso a erros.

mail = Mail.new
  .subject('Hello')
  .from('john@example.org')
  .to('mary@example.org')
  .body('Lunch')
  .deliver

Note também que a ordem das linhas pode ser trocada sem que você precise mexer em nada. Outra vantagem é que você também pode comentar cada uma das linhas sem se preocupar com a cadeia (ou se ela está sendo quebrada em alguma das chamadas).

Mas quão comum é este tipo de código? No Ruby/Rails eu uso isso frequentemente em arrays (enumerators) e construções de queries SQL com ActiveRecord/Arel, mas devo usar eu outros casos também. E essa regra também se aplica ao JavaScript e, principalmente, no jQuery!

Estilo de código no JavaScript

O jQuery, que é de longe a biblioteca que mais uso de JavaScript, também tem uma interface fluente. E assim como no Ruby, você também pode usar cada chamada de método em sua própria linha, inclusive com o . no começo da linha.

$("#test")
  .text("Hello, world!")
  .removeClass("blue")
  .addClass("bold")
  .css("color", "blue")
;

No caso do JavaScript eu ainda tenho o costume de adicionar o ; na mesma linha de indentação da linha que originou a cascata de métodos.