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.