Dicas de Swing MVC

Ao desenvolver um aplicativo Java Swing, o princípio MVC (Model View Controller) às vezes pode ficar confuso. Sem os devidos cuidados e experiência, tudo pode acabar contendo referências a todo o resto e o Controlador corre o risco de ser um Vishnu, onde todo o código é gerenciado centralmente e o Modelo / Controlador se torna um só.

Para manter o padrão MVC claro como cristal e promover um código limpo, alguns princípios devem ser respeitados ao escrever interfaces de usuário. Esta nota reúne alguns desses princípios:

  1. Freqüentemente, um modelo específico de IU deve ser criado com algum significado visual, mas não é relevante para o back-end. Em termos de design de IU, esse Modelo específico de IU faz parte do modelo e do back-end – portanto, não tente tratá-los de maneira diferente. (por exemplo, um objeto gráfico de rede social, que é um conceito estranho ao banco de dados de backend, mas ainda é um modelo da perspectiva da Visualização).
  2. A maior parte do Modelo deve ser independente do Controlador. Tanto o modelo quanto o controlador devem ser completamente independentes de qualquer implementação de visualização (consulte a nota 3). Uma boa maneira de garantir isso é mover a Visualização para um projeto separado que depende do Modelo e do Controlador (que pode ser um projeto).
  3. Faça com que as visualizações sejam ouvintes das mudanças no modelo, registrando-as com o controlador ou modelo (a @ListenerSupportanotação do Lombok-pg é ótima para isso). Dessa forma, o controlador não precisa se lembrar de quem precisa ver o quê – as visualizações apenas se registram para o que é relevante para elas.
  4. Ao criar uma interface de Listener, geralmente faz mais sentido receber eventos de mudança atômica. Se View realmente precisa ver o objeto completo também, então talvez valha a pena dar a ele acesso ao Controller (com um getter para o objeto Model relevante) ou uma referência ao objeto (se for final no Controller).
  5. Não tenha medo de permitir que as assinaturas de View incluam classes de Model: o objetivo não é isolar a View e o Model, mas garantir que o Controller seja responsável por recuperar e alterar o Model. Mas tenha a disciplina de não alterar diretamente o modelo do código de visualização (dê cópias do modelo para a visualização se você for paranóico).
  6. Tente evitar dar uma referência de Controlador a Visualizações que apenas renderizam informações (ou seja, que não precisam de controle).
  7. O Controlador não existe para “controlar outros aspectos da IU”, como fazer janelas pop-up – manter a lógica da IU na Visualização.
  8. O controlador está lá para controlar o modelo. Uma verificação de integridade da API deve revelar muito mais “doSomething” se “addSomethingListener” s em vez de “get / setSomething” s.
  9. O Java Swing é de encadeamento único, portanto, não se preocupe muito com a segurança do encadeamento na Visualização – use o padrão JavaBean para manter o código limpo (o Lombok facilita isso) em vez de exigir tudo na construção.
  10. Para evitar referências circulares, uma ordem de instanciação respeitável é:
    1. criar modelo (pode ser tão simples quanto uma conexão de banco de dados)
    2. criar controladores
    3. registrar controladores entre si (eles também podem ser ouvintes)
    4. registrar o modelo com o controlador
    5. criar vista
    6. registrar View as Listener para mudanças no Model / Controller (aplicativos de nível superior podem precisar fazer muitos registros)
    7. registrar o controlador com visualizações que precisam de controle sobre o modelo
  11. Use o Editor de GUI do Netbeans para economizar tempo, mas atenha-se aos layouts básicos em vez de layouts modernos projetados para editores de GUI: eles resultam em comportamentos de transparência estranhos e não são verdadeiramente portáteis. O que você deseja geralmente é melhor alcançado com um agregado de JPanels usando layouts apropriados.
  12. Aprenda as últimas bibliotecas de extensão Swing (por exemplo, SwingX), bem como a biblioteca central.
  13. repaint()vs : diz ao Swing que uma área da janela está suja; revalidate () diz ao gerenciador de layout para recalcular o layout e deve fazer com que os filhos do painel sejam repintados, mas pode não fazer com que o próprio painel o faça.revalidate()repaint()
  14. Não há consenso se um setter deve implicar que o Componente se revalida ou repinta. Tente ser consistente internamente, mas faça o que achar melhor. Algo a ser considerado é que, com o Lombok, ele pode manter o código mais limpo, não personalizando configuradores.
  15. A maioria dos LayoutManagers ignora completamente os métodos setXXSize, portanto, aprenda quais deles realmente usam esses valores. Sim, isso é realmente uma merda.
  16. O @BoundSetter do Lombok torna realmente fácil registrar um componente com ele mesmo para receber propertyChange (evento), permitindo ganchos pré / pós para alterações de propriedade. Este é um excelente local para registrar subcomponentes e controladores entre si.