Tech Challenge para avaliação da Fase III da Pós Graduação em Arquitetura e Desenvolvimento Java.
- 📑 Tech Chalenge
Faculdade FIAP
Pós-Graduação em Arquitetura e Desenvolvimento Java
Fábio de Oliveira Sales |
---|
Antes de começar, você precisará ter as seguintes ferramentas instaladas em sua máquina:
- Java 17
- Git
- Docker
- IDE de desenvolvimento:
- Eclipse
- IntelliJ IDEA
- VSCode
- Outras
- Navegador:
- Google Chrome
- Outro
- Postman, CURL ou utilize o Swagger
- Abrir o terminal
- Git Bash
- CMD
- Bash
- Outros
- Clonar repositório. git https://github.com/fsales/fiap-tech-chalenge-fase3.git.
git clone https://github.com/fsales/fiap-tech-chalenge-fase3.git fiap-tech-chalenge-fase3
No diretório
/fiap-tech-challenge-fase3/docker-compose
você encontrará o arquivodocker-compose-parktech.yaml
com as definições da aplicação Park Tech.
- Park Tech utilizando o Docker.
- Iniciar o container do Park Tech
docker-compose -f ./docker-compose/docker-compose-parktech.yaml up -d --force-recreate
- Parar o container do MongoDB
docker-compose -f ./docker-compose/docker-compose-parktech.yaml down -v
-
As configurações do Park Tech está definido no arquivo:
A variável de ambiente
PARK_TECH_SPRING_DOCKER_COMPOSE_ENABLE
deve ser configurado com o valor false
- Acessar o diretório
fiap-tech-chalenge-fase3/park-tech
.
cd /fiap-tech-chalenge-fase3/park-tech
- Construir o projeto utilizando o maven.
./mvnw clean package
- MongoDB utilizando o Docker.
No diretório
/fiap-tech-challenge-fase3/docker-compose
você encontrará o arquivodocker-compose-mongodb.yaml
com as definições doMongoDB
e do clienteMongo Express
.
- Iniciar o container do MongoDB
docker-compose -f ./docker-compose/docker-compose-mongodb.yaml up -d
- Parar o container do MongoDB
docker-compose -f ./docker-compose/docker-compose-mongodb.yaml down -v
-
As configurações do MongoDB e Mongo Express estão definidos no arquivo:
Caso a variável de ambiente
PARK_TECH_PROFILE_ENVIRONMENT
esteja definida com o valordev
, o plugin do Spring Boot Docker Compose iniciará automaticamente oscontêineres
que estão definidos no arquivodocker-compose-mongodb.yaml
localizado no diretório/fiap-tech-challenge-fase3/docker-compose
.
-
Importar o projeto
fiap-tech-chalenge-fase3/park-tech
na sua IDE de desenvolvimento. -
Configure as variáveis de ambiente na IDE de desenvolvimento.
- Variáveis:
-
PARK_TECH_MONGODB_DATABASE:
Nome do Banco de Dados utilizado pela aplicação.
-
PARK_TECH_MONGODB_URI:
URI de conexão ao seu banco de dados MongoDB.
-
PARK_TECH_PROFILE_ENVIRONMENT:
Perfis de aplicativos usando a propriedade spring.profiles.active no arquivo application.yml. Isso permite que você defina diferentes configurações e comportamentos para diferentes ambientes (por exemplo, desenvolvimento, produção, teste).
- Valores possíveis para a variável
PARK_TECH_PROFILE_ENVIRONMENT
:- dev
- cloud-atlas
- Valores possíveis para a variável
-
- Variáveis:
O usuário e senha do
MongoDB
foram definidos no/fiap-tech-challenge-fase3/docker-compose/mongo-config/.env-mongodb
e podem ser consultados no arquivo .env-mongoexpress.
A arquitetura hexagonal, proposta por Alistair Cockburn em seu artigo Hexagonal Architecture1, inicialmente chamada de Ports And Adapters, é uma proposta arquitetural em camadas que visa proteger a lógica de negócios do sistema. A inovação dessa abordagem está na compreensão de Cockburn de que não há uma grande diferença entre como a interface do usuário e o banco de dados interagem com o aplicativo; ambos são elementos externos que podem ser substituídos a qualquer momento.
Para mitigar a dependência direta desses fatores externos (como interface de usuário, bancos de dados, integrações e filas), Cockburn introduz o conceito de "portas", que são interfaces aplicando o princípio de inversão de dependência. Estas são interfaces que a lógica de negócio conhece. Além disso, ele propõe os "adaptadores", que são as implementações dessas portas, lidando com as dependências externas.
Essencialmente, a arquitetura hexagonal é um padrão que separa a lógica de negócios do sistema das preocupações técnicas, como a interação com o usuário ou o acesso ao banco de dados. Ela se baseia na ideia de que uma aplicação é composta por "portas" de entrada e saída, que possibilitam a comunicação com o mundo exterior, e "adaptadores", que convertem essas informações em um formato compreensível para a aplicação e vice-versa.
Exemplo da Organização do Projeto
├── src
└── main
└── java
└── br
└── com
└── fsales
└── parktech
├── adapters
│ ├── in
│ │ └── controller
│ │ ├── condutor
│ │ │ ├── CondutorController.java
│ │ │ ├── mapper
│ │ │ │ └── CondutorMapper.java
│ │ │ ├── request
│ │ │ │ ├── CondutorRequest.java
│ │ │ │ ├── DadosAtualizarCondutorRequest.java
│ │ │ │ └── ListarCondutorRequest.java
│ │ │ └── response
│ │ │ └── CondutorResponse.java
│ │ ├── exception
│ │ │ ├── ParkTechControlerExceptionHandler.java
│ │ │ └── response
│ │ │ ├── ValidationErrorResponse.java
│ │ │ └── ViolationResponse.java
│ │ ├── ParktechResource.java
│ │ └── veiculo
│ │ ├── mapper
│ │ │ └── VeiculoMapper.java
│ │ ├── request
│ │ │ ├── DadosAtualizarVeiculoRequest.java
│ │ │ ├── VeiculoFiltroConsultaPaginadaRequest.java
│ │ │ └── VeiculoRequest.java
│ │ ├── response
│ │ │ └── VeiculoResponse.java
│ │ └── VeiculoController.java
│ └── out
│ ├── client
│ │ ├── ConsultarEnderecoPorCepClient.java
│ │ └── response
│ │ └── EnderecoResponse.java
│ ├── condutor
│ │ ├── DeleteCondutorAdapter.java
│ │ ├── FindCondutorAdapter.java
│ │ ├── FindCondutorByIdAdapter.java
│ │ ├── InsertCondutorAdapter.java
│ │ └── UpdateCondutorAdapter.java
│ ├── endereco
│ │ └── ConsultarEnderecoPorCepAdapter.java
│ ├── repository
│ │ ├── CondutorRepository.java
│ │ ├── CondutorRepositoryCustom.java
│ │ ├── entity
│ │ │ ├── CondutorEntity.java
│ │ │ ├── ContatoEntity.java
│ │ │ ├── EnderecoEntity.java
│ │ │ ├── PessoaEntity.java
│ │ │ ├── PessoaFisicaEntity.java
│ │ │ └── VeiculoEntity.java
│ │ ├── impl
│ │ │ ├── CondutorRepositoryCustomImpl.java
│ │ │ └── VeiculoRepositoryCustomImpl.java
│ │ ├── mapper
│ │ │ ├── CondutorEntityMapper.java
│ │ │ ├── EnderecoResponseMapper.java
│ │ │ └── VeiculoEntityMapper.java
│ │ ├── PageRepositoryCustom.java
│ │ ├── VeiculoRepository.java
│ │ └── VeiculoRepositoryCustom.java
│ └── veiculo
│ ├── DeleteVeiculoAdapter.java
│ ├── FindVeiculoAdapter.java
│ ├── FindVeiculoByIdAdapter.java
│ ├── InsertVeiculoAdapter.java
│ └── UpdateVeiculoAdapter.java
├── application
│ ├── core
│ │ ├── domain
│ │ │ ├── Condutor.java
│ │ │ ├── Contato.java
│ │ │ ├── Endereco.java
│ │ │ ├── enumeration
│ │ │ │ └── EstadoEnum.java
│ │ │ ├── funcionalinterface
│ │ │ │ └── Mapper.java
│ │ │ ├── paginacao
│ │ │ │ └── Page.java
│ │ │ ├── Pessoa.java
│ │ │ ├── PessoaFisica.java
│ │ │ ├── Veiculo.java
│ │ │ └── VeiculoFiltroConsultaPaginada.java
│ │ └── usecase
│ │ ├── condutor
│ │ │ ├── DeleteCondutorUseCase.java
│ │ │ ├── FindCondutorByIdUseCase.java
│ │ │ ├── FindCondutorUseCase.java
│ │ │ ├── InsertCondutorUseCase.java
│ │ │ └── UpdateCondutorUseCase.java
│ │ └── veiculo
│ │ ├── DeleteVeiculoUseCase.java
│ │ ├── FindVeiculoByIdUseCase.java
│ │ ├── FindVeiculoUseCase.java
│ │ ├── InsertVeiculoUseCase.java
│ │ └── UpdateVeiculoUseCase.java
│ └── ports
│ ├── in
│ │ ├── condutor
│ │ │ ├── DeleteCondutorInputPort.java
│ │ │ ├── FindCondutorByIdInputPort.java
│ │ │ ├── FindCondutorInputPort.java
│ │ │ ├── InsertCondutorInputPort.java
│ │ │ └── UpdateCondutorInputPort.java
│ │ └── veiculo
│ │ ├── DeleteVeiculoInputPort.java
│ │ ├── FindVeiculoByIdInputPort.java
│ │ ├── FindVeiculoInputPort.java
│ │ ├── InsertVeiculoInputPort.java
│ │ └── UpdateVeiculoInputPort.java
│ └── out
│ ├── condutor
│ │ ├── ConsultarEnderecoPorCepOutputPort.java
│ │ ├── DeleteCondutorOutputPort.java
│ │ ├── FindCondutorByIdOutputPort.java
│ │ ├── FindCondutorOutputPort.java
│ │ ├── InsertCondutorOutputPort.java
│ │ └── UpdateCondutorOutputPort.java
│ └── veiculo
│ ├── DeleteVeiculoOutputPort.java
│ ├── FindVeiculoByIdOutputPort.java
│ ├── FindVeiculoOutputPort.java
│ ├── InsertVeiculoOutputPort.java
│ └── UpdateVeiculoOutputPort.java
├── config
│ ├── condutor
│ │ ├── DeleteCondutorConfig.java
│ │ ├── FindCondutorByIdConfig.java
│ │ ├── FindCondutorConfig.java
│ │ ├── InsertCondutorConfig.java
│ │ └── UpdateCondutorConfig.java
│ ├── feign
│ │ └── FeignConfiguration.java
│ ├── GroupedOpenApiConfig.java
│ └── veiculo
│ ├── DeleteVeiculoConfig.java
│ ├── FindVeiculoByIdConfig.java
│ ├── FindVeiculoConfig.java
│ ├── InsertVeiculoConfig.java
│ └── UpdateVeiculoConfig.java
├── infrastructure
│ ├── configuration
│ │ ├── OpenAPIConfiguration.java
│ │ └── SwaggerConfigProperties.java
│ └── properties
│ └── ParktechProperties.java
└── ParkTechApplication.java
Adapters
Adaptadores na arquitetura hexagonal são componentes que traduzem dados e chamadas entre a aplicação e sistemas externos. Por exemplo, um adaptador pode converter dados do formato interno da aplicação para um formato compreendido por um banco de dados externo, permitindo que a lógica de negócios permaneça independente da implementação específica do banco de dados.
Esses adaptadores são a implementação das dependências externas, como a interface do usuário/entrada e a infraestrutura/saída.
-
adapter/inbound: Nesta parte, encontram-se todos os controladores responsáveis pela entrada de dados na aplicação.
-
adapter/outbound: Aqui estão todas as integrações externas, como repositórios e integrações de API, que cuidam da saída de dados da aplicação.
Domain
O "domain" (domínio) na arquitetura hexagonal representa a parte central da aplicação, onde são implementadas as regras de negócios fundamentais. Nesta camada, a lógica específica da aplicação é encapsulada de forma independente de qualquer tecnologia ou detalhes de implementação externos, como interfaces de usuário ou bancos de dados.
Neste contexto, as classes no domínio não possuem dependências externas, incluindo dependências de estrutura. A estrutura do domínio pode ser organizada da seguinte forma:
-
domain/domain: Aqui estão todas as entidades e objetos do domínio, sem nenhuma dependência externa.
-
domain/ports/inbound: Nesta parte, são definidas as interfaces que representam os casos de uso da aplicação.
-
domain/ports/outbound: Esta seção contém as interfaces que representam os serviços externos utilizados pela aplicação. Importante notar que aqui não há nenhuma nomenclatura ligada a tecnologias específicas.
-
domain/usecase: Nesta área, ocorre a implementação concreta dos casos de uso da aplicação.
O desenvolvimento deste projeto está fundamentado na Arquitetura Hexagonal2, onde a principal preocupação reside em aplicar corretamente os conceitos de portas e adaptadores, estando integralmente alinhado com o princípio de inversão de dependências. É crucial observar que os casos de uso, interfaces (portas) e domínios não devem apresentar dependências externas, incluindo aquelas relacionadas ao framework utilizado. A proposta é assegurar que a lógica de negócios esteja completamente isolada desses fatores externos, garantindo assim sua integridade e independência.
CI/CD é a abreviação de Continuous Integration/Continuous Delivery, traduzindo para o português: integração e entrega contínuas. Trata-se de uma prática de desenvolvimento de software que visa tornar a integração de código mais eficiente por meio de builds e testes automatizados. 3
GitHub Actions é uma plataforma de integração contínua e entrega contínua (CI/CD) que permite automatizar sua compilação, testes e pipeline de implantação. É possível criar fluxos de trabalho que compilarão e testarão cada solicitação de pull em seu repositório ou implantarão solicitações de pull mescladas em produção. 2
- Publicação da Imagem no Docker Hub - Branch Develop 4.
- No início do desenvolvimento, é criada uma branch
feature/w.x.y.z
a partir da branchdevelop
. - Ao finalizar o desenvolvimento, é aberto um
Pull Request
da branchfeature/w.x.y.z
paradevelop
. - Quando esse
PR
formesclado
, o fluxo de trabalhogit-flow-publish-image-develop.yaml
do GitHub Actions será acionado, gerando a imagemDocker
e publicando-a noDocker Hub
.
- Criação da Release - Branch Main 4.
- Quando a validação das funcionalidades for realizada, é criada uma branch
release/w.x.y.z
a partir da branchdevelop
. - Após mesclar esse
PR
, o fluxo de trabalhocreate-release.yaml
do GitHub Actions será acionado, gerando a imagemDocker
e publicando-a noDocker Hub
, além de criar automaticamente umatag
de versãow.x.y.z
.
- Endereço do Docker Hub:
Secrets são variáveis que você cria em uma organização, repositório ou ambiente de repositório. Os Secrets que você cria estão disponíveis para utilização nos fluxos de trabalho em GitHub Actions. GitHub Actions só poderá ler um Secret se você incluí-lo explicitamente em um fluxo de trabalho.
- Lista dos secrets que devem ser configurados no repositório:
- Repositório Github:
- GIT_TOKEN
- GIT_EMAIL
- DockerHub:*
- DOCKERHUB_USERNAME
- DOCKERHUB_TOKEN
- Park-Tech:
- PARK_TECH_PROFILE_ENVIRONMENT
- PARK_TECH_MONGODB_URI
- PARK_TECH_MONGODB_DATABASE
- PARK_TECH_BASIC_AUTH_NAME
- PARK_TECH_BASIC_AUTH_PASSWORD
- URI_DATABASE
- AWS
- AWS_ACCESS_KEY_ID
- AWS_SECRET_ACCESS_KEY
- Publicação da versão
Escolhemos o Amazon Elastic Container Service (ECS)
como plataforma para hospedar
nossa aplicação na nuvem da AWS
. Para garantir uma implantação eficaz e segura, optamos por utilizar o Terraform
,
uma ferramenta que nos permite provisionar toda a infraestrutura
necessária e publicar o contêiner no ECS. O processo
de execução do Terraform é cuidadosamente gerenciado pelo fluxo de trabalho aws-terraform-deploy-manual.yaml
no GitHub Action
s, sendo ativado manualmente para garantir um controle preciso sobre a implantação. Além disso, se
necessário, podemos reverter o processo de implantação acionando o fluxo de
trabalho aws-terraform-undeploy-manual.yaml
.
O sistema Park Tech é responsável por gerenciar o tempo de estacionamento dos veículos, calcular os valores devidos e armazenar essas informações para fins de fiscalização.
- ViaCEP
O ViaCEP é um serviço para consulta gratuita de código postais de endereçamento do Brasil.
API de condutores
: Os condutores podem se registrar no sistema, associando seus dados pessoais, como nome, endereço e informações de contato.API de veiculos
: Os condutores podem registrar no sistema vários veículos.API de estacionamentos
: tem como objetivo permite iniciar o período de estacionamento, oferecendo opções de tempo fixo ou por hora.
Descrição dos endpoints disponíveis na aplicação Park Tech.
Para fazer as requisições HTTP pode ser utilizado:
Durante o desenvolvimento do projeto, não enfrentei dificuldades significativas com o Framework Spring. Por essa razão, pude concentrar-me em desenvolver funcionalidades básicas e aprimorar minhas habilidades em atividades para as quais não tinha experiência anteriormente. Introduzi no projeto as seguintes melhorias:
-
Utilização do banco de dados MongoDB: Optei por utilizar o MongoDB como parte do nosso sistema de gerenciamento de banco de dados, explorando uma abordagem diferente e valiosa para armazenar dados.
-
Implementação de uma Infraestrutura na Nuvem AWS utilizando o Terraform: Aproveitei a oportunidade para utilizar a nuvem pública, específicamente a AWS, e empregar o Terraform para provisionar e disponibilizar nossa infraestrutura na nuvem, proporcionando escalabilidade e flexibilidade ao projeto.
-
Criação de um Pipeline de CI/CD utilizando o GitHub Actions: Estabeleci um Pipeline de Integração Contínua e Entrega Contínua (CI/CD) utilizando o GitHub Actions. Esse pipeline automatizado realiza diversas etapas essenciais, como o build do projeto, a geração da imagem Docker e sua publicação no Docker Hub, a criação de tags e releases no GitHub, além de provisionar recursos com o Terraform e publicá-los na nuvem da AWS, proporcionando uma implantação contínua e confiável.
-
Implementação dos Conceitos Básicos da Arquitetura Hexagonal: Iniciei o estudo para aplicar os conceitos da arquitetura hexagonal, melhorando a estrutura do projeto para torná-lo mais simples de entender e modificar.
Nesta fase do projeto, percebo um grande avanço em meu conhecimento e saio extremamente satisfeito com os resultados alcançados. Estou confiante de que essas melhorias enriqueceram significativamente minha experiência e habilidades no desenvolvimento de software.