O objetivo deste é ampliar o conhecimento do leitor, apresentando alternativas de uso do CDI que proporcionam mais opções para melhor resolução de problemas de código do cotidiano profissional.
Além disso, conheceremos uma ferramenta para criação de telas em JavaFX útil para aumentar a produtividade na construção de interfaces de usuário.
As linguagens de programação já evoluem ao longo de décadas de maneira a facilitar o trabalho executado pelo programador e, consequentemente, impacta positivamente na produtividade do desenvolvimento de software.
É possível afirmar que grande parte da evolução é alcançada à medida que estas linguagens se aproximam do mundo real e se tornam mais fáceis e intuitivas, deixando de ser uma linguagem puramente de máquina para se tornar uma linguagem humanamente compreensível.
Com base nesta máxima, as linguagens orientadas a objetos permitem que um sistema seja desenvolvido por meio de uma abstração do mundo real, onde entidades como uma pessoa ou um automóvel são representadas por objetos, e suas características e comportamentos pertinentes são evidenciados por atributos e métodos, respectivamente.
Mesmo que a orientação a objetos tenha levado a codificação a um nível mais próximo da realidade, durante o desenvolvimento de sistemas os programadores ainda se deparam com problemas parecidos, os quais são inerentes a este paradigma de programação.
Apesar disso, muitos desses problemas já foram catalogados em padrões de projeto. Assim, muitas vezes é necessário apenas reconhecer o problema, para então aplicar a solução conhecida.
Hoje já existem diversos padrões de projeto divulgados nos mais diferentes meios de publicação; é o caso dos padrões G.R.A.S.P. (General Responsibility Assignment Software Patterns), apresentados no artigo da Edição 129, ou os padrões GoF (Gang of Four), que são os mais conhecidos.
Neste ponto é válido ressaltar que diversos padrões de projeto são baseados no princípio de Hollywood (BOX 1), o qual acrescenta um desacoplamento maior entre as classes que desempenham um papel de coordenação da tarefa e as que apenas são coordenadas.
Deste modo, essas classes usuárias (ou coordenadas) não possuem conhecimento sobre o padrão implementado, pois são chamadas apenas para realizar uma pequena e específica porção do trabalho, ao passo que as classes que contemplam o padrão de projeto são responsáveis por chamar as classes coordenadas e orquestrar a comunicação entre elas para atingir o objetivo proposto.
A dinâmica entre esses objetos promove a divisão das tarefas em um trabalho colaborativo e coordenado.
É um famoso termo americano inspirado na expressão “don’t call us, we’ll call you!”, que significa “não nos chame, nós chamaremos você”. Esta expressão era muito utilizada no meio cinematográfico (por isso o nome Hollywood), onde após uma audição, o candidato ficava ansioso para saber se passou ou não no teste e assim questionava o diretor sobre quando poderia ligar para saber o resultado.
O diretor, no entanto, aumentava a ansiedade do candidato informando que ele deveria aguardar sua ligação. Com o tempo, no entanto, esta expressão foi ganhando um caráter negativo, passando ao candidato a sensação que ele nunca seria chamado.
Esta característica existe em alguns padrões de projeto, a exemplo do MVC e da própria Injeção de Dependências, e permite que as classes envolvidas trabalhem de forma coordenada, caracterizando-se então como um framework.
Por sua vez, um framework é um conjunto de classes relacionadas (ou API) que permitem ao programador a criação de pontos de extensão de acordo com a necessidade da aplicação.
Normalmente, estes pontos são representados por classes e objetos que implementam os requisitos funcionais do software, como telas ou entidades.
Assim, é possível observar esta característica em bibliotecas bem conhecidas como o Swing, onde as telas são criadas com o uso da API disponibilizada no JDK.
Dito isso, ressalta-se que o tema a ser abordado neste artigo está intimamente relacionado com os conceitos de framework e design patterns vistos até então, principalmente porque a injeção de dependências é também um padrão de projeto que visa atender um problema recorrente no desenvolvimento de sistemas orientados a objetos.
Também referenciada como Inversão de Controle (Inversion of Control – IoC), é a arte de fazer as “coisas” virem até você, como em um passe de mágica. Assim, o trabalho de um framework IoC é essencialmente criar objetos, verificar quais destes se relacionam e atribuir as respectivas instâncias a quem precisa delas.
A criação de um objeto pode ser trivial, como em uma simples instanciação, ou pode ser complexa, como a criação de um data source ou um serviço de envio de e-mail.
Neste contexto, o CDI (Contexts and Dependency Injection) é a especificação oficial do Java para Injeção de Dependências, representada pela JSR 346, sendo o framework JBoss Weld a implementação de referência.
Para demonstrar o funcionamento do Weld, no outro artigo foi desenvolvido um jogo de Batalha Naval standalone utilizando CDI e JavaFX para montagem e apresentação da tela.
Neste exemplo, a implementação produzida foi bem simplificada e objetivou apenas demonstrar de maneira didática o funcionamento e convívio de ambas as tecnologias.
Neste artigo, será aproveitado todo o código já produzido (você pode obtê-lo no link Download da página desta edição), e serão realizados alguns ajustes para apresentar outros recursos do CDI, bem como uma forma mais produtiva de criar interfaces de usuário com JavaFX, usando uma ferramenta gratuita disponibilizada pela Oracle, a JavaFX Scene Builder, a qual será analisada no tópico subsequente.
Desenvolvendo a tela com JavaFX Scene Builder
Supondo que o código da Listagem 1 tivesse que ser evoluído e mais componentes visuais precisassem ser adicionados, seguir a abordagem empregada anteriormente seria tecnicamente viável, entretanto, a quantidade de objetos a serem manipulados no código cresceria substancialmente, dificultando a manutenção ou evolução da tela.
Por esses motivos, as ferramentas mais modernas para desenvolvimento de interfaces de usuário têm utilizado XML para a construção das telas, a exemplo do XML de layout adotado no Android. No JavaFX isso não é diferente! Este permite o desenvolvimento de telas em arquivos XML que podem ser escritos manualmente ou com o auxílio de ferramentas visuais.
No caso deste artigo, a ferramenta empregada é o JavaFX Scene Builder, que gera arquivos no formato fxml. Você pode baixar esta ferramenta de forma gratuita diretamente do site da Oracle.
Listagem 1. Código da classe Controller.
01 @ApplicationScoped
02 public class Controller {
03 private static final int TAMANHO_QUADRADO = 30;
04
05 @Inject
06 private Instance<AreaMar> instanceQuadrantePane;
07
08 @Inject
09 private Tabuleiro tabuleiro;
10
11 @Inject
12 private SorteioInicialBarcos sorteioInicialBarcos;
13
14 public Scene cenaInicial() {
15 sorteioInicialBarcos.alocarBarcos();
16
17 //atribuir o tamanho de cada quadrado do GridPane
18 GridPane gridPane = new GridPane();
19 for (int i = 0; i < tabuleiro.getAltura(); i++) {
20 gridPane.getColumnConstraints().add(new ColumnConstraints(TAMANHO_QUADRADO));
21 }
22
23 for (int i = 0; i < tabuleiro.getLargura(); i++) {
24 gridPane.getRowConstraints().add(new RowConstraints(TAMANHO_QUADRADO));
25 }
26
27 Map<Pedaco, Pedaco> quadrantes = tabuleiro.getQuadrantes();
28
29 //atribuição dos quadrados no GridPane. x e y representam as linhas e as colunas do grid
30 for (int x = 0; x < tabuleiro.getAltura(); x++) {
31 for (int y = 0; y < tabuleiro.getLargura(); y++) {
32 Pedaco quadrante = quadrantes.get(new Pedaco(x, y));
33 AreaMar quadrantePane = instanceQuadrantePane.get();
34 quadrantePane.setQuadrante(quadrante);
35 gridPane.add(quadrantePane, x, y);
36 }
37 }
38
39 //cria uma nova cena com o tamanho total do tabuleiro (altura e largura)
40 return new Scene(gridPane, tabuleiro.getAltura() * TAMANHO_QUADRADO, tabuleiro.getLargura() * TAMANHO_QUADRADO);
41 }
42
43 }
A Listagem 2 apresenta o código XML que foi criado com o JavaFX Scene Builder para geração da tela exposta na Figura 1.
Listagem 2. TelaJogo.fxml – Tela do Jogo de Batalha Naval desenvolvida em FXML.
01 <?xml version="1.0" encoding="UTF-8"?>
02
03 <?import java.lang.*?>
04 <?import java.util.*?>
05 <?import javafx.scene.control.*?>
06 <?import javafx.scene.layout.*?>
07 <?import javafx.scene.paint.*?>
08 <?import javafx.scene.text.*?>
09
10 <BorderPane prefHeight="384.0" prefWidth="640.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="br.com.devmedia.batalhanaval.ui.Controller">
11 <center>
12 <GridPane fx:id="painelJogo" prefWidth="-1.0" snapToPixel="true">
13 <columnConstraints>
14 <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
15 <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
16 <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
17 <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
18 <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
19 <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
20 <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
21 <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
22 <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
23 <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
24 </columnConstraints>
25 <rowConstraints>
26 <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
27 <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
28 <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
29 <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
30 <RowConstr ...