image

Acesse bootcamps ilimitados e +650 cursos pra sempre

60
%OFF

FL

Fabrício Leopoldino22/08/2025 12:52
Compartir

Organizando Seu Projeto Java com Package by Feature: Um Guia para Iniciantes

    image

    Introdução

    Se você já trabalhou em um projeto Java, provavelmente já viu a estrutura tradicional Package by Layer, onde o código é organizado por camadas técnicas:

    image

    Embora essa abordagem seja comum, ela pode trazer problemas à medida que o projeto cresce. Imagine ter que alterar uma funcionalidade e precisar navegar por várias pastas diferentes só para encontrar todas as classes relacionadas. Isso pode ser frustrante e levar a erros, especialmente em projetos grandes com muitos desenvolvedores. É aí que entra o Package by Feature, uma maneira mais eficiente de organizar seu código, agrupando tudo o que pertence a uma mesma funcionalidade em um único lugar. Essa abordagem promove uma visão mais centrada no domínio do negócio, facilitando o entendimento e a manutenção do código.

    Neste artigo, vamos explorar:  

    1. O que é Package by Feature?

    2. Por que ele é melhor que Package by Layer?

    3. Como aplicar na prática em um projeto Quarkus?

    4. A Rule of Three e quando compartilhar código entre features.

    5. Dicas para evitar armadilhas comuns ao adotar Package by Feature.

    1. O Que é Package by Feature?

    Em vez de separar o código por camadas (controller, service, repository), o Package by Feature organiza o projeto por funcionalidades de negócio. Por exemplo, em um sistema de e-commerce, teríamos:

    image

    Dentro de cada pacote, ficam todas as classes necessárias para aquela funcionalidade:

    - Controller (API REST)

    - Service (regras de negócio)

    - Repository (banco de dados)

    - Entidades (tabelas)

    - DTOs (objetos de transferência de dados)

    Isso torna o código mais fácil de entender e manter, pois tudo relacionado a uma funcionalidade está no mesmo lugar. Além disso, essa organização reflete melhor o domínio do negócio, alinhando o código com os requisitos reais do sistema.

    2. Por Que Package by Feature é Interessante?

    A abordagem Package by Feature oferece várias vantagens em comparação com Package by Layer. Aqui estão os principais benefícios:

    - Facilita a Manutenção : Se você precisa alterar algo em Pedidos, tudo está no pacote order. Não precisa procurar em várias pastas, o que economiza tempo e reduz erros.

    - Melhora a Coesão: Classes que trabalham juntas ficam juntas, o que aumenta a clareza e reduz o acoplamento entre diferentes partes do sistema.

    - Reduz Conflitos no Git: Diferentes times podem trabalhar em features diferentes sem se atrapalhar, já que cada funcionalidade está isolada em seu próprio pacote.

    - Prepara para Microsserviços: Se um dia o projeto crescer, cada feature pode ser extraída para um serviço independente com mínimo esforço, já que o código já está organizado por funcionalidade.

    - Alinhamento com o Domínio: Essa abordagem reflete diretamente o domínio do negócio, facilitando a comunicação entre desenvolvedores e stakeholders não técnicos.

    3. Como Aplicar em um Projeto Quarkus?

    Vamos criar um exemplo simples de um sistema de loja online usando Quarkus, um framework Java moderno otimizado para ambientes nativos e em nuvem.

    Estrutura do Projeto

    image

    Como exemplo, vamos implementar a funcionalidade do usuário

    DTO (Data Transfer Object)

    O DTO é um objeto usado para transferir dados entre camadas ou sistemas, geralmente entre a camada de apresentação (Resource) e a camada de negócio (Service), ou entre a aplicação e sistemas externos (como APIs). Ele encapsula os dados de forma simplificada, evitando a exposição de detalhes internos da entidade. Com o objetivo de reduzir o acoplamento, otimizar a comunicação (ex.: enviando apenas os dados necessários) e permitir transformações ou validações específicas para a interface de entrada/saída.


    image

    Entity

    A entidade representa o modelo de dados do domínio, geralmente mapeado diretamente para uma tabela no banco de dados (em aplicações com ORM, como Hibernate). Ela contém os atributos e as regras básicas do objeto de negócio. Com o objetivo de refletir a estrutura do dado persistente e encapsular a lógica de domínio diretamente relacionada aos dados (ex.: validações simples ou getters/setters).

    image

    Repository

    O repositório é responsável por encapsular o acesso aos dados, fornecendo métodos para realizar operações de persistência (como salvar, buscar, atualizar ou deletar) no banco de dados. Ele atua como uma ponte entre a camada de negócio (Service) e a camada de dados (Entity). Com o objetivo de abstrair a lógica de acesso ao banco de dados, permitindo que a camada de serviço trabalhe com objetos do domínio sem se preocupar com detalhes de infraestrutura.

    image

    Service

    A camada de serviço contém a lógica de negócio da aplicação. Ela orquestra as operações, coordenando chamadas ao repositório, validações complexas, regras de negócio e interações com outras funcionalidades. Com o objetivo de centralizar a lógica de negócio, garantindo que as regras sejam aplicadas de forma consistente e que a funcionalidade seja independente de detalhes de infraestrutura ou apresentação.

    image

    Resource

    O Resource (ou Controller, em algumas terminologias) é a camada de apresentação, responsável por expor a funcionalidade ao mundo externo, geralmente via endpoints de API (ex.: REST). Ele recebe requisições, converte os dados recebidos em DTOs, chama os serviços apropriados e retorna respostas ao cliente. Com o objetivo de atuar como a interface de entrada/saída da funcionalidade, lidando com protocolos de comunicação (como HTTP) e transformando dados entre o formato externo (JSON, por exemplo) e os DTOs internos.


    image

    Perceba que tudo sobre usuários está em um único lugar! Essa organização torna mais fácil adicionar novas funcionalidades, como autenticação ou gerenciamento de perfis, sem afetar outras partes do sistema.

    4. A Rule of Three – Quando Compartilhar Código?

    Uma dúvida comum é: E se várias features precisarem do mesmo código?  

    Aqui entra a “Rule of Three (Regra do Três):  Se você repetir o mesmo código 3 vezes, extraia para um lugar comum.

    Essa regra ajuda a evitar a criação prematura de código compartilhado, que pode levar a abstrações desnecessárias e acoplamento indesejado.

    Exemplo Prático

    Suponha que três features (order, payment, product) precisem gerar um código aleatório:

    1. Primeira vez (em OrderService):  

    image

    2. Segunda vez (em PaymentService)

    image  

      

    3. Terceira vez (em ProductService):  

    image

      

    Agora, em vez de repetir, extraímos para core:  

    image

     

      

    Agora, cada feature pode usar:

    image

      

    Assim, evitamos duplicação sem criar compartilhamento desnecessário.

    5. Dicas para Evitar Armadilhas Comuns

    Ao adotar Package by Feature, algumas armadilhas podem surgir. Aqui estão algumas dicas para evitá-las:

    Não Crie Pacotes Demasiado Genéricos: Evite pacotes como `utils` ou `common` para tudo. Use a Rule of Three para decidir o que realmente deve ser compartilhado.

    Evite Acoplamento Excessivo: Mantenha as features o mais independentes possível. Se uma feature depende muito de outra, talvez elas devam ser uma única feature.

    Não Ignore o Domínio: Antes de criar pacotes, entenda bem o domínio do negócio. Converse com stakeholders para garantir que as features reflitam os conceitos reais do sistema.

    Use Ferramentas de Refatoração: Ferramentas como IntelliJ IDEA ou Eclipse facilitam a reorganização do código para Package by Feature sem quebrar dependências.

    Teste a Organização: À medida que o projeto cresce, revise a estrutura dos pacotes para garantir que ela ainda faz sentido. Ajuste conforme necessário.

    6. Conclusão

    O Package by Feature é uma maneira mais intuitiva e sustentável de organizar projetos Java, especialmente com frameworks modernos como Quarkus. Ele alinha o código com o domínio do negócio, facilita a manutenção e prepara o projeto para escalar.

    Benefícios principais:

    - Código mais fácil de encontrar e manter.

    - Menos conflitos no time.

    - Preparado para escalar.

    - Melhor alinhamento com o domínio do negócio

    Dica final:

    Comece com features isoladas e, usando a Rule of Three, identifique o que realmente deve ser compartilhado. Se possível, valide a estrutura com o time para garantir que todos estão alinhados. 

    7. Referências

    • FELIX, Marc Nuri San. Full Stack Quarkus and React: Hands-on full stack web development with Java, React, and Kubernetes. Birmingham: Packt Publishing, 2022.
    • GONCALVES, Antonio. Practising Quarkus. Independently published
    • HAUER, Philipp. Package by Feature. Philipp Hauer's Blog, 2020. Disponível em: https://phauer.com/2020/package-by-feature/. Acesso em: 20 ago. 2025.
    • O'HANLEY, John. Package by feature, not layer. Java Practices, 3.012, [s.d.]. Disponível em: http://www.javapractices.com/topic/TopicAction.do?Id=205. Acesso em: 20 ago. 2025.
    Compartir
    Recomendado para ti
    Ri Happy - Front-end do Zero #2
    Avanade - Back-end com .NET e IA
    Akad - Fullstack Developer
    Comentarios (0)