quarta-feira, 9 de setembro de 2009

Que idioma devemos utilizar em nosso código inglês ou português. Como devo tratar a expressividade do código e a ubiquitous-language.

Já faz algum tempo que discutimos em meu trabalho sobre que idioma utilizar no código, português ou inglês. Entretanto, meu novo brinquedo me motivou a escrever este post sobre Ubiquitous Language e legibilidade de código. Espero que realmente seja útil para alguem, e que gere alguns bons comentários (Ninguém nunca comentou no meu blog)-: então vamos lá...

Para desenvolver software, necessitamos de um conhecimento sobre o domínio do problema. Como desenvolvedores de software, normalmente, não são especialistas no negócio do cliente, logo se faz necessário a formação de uma equipe multidiciplinar contentendo analistas de negócio, clientes, gerentes de projeto e etc. Além das habilidades, ferramentas e técnicas, as pessoas envolvidas de algum modo no desenvolvimento do software devem estar preparadas para trabalhar em equipe e lidar com os diferentes aspectos e pontos de vista. Há de se buscar sinergia, comunicação e muita disciplina, sem prejudicar o nível de participação e envolvimento das pessoas com a missão recebida.

Para solucionar o problema de comunicação entre esta equipe multidiciplinar e melhorar a qualidade interna do código desenvolvido, Eric Evans em seu livro Domain-Driven Design: Tackling Complexity in the Heart of Software (Hardcover) propõem uma solução denominada Ubiquitous Language.
Basicamente é um dos conceitos que o DDD utiliza, que tem como finalidade: “falar” a língua do usuário/cliente. Manter uma única linguagem de domínio que seja entendível tanto para os desenvolvedores quanto para o cliente. Ubiquitous Language não é uma linguagem utilizada apenas no código, porém em qualquer atividade (documentação, reunião, especificação, testes, código, conversas entre a equipe e especialistas etc) durante todo o desenvolvimento do software. Seu modelo tem que possuir as palavras chaves do domínio do cliente, isto facilita o entendimento de todos os envolvidos do software.

Para conhecer mais sobre ubiquitous language ou DDD sugiro ler o livro. Eu não li, mas minha filha número 4 leu e falou que é muito bom.
Como o ubiquitous language, DDD e juntamente com DSL (Domain Specific Languages) em voga a legibilidade e expressividade do código e ainda prometem dar muito o que falar, parece que a gente fica cada dia mais influenciado pela tendência de deixar o código o mais próximo possível da linguagem de negócio. O código deve estar o mais claro possível, isto é, sem interferências geradas pela sintaxe da linguagem.

Assim, para nós utilizarmos a linguagem do cliente (como estamos no Brasil), deveríamos utilizar o português em nosso código. No entanto, quando falamos em linguagem de programação, somente temos opções em inglês, transformando nosso código em uma tremenda salada de fruta.

Entretanto, ontem descobri que em python poderia traduzir suas palavras reservadas (magia negra) e escrevi um modulo para que acrescenta as palavras chave da linguagem em português, colocando todo meu código em português. Para utilizar o módulo, basta acrescentar o cabeçalho "#encode: pt-br" o inicio do arquivo python. Com isto podemos escrever:


#encode: pt-br

imprima "numeros pares:"
para cada numero na faixa(1, 10):
    se nao numero % 2:
        imprima numero,





Para minha surpresa (minto, sabia que iriam falar isso) meus colegas perguntaram para que vou escrever código python em português?
Mas vamos a resposta... como jah descrito no texto, legibilidade de código faz toda a diferença. As palavras que vc utiliza para se expressar, muda toda sua forma de pensar. Quando vc traduz seu modelo para o inglês, sua interpretação raramente será exatamente a mesma de outra pessoa, logo vc deveria em seu código, utilizar os mesmos conceitos do usuário/cliente e envolvidos no projeto (normalmente, porem nem sempre o pt-br). A tradução das palavra reservadas do python, somente evita o tutifrute de idiomas. Para resolver a bateria de módulos inclusos no python, simplesmente traduza em seu importe. Por exemplo:
#encode: pt-br
de os importe path como caminho


Para entender melhor o que eu estou falando e testar o inglês dos leitores, vejamos alguns exemplos:

Qual das duas palavras em inglês quer dizer faculdade, college ou Faculty?
A grande maioria das pessoas deve ter respondido college, o que esta correto. Entretanto, faculty tambem esta correto, onde este significa faculdade de faculdade mental.
A tradução sempre é um problema, vejamos a palavra "free", qual das palavras abaixo poderia ser uma tradução?
gratuitamente, aforrar, grátis, libertar, desembaraçado, livrar, espontâneo, soltar, desembaraçar, desobstruir, emancipado, desentupir, franquear, eximir, emancipar, desobrigar, abrir, aliviado, livre, liberto, desprendido, gratuito, absolvido, autônomo, desobstruído, independente, isento.
Para a surpresa de alguns, todas estas palavras poderiam ser possíveis traduções para free.
Qual destas palavras quer dizer fisico: physic, psychic, physics, physicist, physician, physique?
Físico em português possui dois sentidos, o profissional de física e relacionado a aparência. Nas opções, a primeira palavra quer dizer lachante, a segunda quer dizer vidente, a terceira quer dizer a fisica a ciência, physicist significa fisico, physician é médico e physique quer dizer fisico de aparência.
Continuando com a brincadeira, qual destas palavras não quer dizer tempo: time, weather, tempo, tense:
A palavra “tempo” pode ser vertida para a língua inglesa de três maneiras diferentes: quando quiser se referir à medida cronológica, use “TIME” Ao se referir às condições climáticas, a opção correta é “WEATHER” Para descrever um tempo verbal, use “TENSE”. Em inglês, a palavra “TEMPO”, de origem italiana, é usada em música e significa andamento, no sentido de rítimo, o tempo da música.

Nem sempre vou utilizar o português para programar em python. Entretanto, como a maioria de meus software tem âmbito nacional, este novo módulo será muito utilizado.

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>