Este projeto simula uma olimpíada de questões, permitindo o cadastro de participantes, provas, questões e o registro de tentativas. A versão atual foi refatorada seguindo boas práticas de SOLID, melhorando manutenibilidade, testabilidade e separação de responsabilidades.
A versão anterior concentrava todas as responsabilidades em uma única classe App, com métodos estáticos e listas globais, o que dificultava manutenção e expansão. A versão refatorada introduziu:
Responsável apenas por criar serviços, repositórios e iniciar o menu.
Cumpre Single Responsibility Principle (SRP): apenas inicialização e injeção de dependências.
Contém apenas lógica de interação com o usuário e chamadas aos serviços.
Toda a lógica de negócio e persistência foi removida da classe principal, facilitando testes e alterações futuras.
Serviços:
- ParticipanteService
- ProvaService
- QuestaoService
- RespostaService
- TentativaService
Cada serviço encapsula operações de CRUD e lógica de negócio específica, permitindo Open/Closed Principle (OCP): novas funcionalidades podem ser adicionadas sem alterar classes existentes.
Repositórios concretos:
- ParticipanteRepository
- ProvaRepository
- QuestaoRepository
- RespostaRepository
- TentativaRepository
Repositórios são injetados nos serviços, respeitando Dependency Inversion Principle (DIP).
Responsável apenas por aplicar uma prova e gerar tentativas.
A separação desta lógica da UI e do menu reforça SRP.
Classe dedicada apenas a imprimir o tabuleiro de xadrez, isolando a responsabilidade de apresentação visual.
| Princípio | Como foi aplicado na versão refatorada |
|---|---|
| SRP (Single Responsibility Principle) | Cada classe tem uma responsabilidade clara: App inicializa, AppMenu controla a interface, serviços contêm regras de negócio e repositórios lidam com dados. |
| OCP (Open/Closed Principle) | O sistema pode ser estendido sem modificar classes existentes, por exemplo ao adicionar novas regras de negócio ou novos tipos de persistência. |
| LSP (Liskov Substitution Principle) | Repositórios implementam interfaces, permitindo trocar implementações sem quebrar o sistema. |
| ISP (Interface Segregation Principle) | Interfaces específicas por entidade evitam dependências desnecessárias em métodos que não são usados. |
| DIP (Dependency Inversion Principle) | Classes de alto nível dependem de abstrações (interfaces e serviços), não de implementações concretas. |
Maior manutenibilidade – mudanças em cadastro ou aplicação de provas não afetam a inicialização nem a UI. Testabilidade – cada serviço e aplicação de prova pode ser testada isoladamente. Clareza de responsabilidades – código organizado por funcionalidade, seguindo princípios de design. Redução de acoplamento – dependências injetadas via construtor (App → AppMenu), facilitando futuras melhorias ou migração de persistência.
br.com.ucsal.olimpiadas
│
├── App.java
├── AppMenu.java
│
├── participante
│ ├── Participante.java
│ ├── ParticipanteService.java
│ ├── ParticipanteRepository.java
│ └── ParticipanteRepositoryInterface.java
│
├── prova
│ ├── Prova.java
│ ├── ProvaService.java
│ ├── ProvaRepository.java
│ ├── ProvaRepositoryInterface.java
│ └── AplicacaoProva.java
│
├── questao
│ ├── Questao.java
│ ├── QuestaoService.java
│ ├── QuestaoRepository.java
│ └── QuestaoRepositoryInterface.java
│
├── resposta
│ ├── Resposta.java
│ ├── RespostaService.java
│ ├── RespostaRepository.java
│ └── RespostaRepositoryInterface.java
│
├── tentativa
│ ├── Tentativa.java
│ ├── TentativaService.java
│ ├── TentativaRepository.java
│ └── TentativaRepositoryInterface.java
│
├── tabuleiro
│ └── TabuleiroPrinter.java
│
└── test
└── java
└── br
└── com
└── ucsal
└── olimpiadas
└── ExemploTest.java
A versão refatorada separa claramente a responsabilidade de inicialização, interface e regras de negócio. O fluxo de execução funciona da seguinte forma:
+----------------+
| App |
| (main apenas) |
+----------------+
|
v
instancia serviços + repositórios
|
v
+----------------+
| AppMenu |
| (interface CLI)|
+----------------+
| |
| v
| chama serviços
| |
v v
+------------------------+
| Services |
| (regra de negócio) |
| ParticipanteService |
| ProvaService |
| QuestaoService |
| RespostaService |
| TentativaService |
+------------------------+
|
v
+------------------------+
| Repositories |
| (persistência em memória) |
+------------------------+
Responsável apenas por iniciar a aplicação. Cria instâncias de serviços e injeta dependências.
Atua como camada de interface (CLI). Recebe comandos do usuário e delega ações aos serviços.
Contêm regras de negócio. Exemplo: cadastrar participante, aplicar prova, calcular nota.
Responsáveis por armazenar e recuperar dados em memória. Implementados via interfaces, permitindo substituição futura (ex: banco de dados).
Com essa estrutura, o sistema evoluiu de um modelo monolítico (tudo em uma classe) para uma arquitetura em camadas:
UI (AppMenu)
↓
Services (regras de negócio)
↓
Repositories (dados)