Por se tratar de um projeto de conclusão de curso, algumas diretrizes foram passadas via documentação de requisitos, tornando-se assim, obrigatórias. Dentre elas destacam-se três que trouxeram um nível de dificuldade descomunal ao projeto:
- Rodar a aplicação na console
Sem dúvida nenhuma, o requisito mais emblemático. Após uma avaliação inicial de 5 horas e 30 minutos (fase projeto) foi necessário decidir entre:
- Desenvolver a aplicação na console — e adicionar ao projeto um nível de complexidade inimaginável.
- Desenvolver a aplicação com a Biblioteca Java Swing — e não adicionar ao projeto complexidade nenhuma.
Diante das opções disponíveis, optou-se por seguir a documentação original de requisitos e desenvolver a aplicação na console — única forma de se praticar e consolidar o aprendizado de alguns dos conceitos trabalhados no curso (modelagem CRC, por exemplo).
Ao todo, foram 266 horas investidas somente em modelagem CRC — para definir as classes, suas responsabilidades e dependências. Após isso, mais 73 horas para construir o diagrama de classes UML.
Durante todo esse tempo, utilizou-se os os princípios de engenharia de software Tell Don't Ask e Law of Demeter — para diminuir o nível de acoplamento entre as classes.
- Construir uma aplicação onde as partes de sua execução possam ser facilmente trocadas
Para cumprir esse requisito utilizou-se o padrão de projetos Factory Pattern duas vezes:
- Factory Pattern 1: A aplicação possui uma classe abstrata chamada Embaralhador. A classe Embaralhador possui três implementações. Cada uma utiliza uma técnica diferente para embaralhar as palavras.
- Factory Pattern 2: A aplicação possui uma classe abstrata chamada MecanicaDoJogo. A classe MecanicaDoJogo possui três implementações. Cada uma apresenta uma sequência diferente de passos para conduzir e encerrar a partida.
Para que um embaralhador possa ser facilmente adicionado ou excluído da aplicação, a tarefa de instanciá-los é delegada à classe FabricaEmbaralhador. Dessa forma, para se adicionar ou remover um Embaralhador, basta modificar uma única classe: FabricaEmbaralhador.
Para que uma MecanicaDoJogo possa ser facilmente adicionada ou excluída da aplicação, a tarefa de instanciá-las é delegada à classe FabricaMecanicaDoJogo. Dessa forma, para se adicionar ou remover uma MecanicaDoJogo, basta modificar uma única classe: FabricaMecanicaDoJogo.
- Apenas uma única classe pode ler a entrada do usuário e imprimir informações na console
Para cumprir esse requisito utilizou-se herança e polimorfismo.
O Jogo das Palavras Embaralhadas possui 16 telas — cada uma instanciada por uma classe distinta. Toda tela precisa imprimir e ler informações na console — afinal de contas, as telas servem para isso.
Para resolver o dilema foi criada a classe abstrata TelaNav (abreviação de tela de navegação). A classe TelaNav possui o método leEntrada, que imprime a tela do jogo na console e lê a entrada do usuário através de um atributo tipo Scanner.
O próximo passo foi utilizar herança para tornar as 16 telas do jogo subclasses de TelaNav (estendendo-a). Dessa forma, toda tela pode ler e imprimir informações na console, pois herdam o método leEntrada da superclasse — e, ao mesmo tempo, devido ao polimorfismo, toda classe que estende TelaNav é TelaNav. Desse modo, podemos dizer que apenas uma classe imprime e lê informações da console: TelaNav.