Erros na view e views type safe em java

Diversas vezes escolhemos uma linguagem como Java para nosso projeto para que tenhamos benefícios de uma linguagem type safe mainstream. Ganhamos o poder de refatoração sem medo através do uso da IDE, a capacidade de detectar toda um categoria de erros em tempo de compilação ao invés de descobrir em tempo de execucão que algo estava muito errado etc.

Mas ao escolhermos Java para o desenvolvimento de uma aplicação web tradicional junto com um framework como o VRaptor, qual a tecnologia de view que escolhemos? JSP? Velocity? Freemarker? Twirl? Erb?

Se escolhermos uma view com linguagem dinâmica e não compilada, como JSP, Freemarker ou Erb, não sabemos em tempo de desenvolvimento se o método que estamos invocando na view existe de verdade em nossos modelos. Não cobrimos 100% com testes de aceitação (100% de testes de unidade aqui não valem), então só pegamos alguns erros de invocações inválidas em tempo de execução, um horror. Só descobrimos que digitamos um “items” ao invés de “itens” dentro de uma cláusula de if em produção. Claro, o desenvolvedor deveria testar todos os caminhos, mas todos os caminhos são (literalmente) infinitos.

Linguagens de view não compiladas facilitam o indesejado: pegar erros somente em produção.

Mas o JSP é compilado. Somente em produção. E mesmo que instalássemos um plugin na IDE para compilar o JSP, ao utilizar expression language a compilação não pega erros como os citados acima.

Essas views também não permitem definir quais são as variáveis que elas precisam receber para serem renderizadas. O resultado é um controller que esquece de enviar uma variável ou faz uma query desnecessária e envia dados além do desejado pela view: por um lado o comportamento é indesejado e no outro desnecessário, não ótimo.

Desejamos então o que? Uma view capaz de definir o que ela precisa, e que nos diga em tempo de desenvolvimento o que estamos fazendo de errado: desde variáveis descenessárias, variáveis erradas ou invocações inválidas.

O Twirl oferta isso, mas em outra linguagem, Scala. E com ela, vem todas as dependências do Scala, mais uma linguagem para o desenvolvedor de backend e o de frontend aprenderem, erros de compilação obscuros (ligados a outra linguagem) e a impossibilidade de um debug de nossa view para seres humanos (a implementação atual do Twirl é feita em cima de sequências de yields).

Queremos então algo onde eu escreva primariamente HTML e secundariamente (meus laços e condicionais) em Java, que não obrigue o desenvolvedor a aprender mais uma linguagem, que seja debugável, apresente mensagens de erro adequadas ao meu ambiente e permita que o desenvolvedor pegue diversos tipos de erro durante o desenvolvimento, como no arquivo lista.tone a seguir:

@(List<User> users)

<html>
<% for(User user : users) { %>

    <h1>Hi @user</h1>

<% } %>
</html>

A view acima foi escrita em Panettone, uma template engine que utiliza código Java e permite declarar as variáveis que deseja utilizar. O código acima será transformado durante desenvolvimento em uma classe chamada template.lista, com o método render:

public void render(List<User> users) {
// line 3
    write("<html>\n");
// line 4
 for(User user : users) {
// line 6 
    write("<h1>Hi @user</h1>\n");
// line 7
 } 
// line 8
    write("</html>\n");
}

Isto é, em tempo de desenvolvimento temos todas as vantagens que estávamos procurando. Para isso basta deixar rodando um jar que compila nossas views o tempo todo, seja através de um java -jar, do ant ou do maven. Ou podemos ainda instalar um plugin do Eclipse (solução mais simples de todas) que ao aplicar a natureza Panettone no projeto, já passa a compilar todas as suas views.

O processo de migração de uma view JSP para Panettone não é doloroso, uma vez que a expression language existente no Panettone é compile safe (diferentemente do JSP) e suporta diversas características dele. Para nossos projetos onde não usamos taglibs de terceiros, o Panettone parece ser um bom caminho para minimizar erros em nossos projetos.

Para começar a utilizar o Panettone (principalmente com VRaptor), você pode seguir as informações do README ou conversar na lista do VRaptor e no GUJ.

Tags: ,

16 Comentários

  1. Vanderson assis 21/10/2014 at 08:47 #

    É impressão minha ou esse Panettone é bem parecido com scriptlet? Código java na view? Isso não é uma má prática?

  2. Guilherme Silveira 21/10/2014 at 09:04 #

    Bom dia Vanderson! Lógica de negócios na view é má prática, lógica de visualização na view é normal.
    Quando fazemos um if ou um for na view com JSTL, java, ruby ou qualquer outra variação estamos fazendo lógica de visualização, aplicando condicionais e laços para montar o resultado de nossa view.

    Quando fazemos “meuCodigo.acessaOBanco()” ou “meuCodigo.processaNegocio” estamos fazendo lógica de negócios na view. Ai fugiu da separação de responsabilidade (view é view, logica de negocios é logica de negocios). Na maior parte dos template engines e similares (no JSTL, no EL, em Scriptlet, ERB etc) você pode fazer meuCodigo.acessaOBanco e meuCodigo.processaNegocio…a má prática está dependendo do desenvolvedor e não da linguagem que ele escolheu pra lógica de apresentação a ser usada na view.

    Abraço!

  3. Robson Peixoto 21/10/2014 at 09:21 #

    A solução ficou massa!
    Mas como é o desempenho do Panettone? Vocês fizeram algum benchmark para comparara as soluções?

  4. Guilherme Silveira 21/10/2014 at 16:46 #

    Bom dia Robson!

    Não tenho não. Ele deve ser mais lento que uma servlet pura pois passa pela instanciação do vraptor (e possível injeção via CDI), um benchmark justo envolveria uns forzinhos e ifs na tela (que no JSP seria tipico com JSTL e chamada de tags). Pelo lado do JSP as tags envolvem chamadas de métodos que armazenam estados. Precisa testar mesmo para poder dizer!

    Abraço

  5. icaro 22/10/2014 at 16:51 #

    É uma otima iniciativa! So senti falta de um exemplo baixavel no site ja pronto pra testar…

  6. Arthur 22/10/2014 at 20:02 #

    Ok, parece o Razor…. IRADO!!! Vcs vão implementar HtmlHelpers também? E aquele link do Paulo Coelho??? hauhauha…. bizarro!

  7. Guilherme Silveira 22/10/2014 at 22:03 #

    @Icaro verdade! O que acha de alterar o exemplo do vraptor-blankproject e configurá-lo lá? Topa enviar um pull request?
    @Arthur isso mesmo! Acho que os helpers vem de graça: passe seu helper object como parâmetro para a view, fica transparente e continua type safe!

  8. Felipe Alfaville 24/10/2014 at 13:13 #

    Bom dia! Eu uso Play Framework 2 Java, e por consequência, uso Twirl como tecnologia de view e estou gostando muito.

    Òtimo artigo, meus parabens!!

  9. Joel Lobo 25/10/2014 at 12:35 #

    Como faço para “aplicar a natureza Panettone no projeto”?

  10. Joel Lobo 25/10/2014 at 12:46 #

    Já instalei o plugin. Como faço para “aplicar a natureza Panettone no projeto” ? Alterando .project? ????

  11. Guilherme Silveira 25/10/2014 at 22:45 #

    Boa noite Joel, use o CTRL+3 que o ajuda a procurar qualquer coisa no Eclipse, ai digite “Panettone” que aparecerá a opção. Vou adicionar na documentação! Se quiser contribuir, um patch para adicionar ao menu do projeto era uma boa.

    Abraço!

  12. Wesley Martins 29/10/2014 at 22:26 #

    Muito bom o artigo.
    O que há gente tem feito nos projetos com o Vraptor é, desenvolveu o UC desenvolve o teste no Selenium.
    Os TD’s validam as RN.
    Junto com isso temos uma equipe de homologação de qualidade.
    Não temos encontrado os temidos erros em produção.
    Nesse caso, seria interessante. Vamos fazer uns testes.
    Em relação a performance a ‘perda’ é minima e vale a pena no final.

  13. Guilherme Silveira 30/10/2014 at 14:14 #

    Ótimo Wesley! Enquanto um projeto aqui utiliza baterias de selenium para pegar muitos caminhos no runtime, devido a infinidade de combinações lógicas que a view tem, ficava difícil para nós cuidar de tudo. O compilador nos ajudou com isso, e com delay de 0 segundos 🙂

    Abraço!

  14. Denilson Telaroli 14/05/2015 at 17:02 #

    Tentei usar a opção CTRL+3 mas o eclipse não acha nada.
    Estou usando a versão Luna SR2, será que é problema de compatibilidade?

  15. Paulo Silveira 15/05/2015 at 14:18 #

    deveria funcionar. se é mac, é command 3!

  16. Macedo 20/08/2015 at 19:11 #

    Qual a situação atual do vraptor panettone ? alguem tem algum exemplo de alguem que esteja usando ? tutorial, mais detalhes ? compatível com eclipse mars ? são tantas dúvidas !!

Deixe uma resposta