diff --git a/README.md b/README.md index d4d8404..12a4a3b 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Controle de Estoque CLI Aplicação de linha de comando (CLI) em Go para gerenciar um estoque de produtos. -Projeto de estudo focado em organização de código em camadas (MVC) e no uso de +Projeto de estudo focado em organização de código em camadas e no uso de estruturas de dados nativas do Go. ## Funcionalidades @@ -16,13 +16,13 @@ estruturas de dados nativas do Go. Requer [Go](https://go.dev/) 1.26 ou superior instalado. ```bash -go run . +go run ./cmd/cli ``` Para compilar um binário: ```bash -go build -o controle-de-estoque +go build -o controle-de-estoque ./cmd/cli ./controle-de-estoque ``` @@ -43,40 +43,66 @@ Ao **atualizar**, informe o ID do produto e o campo desejado ## Estrutura do projeto -O código é organizado em camadas, separando responsabilidades: +O código é organizado em camadas, cada uma dependendo apenas da camada +mais interna: ``` . -├── main.go # Ponto de entrada: monta as dependências e inicia a CLI -├── controller/ -│ └── controller.go # Orquestra o fluxo entre a entrada do usuário e o modelo -├── view/ -│ └── view.go # Entrada e saída no terminal (menus, leitura, exibição) -└── model/ - └── inventory.go # Regras de negócio e armazenamento dos produtos (map em memória) +├── cmd/ +│ └── cli/ +│ └── main.go # Ponto de entrada: monta as dependências e inicia a CLI +└── internal/ + ├── cli/ + │ ├── app.go # Loop do menu: lê a opção e chama o handler + │ ├── handlers.go # Entrada e saída no terminal de cada operação + │ └── menu.go # Exibição do menu + ├── service/ + │ └── inventory_service.go # Regras de negócio (validações, atualização por campo) + ├── repository/ + │ ├── inventory_repository.go # Interface: o contrato de persistência + │ └── in_memory/ + │ └── inventory_repository.go # Implementação em memória (map) + └── model/ + └── product.go # Domínio: Product e ProductInput ``` -- **model** — define `Product` e `Inventory`, guardando os produtos em um - `map[ProductID]Product` -- **view** — responsável por toda interação com o terminal. -- **controller** — recebe a opção do usuário e chama as operações do modelo. +- **model** — define `Product` e `ProductInput`, sem lógica nem dependências. +- **repository** — declara a interface `InventoryRepository` (o *contrato*). + A pasta `in_memory` traz uma implementação que guarda tudo em um + `map[int]*Product`. +- **service** — concentra as regras de negócio (nome obrigatório, quantidade não + negativa, conversão do campo a atualizar). Depende apenas da **interface** do + repository, nunca de uma implementação concreta. +- **cli** — responsável por toda interação com o terminal. Lê a opção do usuário + e chama o service correspondente. +- **cmd/cli/main.go** — o único lugar que conhece todas as camadas: cria o + repository, injeta no service, injeta no app e roda. + +Como o service depende só da interface, trocar a persistência (Postgres, arquivo +JSON, etc.) exige apenas uma nova implementação de `InventoryRepository` e a +troca de uma linha no `main.go` — nenhuma outra camada muda. > Os dados são mantidos apenas em memória: ao encerrar o programa, o estoque é perdido. ## Conceitos aprendidos -- **Arquitetura em camadas (MVC)** — separação de responsabilidades entre - `model`, `view` e `controller`, mantendo cada parte independente. -- **Structs e métodos** — modelagem de dados com `Product`/`Inventory` e métodos - (`func (e *Inventory) ...`). -- **Maps** — armazenamento em `map[ProductID]Product` para busca, atualização e +- **Arquitetura em camadas** — separação de responsabilidades entre `model`, + `repository`, `service` e `cli`, mantendo cada parte independente. +- **Interfaces** — `InventoryRepository` define um contrato que qualquer + implementação pode satisfazer, permitindo trocar a persistência sem tocar no + resto do código. +- **Injeção de dependência** — cada camada recebe suas dependências prontas + (`NewInventoryService(repo)`, `NewApp(svc)`), em vez de criá-las por conta própria. +- **Layout de projeto em Go** — `cmd/` para os executáveis e `internal/` para o + código privado do módulo. +- **Structs e métodos** — modelagem de dados com `Product` e métodos com + receiver (`func (s *InventorySevice) ...`). +- **Maps** — armazenamento em `map[int]*Product` para busca, atualização e remoção, o padrão *comma-ok* (`v, ok := m[k]`) e a função embutida `delete(m, chave)`. -- **Tipos nomeados** — criação de `type ProductID int` para dar semântica aos - identificadores. -- **Leitura de entrada** — uso de `bufio.Reader` +- **Leitura de entrada** — uso de `bufio.Scanner` para ler linha a linha do terminal. - **Tratamento de strings** — `strings.TrimSpace` para limpar os espaços e quebras de linhas da entrada e `strconv` (`Atoi`, `ParseFloat`) para converter texto em tipos numéricos. -- **Tratamento de erros** — múltiplos retornos `(valor, error)` e verificação com - `if err != nil`. +- **Tratamento de erros** — múltiplos retornos `(valor, error)`, verificação com + `if err != nil` e erros nomeados (`ErrNotFound`). - **Formatação de saída** — `fmt.Printf` com verbos como `%d`, `%s` e `%.2f`.