Hoje iniciamos mais uma pequena série aqui no blog, onde vamos implementar uma pequena API utilizando arquitetura hexagonal. Essa série será dividida em pelo menos quatro posts, sendo esse primeiro a definição da estrutura de pastas.
Se você ainda não conhece muito bem essa arquitetura, convido você a ler o post onde explico a parte teórica da arquitetura hexagonal.
Agora que estamos todos no mesmo ponto, vamos começar a definir a estrutura de pastas desse pequeno projeto.
pkg
No root do projeto, como já é de costume, precisamos de uma pasta onde ficarão as implementações que podem ser compartilhadas com outros projetos, ou seja, implementações de packages que não tem nenhuma regra de negócio.
Por padrão, chamamos essa pasta de pkg
. Dentro dela, serão criados os packages para conexão com o banco de dados, conexão com filas, logs, agentes de observabilidade e etc.
Como minha idéia para esse projeto é utilizar Mongodb como banco de dados, dentro da pasta pkg
, precisamos criar a pasta mongo
, onde implementaremos a conexão o banco.
internal
Na linguagem Go, para evitar que algum package seja importado por outros projetos, precisamos implementá-los dentro da pasta internal
. Esse é o único nome de pasta que tem um comportamento diferente na linguagem.
Sendo assim, dentro dessa pasta vamos criar todos os packages que implementem as camadas core, port e adapter da arquitetura hexagonal.
category
Como vamos implementar uma simples API com CRUD de categorias, dentro da pasta internal
, teremos uma pasta category
com dois arquivos, entity.go e ports.go. Nesses arquivos vamos definir a entidade e interfaces do package, respectivamente.
Ainda dentro da pasta category
, precisamos criar mais duas pastas. A primeira, que se chamará handlers
, e será utilizada para implementar os adapters do tipo driver. Já a segunda, que se chamará repository
, será utilizada para implementar os adapters do tipo driven.
cmd
Nessa pasta, que também é criada no root do projeto, é onde ficam os packages com implementações de entrada dos programas, ou seja, o package e função main.
Repare que eu disse programas ao invés de programa. Isso por que, em implementações Go, é muito comum um único repositório conter mais de um programa. Além de facilitar a manutenção, conseguimos reutilizar código de uma forma muito mais simples.
Sendo assim, como nessa série vamos implementar uma API, dentro da pasta cmd
, criamos uma pasta api
com um arquivo main.go dentro.
Conclusão
Ao fim desse primeiro post, ficamos com a seguinte estrutura de pastas e arquivos definida:
root | |-- cmd | |-- api | |-- main.go |-- internal | |-- category | |-- handlers | |-- repository | |-- entity.go | |-- ports.go |-- pkg | |-- mongo |-- go.mod |-- go.sum
A meu ver, essa separação deixa muito claro onde está cada componente e camada da aplicação.
Se você ainda não é inscrito na nossa newsletter, não deixe de se inscrever para não perder os próximos posts, onde vamos implementar o package mongo. Até a próxima!
como ficaria a questão dos package com muitos modulos? Exe: user, post… Não teria muito package com o nome igual não?
Teria os packages `handlers` e `repository` para cada um desses packages que você exemplificou.
No entanto, ao fazer o import deles podemos usar um alias, como por exemplo `uh` para o handler do user e `ph` para o handler de post.
Tiago, gostei da sua proposta de organização de pastas. Uma dúvida: se eu tiver outra entidade, por exemplo “pessoa”, eu não poderia ter os pacotes “handlers” e “repository” novamente, pois eles entrariam em conflito com os da entidade “category”. Como você resolveria esse problema?
Pode criar esses packages sim, afinal eles estão dentro da pasta “pessoa”.
Na hora de fazer o import deles, por exemplo na main, podemos utilizar um alias para não dar conflito de nomes.
Bacana, gostei da ideia. Vou tentar aqui! Obrigado.
Organizei os pacotes como você mencionou, Tiago. Está ficando legal. Outra dúvida aqui: onde você colocaria os serviços (services) ou casos de uso? Dentro do pacote de cada entidade (categoria, pessoa, etc)?
[…] você ainda não leu, convido a ler o post onde definimos a organização das pastas e arquivos desse projeto utilizando arquitetura […]
[…] Definimos a estrutura de pastas e arquivos do projeto; […]