Entre para a LISTA VIP da Black Friday

00

DIAS

00

HORAS

00

MIN

00

SEG

Clique para saber mais

Domain Specific Languages em ação

Domain Specific Languages em ação
peas
peas

Compartilhe

Em diversos momentos sentimos a necessidade de utilizar uma linguagem para atacar um problema mais específico. Utilizar Java ou C# nesse tipo de problema pode gerar uma enorme quantidade desnecessária de código. Veja um exemplo que passamos na Caelum:

 Set<Strategy> strategies = new HashSet<Strategy>(); Indicator<Double> close = new ClosePriceIndicator(timeSeries); for (int i = 1; i <= 50; i++) { Indicator<Double> tracker = new EMAIndicator(close, i); Strategy strategy = new IndicatorCrossedIndicatorStrategy(close, tracker); strategies.add(strategy); } 

No nosso caso, esse trecho de código deve ser compreensível para analistas de negócio, que não são necessariamente programadores, muito menos possuem conhecimento de Java. Domain Specific Languages é o nome dado a prática de se criar pequenas linguagens para resolver um problemas bem específicos. Elas existem em dois sabores: as externas, que criam uma linguagem própria, e as internas, que na verdade utilizam um subconjunto de instruções de um linguagem já existente e utilizada no sistema.

Banner da promoção da black friday, com os dizeres: A Black Friday Alura está chegando. Faça parte da Lista VIP, receba o maior desconto do ano em primeira mão e garanta bônus exclusivos. Quero ser VIP

Entre alguns clássicos exemplos de DSLs internas temos o uso da Criteria do hibernate, o uso do ruby nos arquivos de build do rake. Entre as DSL externas, temos as macros do excel e o xml do ant.

Utilizando a api de scripting do java 6, passamos a usar ruby (através da JRuby) para escrever essa parte da lógica de negócios, e nosso código em java ficou assim:

 (1..50).collect{|x| Tail::IndicatorCrossedIndicatorStrategy.new(close, Tail::EMAIndicator.new(close, x)) } 

Criando algumas factories, conseguimos chegar a um código muito mais simples:

 (1..50).collect{|x| cross(close, ema(x)) } 

Logo, estamos próximos de chegar a algo parecido com uma linguagem natural:

 x de 1 a 50 quando cruzar (fechamento, ema(x)) 

Para tal, uma das possibilidades seria usar um dos compiladores de compiladores existentes para Java, porém isso daria muito trabalho.

O Rodrigo Kumpera sugeriu escrever o próprio parser, como fez o Gilad Bracha no Small Talk. Tanto o Rodrigo quanto o Renato Lucindo citaram o spirit++, que faz isso para C++. Uma pena não existir algo equivalente para o Java.

Phillip Calçado recomendou fazer um teste para saber se devemos ou não melhorar ainda mais essa DSL. O teste consiste em colocar a linguagem natural ao lado da DSL ruby e ver se o especialista consegue fazer a ponte entre uma e outra. Exemplo:

 (1..50).collect{|x| cross(close, ema(x)) } 
 x de 1 a 50 quando cruzar (fechamento, ema(x)) 

Se o especialista no domínio não entender a semelhança entre os dois códigos, é necessário aprimorar a DSL em questão.

Veja outros artigos sobre Programação