O Estado da arte da DSL em Ruby

Estive na apresentação de Glenn Vanderburg, no QCon London 2009, que falou sobre o Estado da Arte da DSL em Ruby. A apresentação e os slides você pode conferir aqui no site da infoq.

A idéia de fazer uso de uma DSL interna originou-se aparentemente no Lisp. Em Lisp você não escreve seu programa apenas direcionado na linguagem, você também constrói a linguagem em cima do seu programa:


(task “warn if websites is not alive ”
  every 3 seconds
  starting now
  when ( not (website-alive? “http://example.org”))
  then (notify “admin@example.org”, “server down!”))
)

DSL interna também foi um objetivo de design do Haskell


keepleft (p :>: ps)
  | keepleft p = case partitionFL keepleft ps of
    a :> b -> p:>: a :>: b
  | otherwise = case commuteWhatWeCanFL (p :> ps) of
    a :> p’ :> b -> case partitionFL keepleft a of
      a’ :> b’ -> a’ :> b’ +>+ p’ :>: b

Agora falando em Ruby, uma das principais características da linguagem é a expressividade. O japonês Yukihiro Matsumoto (Matz), criador da linguagem, sempre teve como objetivo fazer o ruby extremamente legível. Para atingir esse objetivo a linguagem tem o recurso conhecido como “Sintax Sugar”. A performance da linguagem não foi o objetivo inicial, e sim a clareza. Por isso o ruby é uma linguagem mais lenta. Entretanto agora com a adoção maior nos projetos de mercado direcionados a web, a preocupação com performance cresceu e o resultado disso foi o recente release da versão 1.9.1 do ruby, com resultados impressionantes de performance.

Deixando a performance de lado e voltando à DSL, em um projeto Rails você pode fazer as seguintes associações em uma classe model:

has_many :favorites, :conditions => {:state => ‘public’}

has_many :roles, :through => :projects, :uniq => true

validates_length_of :login, :within => 3..40, on => :create

validates_presence_of :authority, :if => :in_leadership_role, :message => “must be authorized for leadership”

Fica claro e limpo que o modelo tem uma associação a duas coleções (favorites e roles), e validações ficam explícitas no próprio model. Outro exemplo usado na apresentação citada acima:

#Um intervalo de tempo:

3.years + 13.days + 2.hours

# Quatro meses de agora, na segunda_feira

4.months.from_now.next_week.monday

Muita coisa é possível fazer no ruby por causa do “method_missing” que existe nos objetos. Por exemplo, você pode sobrescrever esse método e incluir um código como esse:


def element(element_name, opts={})
  write “<#{element_name}#{encode_opts(opts)}”
  if block_given?
    puts ”>#{yield}”

  else
    puts “/>”
  end
end

E o resultado disso pode ser fazer uma manipulação simples de html:

xml.html {
  xml.head{
    xml.title(“History”)
  }
  xml.body{
    xml.h1(“Header”)
    xml.p(“paragraph”)
  }
}
Outro exemplo que eu adoro é o uso de Active Record  do Rails. Graças ao “method_missing” podemos fazer uso de métodos que não existem, como por exemplo:

Funcionario.find_by_nome_and_cargo( "Fulano", "Gerente")

E ainda fazer uso de Named Scopes:
Funcionario.gerente.pelo_nome

Na linha acima o Active Record vai trazer todos gerentes ordenados pelo nome.

Ruby é uma linguagem muito boa para escrever DSL internas por ser uma linguagem não-obstrusiva e permite que muitas pontuações sejam opcionais. Porém, DSL não faz o seu software magicamente melhor e devem ser usados com precauções. Nem sempre o código fica mais limpo com esse uso.
Glenn fala sobre a complexidade do software e a indicação do famoso livro de DDD do Eric Evans, e do livro The Mythical Man-Month.

Um bom design de software:
  • Elimine tudo que possível da complexidade acidental
  • Separe o resto

Outras frases muito interessantes dessa apresentação:

  • Linguagens são para pessoas entenderem o domínio
  • Coisas que são implícitas na verdade são complexidades acidentais
  • Aprender a linguagem ajuda a entender o domínio

Um bom design de API:

  • Criar uma DSL para determinada construção é poderoso
  • Você pode refatorar ela quando achar duplicação, complexidade, etc
  • DSL interna é apenas uma parte do bom design da API no Ruby



Publicado em linguagens, QCon, rails. Tags: , . Leave a Comment »

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s

%d blogueiros gostam disto: