*DSL ==> *é uma linguagem (mini liguagem) projetada para um tipo especifico de tarefa, isto é justamente o contrário de linguagens para proposito geral como Java, C ou C#.
*Fluent Interface (Interface Fluente)* ==> objeto que é capaz de deixar as suas responsabilidades mais expressivas a linguagem. (:S confuso, mas o exemplo ajudará)
Para se aprender algo nada melhor do que exemplos./ (aprender com exemplos não dá sono de acordo com Fowler, eu acho que ele está certo)/
Irei apresentar aqui dois exemplos: um simples e outro mais interessante.
*Exemplo Simples*
Supondo que tenho um objeto que representa o conceito Carro.
public class Carro{
private String nome;
private String marca;
private int portas;
public Carro(){
}
// métodos de acesso as propriedades encapsulados...
}
Quando fossemos "usar" esse objeto fariamos...
//***
Carro fusca = new Carro();
fusca.setNome("fusca");
fusca.setMarca("VW");
fusca.setPortas(2);
//***
Tentando aplicar o conceito de Interface Fluente, definiriamos uma Interface
public interface ICarro{
ICarro setNome(String nome);
ICarro setMarca(String nome);
ICarro setPortas(int nome);
}
//classe que implementa essa interface.
public class Carro implements /ICarro/{
private String nome;
private String marca;
private int portas;
public Carro(){
}
public ICarro setNome(String nome){
this.nome = nome;
return this;
}
public ICarro setMarca(String nome){
this.nome = nome;
return this;
}
public ICarro setPortas(int numero){
this.portas = numero;
return this;
}
}
*Agora nosso mesmo exemplo.( O simples ainda )*
//** ANTIGO
Carro fusca = new Carro();
fusca.setNome("fusca");
fusca.setMarca("VW");
fusca.setPortas(2);
//**
//** COM O CONCEITO DE INTERFACE FLUENTE
Carro fusca = new Carro();
fusca.setNome("fusca")
.setMarca("VW")
.setPortas(2);
//Note como cada método de set retorna o objeto aplicando outro método,
dando mais expressividade
//a linguagem.
//**
Isso parece meio bobo, mas para um *exemplo inicial* é até "bonzinho".
*Exemplo Interessante
*Outro possível exemplo, um criador de sql. Em tempos que o padrã JPA está se consolidando, se trata de exemplo não muito usual (sem bem que se pode usar-lo para criar as JPQL)... mas ao exemplo.
Se quiser "conversar" com o SGBD expresse em SQL. Uma consulta SQL é
similar ao exemplo abaixo:*
SELECT* campo1,campo2, campo4 (ou * para todos)
*FROM* tabela1
*[INNER | OUTER ...] JOIN* tabela2 *ON*
*WHERE* condicao1
*AND *condicao2
*OR* condicao2
*ORDER BY* campo1, campo2 ....
O exemplo acima não mostra todas as potencialidades da linguagem SQL mas serve para o propósito do exemplo.
1º A criação da Interface
public interface IConsultaSql{
IConsultaSql select(String campos);
IConsultaSql from(String tabela);
IConsultaSql innerJoin(String tablea);
IConsultaSql outterJoin(String tablea);
IConsultaSql on(String condicao);
IConsultaSql where(String condicao);
IConsultaSql and(String condicao);
IConsultaSql or(String condicao);
IConsultaSql orderBy(String campos);
}
Logo após a criação da classe que implementa a interface.
public class ConsultaSql implements /IConsultaSql/{
private StringBuilder construtor = new StringBuilder();
//note que o próprio StringBuilder aplica conceitos de interface fluente.
public ConsultaSql(){
}
public IConsultaSql select(String campos){
construtor.append("SELECT ")
.append(campos);
return this;
}
public IConsultaSql from(String tabela){
construtor.append(" FROM ")
.append(tabela);
return this;
}
public IConsultaSql innerJoin(String tabela){
construtor.append(" INNER JOIN ")
.append(tabela);
return this;
}
public IConsultaSql outterJoin(String tabela){
construtor.append(" OUTTER JOIN ")
.append(tabela);
return this;
}
public IConsultaSql on(String condicao){
construtor.append(" ON ")
.append(condicao);
return this;
}
public IConsultaSql where(String condicao){
construtor.append(" WHERE ")
.append(condicao);
return this;
}
public IConsultaSql and(String condicao){
construtor.append(" AND ")
.append(condicao);
return this;
}
public IConsultaSql or(String condicao){
construtor.append(" AND ")
.append(condicao);
return this;
}
public IConsultaSql orderBy(String campos){
construtor.append(" ORDER BY ")
.append(condicao);
return this;
}
public String getSql(){
String retorno = construtor.toString();
return retorno;
}
}
*Veja o uso.*
ConsultaSql con = new ConsultaSql();
con.select("nome,telefone")
.from("pessoa_fissica pf").innerJoin("contatos ct").on("pf.id=ct.pf_id")
.where("pf.nome like %?%")
.and("pf.idade>18").orderBy("nome,idade");
*Bem mais expressivo... mais flexível*
Senão engano o Hibernate está implementando [ou tem implementado] algo assim para criar os
objetos Criteria.
public String getSql() throws SqlIncorretoException{
String retorno = construtor.toString();
Sql.valida(retorno);
return retorno;
}
Uma nova característica do java 5, o varargs também pode ajudar a aplicar "esses novos conceitos" de interface fluente.
*TRADICIONALMENTE*
Produto bola;
Produto cafe;
Produto monitor;
Compra compra = new Compra(cliente);
compra.adicionarItem(bola);
compra.adicionarItem(cafe);
compra.adicionarItem(monitor);
*COM USO DE VARARGS
*
Produto bola;
Produto cafe;
Produto monitor;
Compra compra = new Compra(cliente);
compra.adicionarItem(bola,cafe,monitor);
Enfim são todos conceitos muito abstratos e ainda em discussão, logo "nada" é certo sobre esse tema. No mínimo o assunto é interessante e intrigante para os desenvolvedores e clientes (quem realmente interessa). Se acostume com esse novo paradigma /expressividade no desenvolvimento. (tudo mais perto da linguagem de
domínio do sistema)
/ps: perdoem os erros de português.
/Links interessantes sobre os assuntos/.
* _http://www.fragmental.tw_ (Blog sobre pesquisa em DSL)
* _http://martinfowler.com/bliki
"ditando" sobre o que é uma Interface Fluente)
* _http://www.infoq.com/presenta
(Vídeo com uma introdução sobre DSL)
2 comentários:
Muito interessante, parabens pelo artigo.
Consegui agora ver como realmente funciona.
Abraço
Postar um comentário