sábado, 20 de junho de 2009

Domiain Specific Languages (DSL)

O acrônimo "DSL" quer dizer domain-specific language ou linguagem de domínio específico. Ao contrário de uma linguagem de propósito geral como Python, Ruby, C# ou Java, que pode implementar qualquer coisa, uma DSL está restrita um domínio como: consulta (SQL), formatação de texto (HTML), estruturação de dados (XML), automatização de testes (Cucumber) entre outros exemplos.

Para explicar o significado de DSL nos voltamos ao fundamentos.
- O que seria uma linguagem?
Linguagem, de acordo com o dicionário Michaelis, é um conjunto de sinais que serve o homem para exprimir suas idéias; agregado de palavras e métodos de os combinar usados por um povo; idioma, língua. Logo, uma linguagem especifica de domínio ao contrário de uma linguagem genérica, caracteriza-se por certas peculiaridades de palavras e métodos de uma área específica de interesse e seus domínios gramaticais ou léxicas para exprimir suas idéias; dialeto.

O uso de DSL visa tratar um problema específico, dentro de um domínio específico, através da criação de uma linguagem própria para o mesmo. Neste contexto, existem diversos tipos de DSL como por exemplo externas ou internas. Uma DSL externa geralmente pode ser interpretadas por uma linguagem de uso geral ou compiladas para obter uma linguagem mas natural ao seu domínio. Um exemplo que expressa bem esse conceito é o pyccuracy, uma ferramente de teste para aplicar bdd em uma linguagem que um usuário/cliente possa ler.

Em contrapartida, uma DSL internal normalmente é voltada para os próprios programadores realizar uma determinada área de aplicação. Uma DSL interna torna o código extremamente legível, ou seja, o código é fácil de ser lido e entendido por uma pessoa que entende sobre seu domínio, tornando o código muitas vs mais curto e menos cansativo de escrever.

Qualquer linguagem pode-se criar uma linguagem de domínio interna, em maior ou menor grau, sendo que linguagens dinâmicas existem certas características que facilitam esse tipo de programação. Um forte protocolo para objetos, uma sintaxe flexível e a capacidade de interceptar características da linguagem são essenciais para o aproveitamento máximo de uma DSL.

Uma DSL interna que estou desenvolvendo no momento é uma linguagem de consulta "hurrySQL" para o grok. Este framework utiliza um banco de dados OO (ZODB) e estou desenvolvendo uma DSL interna semelhante ao SQL para consultar os objetos python pela sua interface.

Exemplo:
>>> from hurrySQL import SELECT
>>> from RH.interface import IPessoa
>>>
>>> SELECT(IPessoa.nome, IPessoa.idade).FROM(IPessoa).WHERE(IPessoa.idade > 18)
[("Gustavo Rezende", 28), ("Paula Tejando", 22)]

Uma derivação desta DSL será para criação de tabelas HTML.
Exemplo:

>>> TABLE(IPessoa.nome, IPessoa.idade).FROM(IPessoa).WHERE(IPessoa.idade > 18)
<table>
    <tr>
        <td>Gustavo Rezende</td>
        <td>28</td>
    </tr>
    <tr>
        <td>Paula Tejando</td>
        <td>22</td>
    </tr>
</table>

Repare que estou utilizando a sintaxe do python para simular outra linguagem (SQL). Ou seja, um dialeto python diferente para um problema especifico.

Um outro exemplo de DSL interna que fiz que estou disponibilizando junto com este post é para escrever HTML em python. Para demonstrar a diferença entre uma api comum e uma DSL vou criar um XHTML com o BeautifuSoup do python.

Código equivalente não usando DSL:

>>> pag = BeautifulSoup()
>>> html = Tag(pag,"html")
>>> pag.append(html)
>>> head = Tag(pag, 'head')
>>> title = Tag(pag, 'title')
>>> title.append("Teste BeautifuSoup")
>>> head.append(title)
>>> html.append(head)
>>> body = Tag(pag, 'body')
>>> h1 = Tag(pag, 'h1',attrs=[("id","title")])
>>> h1.append("Teste BeautifulSoup")
>>> body.append(h1)
>>> p = Tag(pag, 'p',attrs=[("id","content")])
>>> p.append("Conteúdo da página")
>>> body.append(p)
>>> html.append(body)
>>> html
<html>
 <head>
  <title>
   Teste BeautifuSoup
  </title>
 </head>
 <body id="content">
  <h1 id="title">
   Teste pyhtmdsl
  </h1>
  <p id="content">
   Conteúdo da página
  </p>
 </body>
</html>


Utilizando a DSL (pyhtmdsl):

>>> HTML(
...     Head(
...         Title("Teste pyhtmdsl")),
...     Body(id="content")(
...         H1(id="title")
...             ("Teste pyhtmdsl"),
...         P(id="content")
...             ("Conteúdo da página")))
<html>
 <head>
  <title>
   Teste pyhtmdsl
  </title>
 </head>
 <body id="content">
  <h1 id="title">
   Teste pyhtmdsl
  </h1>
  <p id="content">
   Conteúdo da página
  </p>
 </body>
</html>

Um comentário:

  1. Gustavo, boa noite. Li teu post e achei interessante o teu trabalho com DSL. Bom, vou tratar na minha monografia de especialização esse assunto e gostaria, se possível, de uma ajuda tua. Preciso montar um sumário conciso para explorar a parte conceitual da dsl, se puderes me dar um norte nisso, ficaria muito grato. Meu email é thalesr@gmail.com

    Um abraço.

    ResponderExcluir