Gridify – Uma abordagem com DSL para melhorar o javax.swing

Gridify – Uma abordagem com DSL para melhorar o javax.swing

Buenas pessoal,

Quando ouvimos falar em javax.swing as primeiras coisas que nos vem a cabeça são:

  • Códigos gigantescos e estranhos;
  • Classes bizarras e sem nome de autor;
  • Exemplos visíveis do mau uso da orientação a objetos e herança entre os componentes;

Acredito que muitos dos problemas que existem na API do Java se deve ao fato de garantir compatibilidade com as suas versões anteriores, isto, na minha opinião, vira salvação pra muito código porcão que a gente vê por aí.

Mas o lado mais impactante ainda é a não evolução natural de toda sua API, não trazendo inúmeros recursos lindos das versões recentes do JEE, como por exemplo o CDI e também o próprio modo de pensar, em que podemos destacar a implementação para interfaces e redução no uso de herança.

Alternativas: usar uma DSL interna?

Quando empregamos uma DSL interna, estamos aplicando um melhor uso da própria linguagem hospedeira para limitar o domínio de negócio, ou seja, estamos criando uma sobre camada que permite lidarmos com os problemas de um ponto de vista de cima, mas como assim ?

As DSLs internas entram exatamente com este papel fundamental, geralmente elas aparecem naturalmente durante o processo de refactoring e é possível facilmente abstrair toda a complexidade do tratamento de um problema através de contratos bem definidos (interfaces). Tudo isto somado ao uso de Method chaining podemos usar o encadeamento de métodos afim de deixar a solução programática final de forma mais verbal. Abaixo um pequeno exemplo desta técnica:

Por mais que o trecho acima seja um mero exemplo, a forma em que empregamos o uso da DSL garante uma simplicidade grande na hora de ter que realizar alguma operação financeira, fica simples para que a equipe de desenvolvimento possa alinhar análises e soluções com a área técnica contábil, não dependendo de que o contador  saiba programar, logo porque apenas visualmente ele pode ler e também tratar algum problema não atendido, como por exemplo:

Se no exemplo acima o cálculo do lucro da nossa aplicação financeira estivesse errado e ao colocar o contador de um desenvolvedor para ver o problema, o contador poderia apenas olhando para o código falar que não foi informado o percentual de recolhimento do leão.

Simples assim, o que o desenvolvedor deveria fazer é alterar o seu código numa visão de cima:

Agora voltando ao nosso caso do javax.swing, o que eu comecei a tratar por meio de uma DSL interna (Gridify) foi a construção de telas que usam o famoso GridBagLayout e o seu tenebroso ajudante, o GridBagConstraints. É horrível ter que montar uma tela relativamente grande e/ou com vários elementos através do GridBagConstraints, basicamente é 60% do seu código final é somente referente a posicionamento dos elementos. Veja esse exemplo abaixo:

Se dermos uma boa olhada no código não é difícil de ver vários exemplos que fogem da OO e também alguns erros de arquitetura já declarados pelos engenheiros do Java daqueles tempos. Mas agora usando o Gridify, veremos como ficaria esse mesmo caso sendo abortado com uma DSL interna:

De uma forma programática verbal, eu pude colocar facilmente um elemento JLabel na linha e coluna zero aplicando uma margem igual para todos os lados sem precisar conhecer do horrível GridBagConstraints. Mas agora você deve estar se perguntando em qual a vantagem de eu querer trocar códigos das minha aplicação por isso?

Simples. Imagine que você tenha que aplicar uma correção em 140 telas usando a forma ogra do GribBagLayout, e que o seu programador Swing raçudo saiu da empresa e um novato esteja no seu lugar. Acredito que será bem complicado pra ele entender de todos os elementos que GridBagConstraints possui.

Já por outro lado usando a Gridify, seria bem mais fácil para ele assimilar a forma de posicionar os elementos e assim reduzir a curva de aprendizado para desenvolver no mesmo ritmo dos demais colegas.

OK, o que mais a Gridify tem ?

A DSL ainda tem os recursos básicos de posicionamento, não sou um conhecedor profundo do GridBagLayout, mas acredito que 70% dos casos já são tratados por ela. Na sua versão alpha, estão disponíveis os seguintes handlers:

  • Gridify.grid() para atender detalhes quanto a posicionamento;
  • Gridify.align() para atender detalhes de alinhamento;
  • Gridify.margin() para atender detalhes de margem dos elementos;
  • Gridify.fill() para atender detalhes de preenchimento;

Nas próximas semanas pretendo implementar mais alguns casos, como o rowspan e colspan, que são fundamentais no uso do GridBagLayout. Por enquanto que quiser conferir o projeto de uma olhada lá no Github:

https://github.com/carlosjrcabello/gridify/

Referências

http://www.martinfowler.com/bliki/FluentInterface.html

http://www.ibm.com/developerworks/br/java/library/j-eaed14/index.html

http://docs.oracle.com/javase/tutorial/uiswing/layout/gridbag.html

http://javafree.uol.com.br/artigo/5792/Tudo-sobre-o-GridBagLayout.html

Blog Java
  • daora cara! ficaria ainda mais profit se pudesse escrever as telas com XML :P

    • carlosspohr

      Então, o lance de usar XML é bacana mas eu acho que daria pra usar a própria onda atual de usar convenção sobre configuração, que aliás, o uso de XML complicaria a configuração de action listeners…

  • Massa, mas não curto esse esquema de encadeamento estilo JQuery. Talvez encapsulando em funções que recebem os parâmetros ficasse bem digerível.
    JavaFX 2.x está da hora também.

    • carlosspohr

      O legal do encadeamento/fluente é exatamente para reduzir a passagem de parâmetros, como no caso de ancorar a direita…é a direita e pronto sem a necessidade de parâmetros. Mas concordo que a passagem de parâmetros em alguns casos é necessária mesmo…como no caso do rowspan e colspan que comecei a implementar aqui.