Vitor Pamplona

Innovation on Vision: Imaging , Enhancement and Simulation

Documentação como Réplica

Recentemente o Urubatan escreveu um belo post sobre documentação desatualizada usando o Easyb em Java, algo semelhante ao RSpec, famoso no mundo Ruby. Em suma, Urubatan defende a utilização da dita " documentação executável ", evitando documentos específicos, externos ao ambiente de programação, que deveriam esclarescer a maneira como as regras de negócio são implementadas. A motivação disto é que não há sincronismo formal entre este tipo de documento e o código, permitindo que o documento fique desatualizado.

Tanto o RSpec quando o Easyb, trouxeram grandes avanços tecnológicos no sentido de evitar a documentação desatualizada. No entanto, ainda há muito a ser feito. Eu, francamente, acho que ambos criaram uma solução para um problema que não precisa existir. Além da sintaxe de ambos ser um tanto poluída.  

Por exemplo, qual a diferença de fazer isto (Código 1):  

scenario "Um nome de usuário deve ser único no sistema", {
    given "Um usuário com o formulário preenchido corretamente", {
        user = new User('userName','password','password')
        userManager = UserManager.getInstance()
    }
    then "O registro deve criar o usuário no sistema", {
        userManager.create(user)
    }
    when "O nome de usuário ja existe no sistema", {
        user = new User('userName','otherPassword','otherPassword')
    }
    then "O registro do usuário deve falhar",{
        ensureThrows(UserAlreadyExistsException){
            userManager.create(user)
        }
    }
}

para isto (Código 2):

// Um nome de usuário deve ser único no sistema
function testNomeDeUsuárioÚnico() {
// Dado que existe um usuário com o
// formulário preenchido corretamente
user = new User('userName','password','password')
    userManager = UserManager.getInstance()
    // Então o registro deve criar o usuário no sistema
userManager.create(user)

// Se o nome de usuário ja existe no sistema
user = new User('userName','otherPassword','otherPassword')

// O registro do usuário deve falhar
    ensureThrows(UserAlreadyExistsException){
        userManager.create(user)
    }
}

Não sei se vocês perceberam, mas na prática nada muda. É apenas uma sintaxe diferente para escrever a sua documentação. E eu ainda acho mais fácil de ler a versão onde a documentação está nos comentários, pois na versão do Easyb mistura-se inglês e português e caracteres como aspas e chaves atrapalham. Claro, tanto o RSpec quanto o Easyb podem gerar relatórios html contendo somente as Strings de documentação para tornar a leitura mais fácil. Mas, sinceramente, com a documentação na sua frente no código, quem irá ler os documentos html?

Lembrem-se que, tanto no Código 1 quanto no 2, a documentação ainda não está sincronizada automaticamente com o fonte. Ela está apenas no mesmo lugar para que o desenvolvedor se toque de alterar ambas quando alguma mudança for feita.  

Outra. Observem atentamente as strings e os trechos de código que foram gerados a partir dela. O given do Código 1 pede: Um usuário com o formulário preenchido corretamente. Onde está o formulário no código? Pode parecer uma simples questão de interpretação, no entanto, estas divergências este tipo de questionamento pode ser feito por um novato naquele trecho de código e, se ele não entender, de que adiantou a documentação? Lembrem-se que este exemplo ainda é simples, regras de negócio complexas podem tornar a tarefa de interpretar a documentação e encontrar semelhanças no código, muito difícil.  

Uma vantagem da sintaxe do RSpec e do Easyb é que ambos estimulam os desenvolvedores a escreverem uma documentação. É quase uma obrigação. Afinal, ninguém é louco de fazer isso:  

scenario "", {
    given "", {
        user = new User('userName','password','password')
        userManager = UserManager.getInstance()
    }
    then "", {
        userManager.create(user)
    }
    when "", {
        user = new User('userName','otherPassword','otherPassword')
    }
    then "",{
        ensureThrows(UserAlreadyExistsException){
            userManager.create(user)
        }
    }
}

Além disso é possível personalizar a documentação com os parâmetros em tempo de execução. Isto permite gerar uma documentação mais " prática ", com valores e outras informações que podem ser validadas por qualquer um que visualizar os relatórios gerados pelo sistema de teste. Por exemplo, algo como isto (Não sei se a sintaxe é exatamente essa):  

scenario "Um nome de usuário deve ser único no sistema", {
    given "Um usuário com o formulário preenchido corretamente", {
        user = new User('userName','password','password')
        userManager = UserManager.getInstance()
    }
    then "O registro deve criar o usuário ${user.userName} no sistema", {
        userManager.create(user)
    }
    when "O nome de usuário ${user.userName} já existe no sistema", {
        user = new User('userName','otherPassword','otherPassword')
    }
    then "O registro do usuário ${user.userName} deve falhar",{
        ensureThrows(UserAlreadyExistsException){
            userManager.create(user)
        }
    }
}

Apesar da vantagem, a minha maior crítica está no fato do desenvolvedor precisar escrever essa documentação e permitir que ela fique desatualizada que, nada mais é, do que um problema de duplicação de código. Este é um problema amenizado pelas práticas de XP, nas quais o meu código ficaria assim:  

function testNomeDeUsuárioÚnicoNoSistema() {  
user = preencheUsuárioPeloFormulario('userName','password','password');
criarUsuárioNoBanco(user);
user2 = preencheUsuárioPeloFormulario('userName','otherPassword','otherPassword');
   ensureThrows(UserAlreadyExistsException){
criarUsuarioNoBanco(user2);
}
}

Óbvio, mais linhas de código são necessárias, mas evita-se a duplicação. Não estou dizendo que esta é a maneira correta de fazer, muito menos que seja a mais bonita, mas certamente é a mais eficiente na questão de amenizar o problema de desatualização. Este modo XPeiro de ser, ainda mistura inglês e português, fato presente em quase todas as aplicações que eu trabalhei e que, pessoalmente, eu odeio.

Concluindo, os reais benefícios que o Easyb e o RSpec trazem a um projeto são:

  • Geração automática de um html de documentação
  • Um toque psicológico para forçar os desenvolvedores a criarem documentação

Na contra mão, temos:  

  • Uma sintaxe nova e um novo " estilo " de documentar
  • A dificuldade de leitura relacionada a mistura de termos em inglês e português e a caracteres especiais.

Posted in Mar 26, 2008 by Vitor Pamplona - Edit - History

Showing Comments

[...] Por exemplo, qual a diferença de fazer isto (Código 1) [...] para isto (Código 2) [...]
Simples: No primeiro caso, você pode gerar um HTML e mostrar para o cliente apenas o que o interessa, neste caso:
scenario " Um nome de usuário deve ser único no sistema "
given " Um usuário com o formulário preenchido corretamente "
then " O registro deve criar o usuário no sistema "
when " O nome de usuário ja existe no sistema "
then " O registro do usuário deve falhar "

No caso do método do JUnit não tem nada pronto para fazer isso. Esta é a diferença.

- - Antonio Carlos de Souza

- - Posted in Mar 30, 2008 by 201.51.255.239

Mas isso pode ser gerado a partir de qualquer comentário, num processo semelhante ao Javadoc.

- - Vitor Pamplona

- - Posted in Mar 30, 2008 by 189.27.241.214

A questão é que o principal objetivo do Rspec é seguir o TDD (Test Driven Development), para otimizar o desenvolvimento e a manutenção do código. A " documentação " acaba sendo uma consequência, e visto que o TDD prevê que o desenvolvedor sempre escreva um TESTE antes de codificar alguma funcionalidade, a integridade é mais garantida e a documentação mais exigida.

Não conheço o Easyb, mas pelos códigos se assemelha mais ao Cucumber, do Ruby, do que ao Rspec, visto que ambos fazem referência ao comportamento do sistema, e são utilizados para seguir o BDD (Behaviour Driven Development), que não substitui o TDD, mas o complementa.

- - Ícaro Vinícius

- - Posted in Mar 23, 2010 by 200.133.215.2

A questão é que o principal objetivo do Rspec é seguir o TDD (Test Driven Development), para otimizar o desenvolvimento e a manutenção do código. A " documentação " acaba sendo uma consequência, e visto que o TDD prevê que o desenvolvedor sempre escreva um TESTE antes de codificar alguma funcionalidade, a integridade é mais garantida e a documentação mais exigida.

Não conheço o Easyb, mas pelos códigos se assemelha mais ao Cucumber, do Ruby, do que ao Rspec, visto que ambos fazem referência ao comportamento do sistema, e são utilizados para seguir o BDD (Behaviour Driven Development), que não substitui o TDD, mas o complementa.

- - Ícaro Vinícius

- - Posted in Mar 23, 2010 by 200.133.215.2

Add New Comment

Your Name:


Write the code showed above on the text below.