View all files | ||||
Este projeto é uma aplicação de gerenciamento de tarefas (Task Manager), desenvolvida com o objetivo de construir um backend robusto em Java mais puro possível, evitando abstrações típicas de frameworks como Spring. A ideia central é reforçar o raciocínio lógico, aplicar princípios fundamentais da linguagem e utilizar padrões de projeto de forma prática.
💡 Modo Desktop: Interface gráfica construída com Java Swing, permitindo ao usuário criar e gerenciar tarefas de forma local, com uma experiência simples e funcional.
💡 Modo Web (opcional): Versão empacotada como um arquivo .war, que pode ser implantado em um servidor Tomcat configurado manualmente, possibilitando o consumo dos dados via endpoints que retornam JSON, caso se deseje uma integração web ou API.
Essa abordagem mista serve para demonstrar como um mesmo backend pode ser estruturado para diferentes formas de acesso (desktop e web), sempre com foco em manter um código limpo, compreensível e bem estruturado.
A aplicação foi desenvolvida seguindo os princípios da Arquitetura Limpa (Clean Architecture), com uma separação clara entre lógica de negócio (core) e infraestrutura (infra). Essa abordagem proporciona maior flexibilidade, testabilidade e facilidade de manutenção ao longo do tempo.
A aplicação está dividida principalmente em dois módulos:
Core:
Infra:
A principal regra seguida é:
As dependências sempre apontam para dentro.
Ou seja, o core define contratos e o infra fornece implementações concretas. Isso permite que o core possa ser testado e evoluído isoladamente, e até mesmo reutilizado em diferentes ambientes (desktop, web, testes automatizados, etc.).
A aplicação foi projetada com foco em flexibilidade e evolução gradual. Por isso, foram implementadas múltiplas formas de persistência de dados, todas utilizando o padrão Repository, o que permitiu alternar facilmente entre diferentes estratégias sem alterar a lógica de negócio.
A primeira implementação foi feita em memória, utilizando estruturas como Map para armazenar tarefas e quadros temporariamente. Essa abordagem foi essencial nos estágios iniciais do desenvolvimento, pois:
Na etapa seguinte, foi adicionada uma implementação de persistência baseada em arquivos CSV. Cada entidade (como tarefas ou quadros) é salva em arquivos locais, permitindo:
Por fim, foi implementada a persistência com banco de dados relacional PostgreSQL, tornando a aplicação pronta para cenários mais reais e robustos. Essa implementação trouxe:
Todas as formas de persistência seguem o padrão Repository, com interfaces definidas no módulo core e implementações específicas no módulo infra. Graças à Arquitetura Limpa e à inversão de dependência, trocar a forma de persistência é simples:
Basta injetar uma nova implementação no lugar da anterior, sem alterar nenhuma regra de negócio.
Essa estrutura garante alta coesão, baixo acoplamento e grande facilidade para testes, manutenção ou expansão futura da aplicação.
Dentro da pasta infra, a camada de apresentação está organizada na pasta presenters, e foi dividida em duas interfaces distintas para refletir os dois modos de acesso à aplicação: modo desktop (Swing) e modo web (Servlet).
A subpasta swing contém todos os componentes relacionados à interface gráfica da aplicação, construída com Java Swing. Aqui ficam:
Essa interface permite que o usuário utilize a aplicação de forma local, com uma experiência visual simples e funcional, sem depender de servidor web.
A subpasta web abriga a implementação da camada de apresentação para a versão web da aplicação, utilizando Java Servlet. A principal funcionalidade atual é:
Essa implementação permite que o backend seja acessado por aplicações externas (como um frontend web ou cliente REST), sem alterar a lógica de negócio.
Graças à arquitetura limpa, ambas as interfaces consomem os casos de uso e entidades do core, sem duplicar regras de negócio. Isso garante:
Durante o desenvolvimento, foram aplicados alguns padrões de projeto clássicos para garantir flexibilidade, extensibilidade e organização da aplicação. A escolha de cada padrão foi feita com base na intenção de simular funcionalidades típicas de frameworks e ambientes reais — mas com código totalmente manual e transparente, como parte do aprendizado de backend com Java puro.
Foi implementado um Service Locator dentro da pasta infra/config, com o objetivo de simular o funcionamento de um container de injeção de dependências, semelhante ao que frameworks como Spring oferecem.
Esse componente centraliza a criação e o fornecimento das dependências (repositórios, serviços, controladores), permitindo:
Essa abordagem foi essencial para manter a inversão de dependência, que é um dos pilares da arquitetura limpa.
Na implementação da persistência baseada em arquivos (CSV), foi utilizado o padrão Observer para simular um comportamento comum de banco de dados relacionais: deleção em cascata (cascade delete).
Como funciona:
A aplicação conta com uma camada de testes unitários bem estruturada, com foco principal nos casos de uso (use cases), que representam o coração da lógica de negócio. Isso segue a proposta da Arquitetura Limpa, onde os use cases devem ser totalmente independentes de detalhes externos (como banco de dados, interface gráfica ou frameworks).
O projeto foi construído com Maven como sistema de build e gerenciamento de dependências, utilizando Java 21 como linguagem alvo.
Desde o início, houve a preocupação em manter o projeto enxuto, evitando bibliotecas ou frameworks que pudessem mascarar a lógica de negócio. Todas as dependências foram escolhidas com critério, apenas para atender necessidades específicas, sem comprometer a clareza da arquitetura ou o aprendizado da base da linguagem.
Abaixo estão as únicas dependências externas utilizadas no projeto:
✅ Execução e Web
✅ Banco de Dados
✅ Testes
JUnit Jupiter (junit-jupiter): Framework de testes unitários padrão no ecossistema Java moderno (JUnit 5).
Mockito (mockito-core, mockito-junit-jupiter): Utilizado para criação de mocks e testes isolados dos componentes de negócio, reforçando a testabilidade do core desacoplado.
Essa configuração leve foi essencial para manter o controle total sobre a estrutura do código e entender com clareza os princípios fundamentais da construção de backends robustos em Java puro.