Blog do Urubatan
msgbartop
Desenvolvedor, Palestrante, Escritor, Nerd Assumido e Pai do Marcus :D
msgbarbottom

17 Sep 07 Estendendo o Ruby com DSL (Domain Specific Languages – Linguagens Especificas de Domínio)

O Marcus Sá, acabou de ganhar o livro Desenvolvendo Aplicações com UML por escrever este tutorial:

DLS é uma maneira simular no ruby outra linguagem. Ou seja, uma sintaxe diferente para um problema em mente…

Por exemplo, digamos que existe algo que você faz diversas vezes… Como uma espécie de mapa… Eu desenvolvi esse código para o curso que estou fazendo na e – Genial, que por sinal está ótimo… Ai vai uma breve descrição…

Farei um mapa para chegar até a minha casa…

Mapa Minha Casa

- “caminho “Virar a direita”,” no Posto “
- caminho “Seguir reto”,” ate o Campo do Barnabé “
- caminho “Virar a esquerda”,” na Madeireira “
- distancia “quatro Kilometros”
- tempo “30 minutos”

Achei bem legal o tutorial dele, eu apenas faria algumas modificações no exemplo, mais ou menos assim:

class Mapa
	#Inicialização da classe, recebe o nome do mapa e um bloco com os dados dele
	def initialize(nome, &bloco)
		#Atribui o nome do mapa
		@nome = nome
		#Atribui os dados do mapa
		@dados = {
			#Note que poderemos ter mais de uma instrução, estão criaremos um Hash
			:instrucao => {},
			# Os demais campos do bloco dados serão campos normais
			:distancia => nil,
			:tempo => nil
		}
		#Invoca o bloco como se o mesmo fosse parte de um instancia de objeto
		instance_eval(&bloco)
	end

	def virar(direcao,onde)
		caminho("virar a #{direcao}"," n(o/a) #{onde}")
	end

	def seguir(opcoes = {})
		if opcoes[:ate]
			caminho "seguir", "até #{opcoes[:ate]}"
		elsif opcoes[:por]
			caminho "seguir", "por #{opcoes[:por]}"
		end
	end

	# Atribui os dados
	def caminho(acao, instrucao)
		@dados[:instrucao][acao] = instrucao
	end

	def distancia(distanciakm)
		@dados[:distancia] = distanciakm
	end

	def tempo(tempomin)
		@dados[:tempo] = tempomin
	end

	# Exibição dos dados
	def to_s
		resultado = ""
		resultado << "Mapa #{@nome}\nCaminho:\n"
		@dados[:instrucao].each do |ordem|
			resultado << "\t - #{ordem}\n"
		end
		resultado << "Distancia: #{@dados[:distancia]}\n"
		resultado << "Tempo: #{@dados[:tempo]}\n"
		resultado
	end
end

# Instancia a classe Mapa
def mapa(nome, &bloco)
	Mapa.new(nome, &bloco)
end

# Monta o mapa "Minha Casa"
m = mapa "Minha Casa" do
	virar :direita, "no posto"
	seguir :ate => "o campo grande"
	virar :esquerda, "madeireira"
	seguir :por => "aproximadamente 15 kilometros"
	virar :direita, "frente do bar do zé"
	distancia "20 Kilometros"
	tempo "30 minutos"
	# Mostra o conteúdo da string resultado que é retorno de to_s
	puts to_s
end

Percebam os métodos especializados novos que foram adicionados …
A idéia de uma DLS é que seja possível explicar facilmente utilizando jargões do domínio ao qual aquela DSL se aplica, por exemplo, para melhorar mais ainda este exemplo a utilização dele teria que ser mais ou menos assim:

# Monta o mapa "Minha Casa"
m = mapa "Minha Casa" do
	virar :direita, "posto", 500.metros
	seguir :ate => "o campo grande", :por => 200.metros
	virar :esquerda, "madeireira"
	seguir :por => 15.kilometros
	virar :direita, "frente do bar do zé"
	# Mostra o conteúdo da string resultado que é retorno de to_s
	puts to_s
end

Neste caso fora as referencias a locais, todo o resto seriam comandos da linguagem especifica para montagem de mapas, mas fora esta pequena alteração no exemplo, o tutorial ficou muito bom, o livro vai ser entregue na sexta feira no encontro dos nerds de RoR aqui de porto alegre :D

PS.: Espero que o Shoes veja isto aqui e diga que eu to falando besteira, assim eu aprendo um pouco mais sobre DSL :D

PS2.: Este foi o primeiro vou deixar assim, mas se vocês prestarem atenção, os tutoriais escritos para ganhar o livro, são para serem postados aqui neste blog, e não no do autor :D


O melhor curso de Ruby On Rails de porto alegre começa dia 24, ainda da tempo de se inscrever

If you enjoyed this post, make sure you subscribe to my RSS feed!

Tags:

Reader's Comments

  1. |

    Opa, olha só, o primeiro vencedor fui eu! E o meu vai sair 100% de graça!!!!!

    Reply to this comment
  2. |

    As alterações ficaram bem legais. Como rule of thumb tudo que não variar além de um intervalo deve ser ‘tokenizado’ (transformado em algo como os simbolos que você utilizou). Minhas DSLs estão muito baseadas em Strings e isso está me imcomodando bastante.

    Outro ponto foi o que comentei no blog do Marcus sobre evitar instance_eval para não perder as closures.

    []s

    Reply to this comment
  3. |

    eu pensei em remover o instance_eval, mas a única forma que consegui fazer isto sem utilizar módulos para declarar os métodos foi passando self como parâmetro para a closure, ai em vez de poder escrever: virar eu teria que escrever m.virar …
    Claro que isto apenas para este exemplo, concordo que usando o instance_eval, integrar isto com um sistema de verdade seria quase impossível :D

    Reply to this comment
  4. |

    Parabens pelo livro Marcus!

    “A idéia de uma DLS é que seja possível explicar facilmente utilizando jargões do domínio ao qual aquela DSL se aplica”

    Acho que isso está mais para uma Business Natural Language (BNL http://blog.jayfields.com/2006/11/bnl-common-pieces.html). Uma DLS é apenas uma linguagem focada em resolver um problema se ela vai usar ou não jargões é outra historia! =D

    Tem um exemplo legal de uma DSL que fiz aqui:
    http://forum.rubyonbr.org/forums/14/topics/698

    []s

    Reply to this comment
  5. |

    Daniel, não concordo muito com o que tu escreveu …
    Vamos seguir com o teu exemplo …
    Os jargões para controlar o winamp neste caso são, play, stop, pause que é exatamente o que tu esta usando …
    Agora se tu fosse seguir o exemplo original do Marcus, seria algo do tipo:
    comando “play”
    comando “stop”
    neste segundo caso eu ja não concordo que isto fosse uma DSL, acho que o que gerou a confusão foi a palavra “jargão” …
    Uma DSL tem que ser especifica e não genérica como o próprio nome diz :D

    Reply to this comment
  6. |

    Atenção pessoal.. um site de Portugal está pagando em euros(quase 3x mais q em reais) pra quem estiver disposto a:

    * Ler anúncios
    * Visitar sites
    * Clicar em banners
    * Navegar na NET
    * Ler e-mails
    http://www.publipt.com/pages/index.php?refid=kennedypeixoto

    Reply to this comment
  7. |

    É realmente jargões ai foi uma pegadinha. hehehe!
    Mas será que o unico jeito de deixar uma linguagem especifica ao dominio é usando “jargões”? ;D

    Se eu tiver uma linguagem prontinha para um dominio que resolve varios problemas nesse dominio e por exemplo for para realidade de outra cultura em que os jargões sejam outros mas os problemas continuam iguais. Será que essa linguagem é especifica ao dominio nesse caso? =O

    Reply to this comment
  8. |

    Daniel, pelo menos pelo o que eu entendo por DSL, ela tem que fazer sentido para quem esta utilizando, por tanto uma DSL é especifica, sendo assim, uma DSL para envio de e-mail escrita em portugues, para um usuário que não fala portugues não é uma DSL pois aquelas palavras não fazem sentido algum …

    Lógico que este conceito pode estar errado :D

    Reply to this comment

Leave a Comment