*Status ENCERRADO
- Primeiro commit dia: 07/02/2024 Ultimo commit dia 12/02/2024 - 5 dias corridos
⤴️ Índice- 📗 Sobre
- 💻 Rodando o Projeto
- 📰 Documentação da API
- 📊 Diagramas
- ✅ Testes
- 🪲 Debug
- 🕵️ Observabilidade
- 👏 Boas Práticas
- 🧠 ADR - Architecture Decision Records
- 🔢 Versões
- 🧰 Ferramentas
- 🤖 Uso de AI
- 🏁 Conclusão
Este repositório foi criado com a intenção de propor uma possível solução para o seguinte desafio:
👨💻 Case Dev Backend:
Vamos construir uma API? A API a ser desenvolvida deve conter rotas C.R.U.D. de produtos, seguindo um bom design de API.
- Requisitos:
- Rota para criação de produtos.
- Rota para consulta de produtos.
- Rota para atualização de produtos.
- Rota para exclusão de produtos.
Sinta-se livre para aprimorar a API e demonstrar seus conhecimentos.
Stack Back-end
- Postman
- GoLang
- Echo Framework
- MySQL
Padrões de qualidade.
- API Design
- Código Limpo (Clean Code)
- Padrões e convenções GoLang
Dada sua simplicidade, uma vez que se trata de um CRUD simples. Faz sentido utilizar Arquitetura de Duas Camadas o que aumenta o ritmo do desenvolvimento porém mantendo a qualidade do resultado final. Construido junto a uma visualização estilo Kanbam no Github Project
Foco em garantir estabilidade com TDD e uma implementação minima de CI no GitHub Actions, boas práticas de design de código e Observabilidade com Prometheus e Grafana garantindo a robustez necessária e devidos aprimoramentos
Exatamente por parecer ser "simples", é necessário ter um bom nível de qualidade.
O desenvolvimento e os testes foram executados no sistema Linux Ubuntu 20.04.6 LTS e testada em Linux Ubuntu 22.04.3 LTS.
Crie uma cópia do arquivo sample.env
com o nome .env
e rode o comando docker compose
(de acordo com sua versão do docker compose
) no diretorio raiz do projeto:
$ docker compose build
$ docker compose up
Dentro da pasta ./scripts/postman-collection/go-products-api.postman_collection.json encontra-se o arquivo JSON básico que pode ser importado no seu Postman para auxiliar em testes manuais e desenvolvimento.
Com a aplicação em execução, a rota de documentação Swagger fica disponível em https://localhost:8080/swagger/index.html#/ .
Acesse-a para realizar validações, caso prefira ao usar o Postman. Utilizar o Swagger-API também é uma boa maneira de tornar a aplicação aderente às boas práticas e ao design de API.
O cliente deve informar o UUID do recurso, seguindo as modernas práticas de desenvolvimento. Para validações, você pode utilizar um site gerador de UUIDs. Outras restrições e características dos recursos que podem ser criados, obtidos, listados e deletados podem ser visualizadas na seção 'Models' do Swagger.
Gerando a Documentação:
Para gerar a documentação, você precisa ter o Golang, o Swaggo e o projeto instalados localmente e executar o seguinte comando no diretório raiz do projeto:
swag init --generalInfo cmd/api/main.go -o ./api
✍️ Nota:
Existe um bug na geração da documentação do Echo Swagger. No arquivo ./api/docs.go está gerando duas propriedades na struct
swag.Spec
que não são reconhecidas. A solução encontrada no momento é remover manualmente essas propriedades a cada geração da documentação.LeftDelim: "{{", RightDelim: "}}",*A geração da documentação necessita de mais testes no S.O. Windows
graph LR
subgraph User Flow
ADMIN(["👤 User"])
ADMIN --> CREATE_PRODUCT("💻 Create Product")
ADMIN --> RETRIEVE_PRODUCT_LIST("💻 Retrieve Product List")
ADMIN --> RETRIEVE_PRODUCT("💻 Retrieve Product")
ADMIN --> UPDATE_PRODUCT("💻 Update Product")
ADMIN --> REMOVE_PRODUCT("💻 Remove Product")
end
subgraph go-products-api - Two Tier Architecture -
subgraph Handlers
API_CREATE_PRODUCT("🖥️ Create Product")
API_GET_PRODUCTS("🖥️ Get Products")
API_GET_PRODUCT("🖥️ Get Product by UUID")
API_UPDATE_PRODUCT("🖥️ Update Product by UUID")
API_DELETE_PRODUCT_BY_ID("🖥️ Delete Product by UUID")
end
subgraph Entities
ENTITY_PRODUCT("📄 Product")
end
subgraph DATABASE
CATALOGO_DB[("🗄️ MySQL <br/> catalogo-db")]
end
end
CREATE_PRODUCT -->|http POST| API_CREATE_PRODUCT
RETRIEVE_PRODUCT_LIST -->|http GET| API_GET_PRODUCTS
RETRIEVE_PRODUCT -->|http GET| API_GET_PRODUCT
UPDATE_PRODUCT -->|http PATCH| API_UPDATE_PRODUCT
REMOVE_PRODUCT -->|http DELETE| API_DELETE_PRODUCT_BY_ID
API_CREATE_PRODUCT-->ENTITY_PRODUCT
API_GET_PRODUCTS-->ENTITY_PRODUCT
API_GET_PRODUCT-->ENTITY_PRODUCT
API_UPDATE_PRODUCT-->ENTITY_PRODUCT
API_DELETE_PRODUCT_BY_ID-->ENTITY_PRODUCT
ENTITY_PRODUCT-->CATALOGO_DB
*Diagrama geral com baixo nível de fidelidade
Para testar localmente, é necessário ter o Go v1.21.1 instalado. Execute os para garantir o funcionamento correto da API e do banco de dados. Inicie o banco de dados na raiz do projeto usando docker-compose.
docker compose up mysql-go-products-api
Em outro terminal mas ainda na raiz do projeto, execute o comando:
go test -v ./ ./internal/handlers/
obtendo uma saida similar a seguinte:
Os testes também são executados como parte da rotina minima de CI do GitHub Actions, garantindo que versões estáveis sejam mescladas na branch principal. O badge TESTS_CI no cabeçalho do arquivo readme é uma ajuda visual para verificar rapidamente a integridade do desenvolvimento.
Utilizando o VSCode como editor de código (maiores informações aqui) com a seguinte configuração no arquivo .vscode/launch.json
:
{
"version": "0.2.0",
"configurations": [
{
"name": "Launch go-products-api",
"type": "go",
"request": "launch",
"mode": "debug",
"program": "${workspaceFolder}/cmd/api/main.go",
"cwd": "${workspaceFolder}",
"trace": "verbose",
},
{
"name": "Test Smoke Happy Path",
"type": "go",
"request": "launch",
"mode": "test",
"program":"${workspaceFolder}/main_smoke_test.go",
"trace": "verbose",
},
{
"name": "Test Integration Corner Cases",
"type": "go",
"request": "launch",
"mode": "test",
"program":"${workspaceFolder}/internal/handlers/productHandler_integration_test.go",
"trace": "verbose",
}
]
}
Altere a connection com a database para localhost em seu arquivo .env
DATABASE_HOST=localhost # mysql-go-products-api | localhost - To run localy (without all docker compose dependency) or debug use localhost
E suba o Banco de Dados antes de iniciar seu debug:
docker compose up mysql-go-products-api
Prometheus:
Apos rodar com sucesso o docker compose up
como visto anteriormente, acesse:
- Prometheus - https://localhost:9090/
Configurando o Grafana:
A primeira vez que executarmos o Grafana, entramos com usuário/senha
padrão de admin/admin
. Ele solicita a alteração da senha, para facilitar o desenvolvimento local, alteramos para admin/12345
.
- Grafana - https://localhost:3000/ (usuário/senha: admin/admin | admin/12345)
Uma vez dentro do Grafana em sua primeira execução, também precisamos criar uma conexão Datasource com o Prometheus (que acessamos acima). Procure por `Connections > Add New Connection` digite Prometheus no campo de Search, selecione-o, clique em `Add New Datasource` e configure-o com a URL: https://prometheus-go-products-api:9090 e clique no botão Save & test no final da página
Agora você pode usar o menu `Dashboards > New > Import` para importar o arquivo dash-go-products-api.json que está localizado no diretório: ./scripts/grafana-dashboards. Acesse o diretório em seu computador, clique e arraste o arquivo para o campo correto especificado pela tela Upload Dashboard JSON File
Quando adequadamente importado, o Dashboard estará disponível e responderá às solicitações que você pode simular pelo Postman
ou Swagger
.
A partir dessas métricas dos dashboards, temos uma ideia da saúde da API e quais são as reais necessidades de escala que ela deve ter em produção, o que nos dá uma ideia de quais arquiteturas e abordagens poderão ser utilizadas para atender às suas demandas, incluindo testes de carga, possíveis caches defensivos, filas, etc.
Nossas decisões de Arquitetura
e Design de Sistemas
devem sempre ser baseadas em dados!
- Swagger
- Github Project - Kanbam
- Layout padrão de projetos em Go
- Conventional Commits
- Keep a Changelog
- ADR - Architecture Decision Records
- Mermaid Diagrams
- Observabilidade com:
- 0001: Registro de Decisões de Arquitetura (ADR)
- 0002: Echo, Gorm e MySQL em API TDD com Arquitetura de Duas camadas
- 0003: Observabilidade com Prometheus e Grafana
As tags de versões estão sendo criadas manualmente a medida que o projeto avança com melhorias notáveis. Cada funcionalidade é desenvolvida em uma branch a parte (Branch Based, feature branch) quando finalizadas é gerada tag e mergeadas em master.
Para obter mais informações, consulte o Histórico de Versões.
-
Linguagem:
-
Framework & Libs:
-
Infra & Technologias
-
GUIs:
A imagem do cabeçalho desta página foi criada com o auxílio de inteligência artificial e um mínimo de retoque e construção no Gimp
Foi utilizado os seguinte prompt para sua criação no Bing IA:
Gopher com carrinho de compras
"gopher azul, simbolo da linguagem golang, empurrando um carinho de compras com caixas escrito REST, API, ECHO e Swagger dentro desse carrinho, estilo cartoon, historia em quadrinhos, fundo branco chapado para facilitar remoção"(sic)IA também é utilizada em minhas pesquisas e estudos como ferramenta de apoio; no entanto, artes e desenvolvimento são, sobretudo, atividades criativas humanas.
Contrate artistas para projetos comerciais ou mais elaborados e Aprenda Engenhosidade!
Conduzi o desafio no espírito do TDD e das melhores práticas que conheço. Preocupando-me com a coleta de métricas visando expansão futura, caso os dados apontem essa necessidade, e utilização de ferramentas que fazem parte do parque de tecnologias do proponente do desafio. Mantive-me focado nos prazos das tarefas e na qualidade do código desenvolvido.
Aqui deixo alguns pontos que imagino serem melhorias possíveis (alguns merecem seus próprios ADRs):
- Bug do Swagger, cuja solução manual que adotei impediu a geração da documentação automaticamente a cada subida da aplicação.
- Melhoria no script do Postman para melhor compartilhamento entre equipes.
- Montagem do
docker-compose
que poderia incluir automaticamente o Dashboard Grafana. - Melhorias no Log e utilização de algum centralizador de Logs como Grafana Loki ou Logstash
- Utilização de algum APM
- Processo de CD
- Testes de Performance e Carga que poderiam rodar em conjunto com nossa monitoria local. Gostaria de ter utilizado o Gatling com essa finalidade.
- A partir de tais testes, poderíamos decidir escalar:
- Implementação de um cache defensivo com Redis para consultas.
- Criação de produtos em fila RabbitMQ ou outro, com workers, permitindo o aumento de requisições na rota POST, se necessário.
Algumas das melhorias citadas (Gatling, Cache Defensivo e Filas) desenvolvi como POC em outro projeto que não está na solução "ótima", mas servem para nortear possibilidades.
Terei prazer em discutir sobre o assunto e sinta-se à vontade para visitar outros dos meus repositórios.
😊🚀