Existem práticas recomendadas para organização de pacotes (Java)? [fechadas]

201

Há pouco tempo, vi uma pergunta respondida aqui sobre a organização refinada dos pacotes java. Por exemplo, my.project.util, my.project.factory, my.project.service, etc.

Agora não consigo encontrá-lo, então é melhor fazer a pergunta.

Existem práticas recomendadas com relação à organização de pacotes em Java e o que há nelas?

Como você organiza suas aulas no seu projeto Java?

Por exemplo, um projeto no qual estou trabalhando com algumas pessoas tem um pacote chamado beans. Começou sendo um projeto contendo beans simples, mas acabou (por falta de experiência e falta de tempo) contendo tudo (quase). Eu os limpei um pouco, colocando algumas classes de fábrica em um pacote de fábrica (classes com métodos estáticos que criam beans), mas temos outras classes que fazem lógica de negócios e outras que fazem processamento simples (não com lógica de negócios) como recuperar uma mensagem para um código de um arquivo de propriedades.

Seus pensamentos e comentários são apreciados.

Cyntech
fonte
74
Não concordo com o fechamento desta questão. Não discordo de que as perguntas sobre as melhores práticas quase sempre sejam baseadas na experiência e na opinião; no entanto, discordo que essas questões devem ser encerradas no Stack Overflow. Esse é o cerne da boa programação, usando as melhores práticas e encontrar a melhor solução usa essas opiniões e experiências. Por favor, reabra esta pergunta.
Cyntech
Sugiro que você leia isto: satisfice.com/blog/archives/5164 . TL; DR ... toda a idéia de "melhores práticas" está quebrada. Na melhor das hipóteses, é um equívoco flagrante, na pior das hipóteses é absolutamente prejudicial.
Stephen C

Respostas:

174

A organização ou estruturação de pacotes geralmente é uma discussão acalorada. Abaixo estão algumas diretrizes simples para nomeação e estruturação de pacotes:

  • Siga as convenções de nomenclatura de pacotes java
  • Estruture seus pacotes de acordo com a função funcional e a função comercial
    • Divida seus pacotes de acordo com suas funcionalidades ou módulos. por exemplo com.company.product.modulea
    • Avarias adicionais podem ser baseadas em camadas do seu software. Mas não exagere se você tiver apenas poucas classes no pacote, então faz sentido ter tudo no pacote. por exemplo com.company.product.module.weboucom.company.product.module.util etc.
    • Evite exagerar na estruturação, a IMO evita embalagens separadas para exceções, fábricas etc., a menos que haja uma necessidade premente.
  • Se seu projeto for pequeno, mantenha-o simples com poucos pacotes. por exemplo , com.company.product.modele com.company.product.utiletc.
  • Dê uma olhada em alguns dos projetos populares de código aberto disponíveis nos projetos Apache . Veja como eles usam a estruturação, para projetos de vários tamanhos.
  • Considere também construir e distribuir ao nomear (permitindo distribuir sua API ou SDK em um pacote diferente, consulte API do servlet)

Após algumas experiências e testes, você poderá criar uma estrutura com a qual se sinta confortável. Não se fixe em uma convenção, esteja aberto a alterações.

naikus
fonte
Obrigado pela sua resposta. Isso é em grande parte o que tentamos incluir, mas muito código não relacionado entrou no nosso pacote de beans, que é de onde veio minha pergunta.
Cyntech
2
Concordo que pacote por recurso faz mais sentido. Ouvi uma grande analogia uma vez relacionada a uma estrutura de escritório da empresa. Em uma abordagem em camadas, cada um dos indivíduos por nível de uma empresa sentaria-se entre si, ou seja, executivos, gerentes, administradores, funcionários / trabalhadores, todos sentados em seções separadas em um edifício. Essa estrutura provavelmente não é tão eficaz quanto uma abordagem organizada por "recursos". Ou seja, se o executivo de vendas se sentar com o gerente de vendas que se senta com os funcionários de vendas, todos com um administrador de vendas. Isso proporciona uma melhor coesão entre o departamento quando organizado dessa maneira.
25419 alex
Concorde com seus pontos. Apenas um ponto a destacar sobre o nome da empresa no pacote: algumas vezes a empresa obtém um produto adquirido. A gerência deseja remover o nome da empresa. Isso pode ser uma sobrecarga.
precisa
183

Organizo pacotes por recurso , não por padrões ou funções de implementação. Eu acho que pacotes como:

  • beans
  • factories
  • collections

está errado.

Eu prefiro, por exemplo:

  • orders
  • store
  • reports

para que eu possa ocultar os detalhes da implementação através da visibilidade do pacote . A fábrica de pedidos deve estar no orderspacote para que os detalhes sobre como criar um pedido sejam ocultos.

ligado desligado
fonte
10
Este post faz um bom argumento sobre a visibilidade do pacote. Eu nunca vi o escopo do pacote Java em uso, mas a estrutura correta do pacote poderia permitir que os desenvolvedores tirassem maior proveito dele.
Jpnh
23
Isso é exatamente correto, mas poucos desenvolvedores fazem isso. Os pacotes devem ser coleções coesivas de classes, algumas das quais são visíveis apenas dentro do pacote. Isso minimizaria o acoplamento entre classes que não deveriam ser acopladas porque pertencem a diferentes recursos. A abordagem de pacote por camada não tira proveito dos modificadores de visibilidade de pacotes, e os pacotes nesse projeto têm baixa coesão e um alto grau de acoplamento entre pacotes.
Nate Reed
Você tem exemplo disso? Estou usando o Spring-MVC, acho difícil organizá-lo por recurso / módulo porque o spring usa o config xml.
Eric Huang
2
@onof Também organizo meu código por recurso, mas quais são as práticas recomendadas para classes base compartilhadas por todos os recursos?
Marc
Eu estava seguindo o primeiro estilo. mas agora eu tenho que pular de um pacote para outro ao trabalhar com classes. realmente faz uma experiência ruim. Agora estou mudando para o segundo estilo, porque acho que será mais fácil acompanhar as classes relacionadas juntos.
M.kazem Akhgary
40

Resposta curta: Um pacote por módulo / recurso, possivelmente com subpacotes. Coloque as coisas estreitamente relacionadas no mesmo pacote. Evite dependências circulares entre pacotes.

Resposta longa: concordo com a maior parte deste artigo

Peter Tseng
fonte
2
subpacotes quebram o encapsulamento. Um "subpacote" é realmente um pacote completamente independente por si só
Ricardo Gamba
21

Prefiro o recurso antes das camadas, mas acho que depende do seu projeto. Considere suas forças:

  • Dependências
    Tente minimizar as dependências do pacote, especialmente entre os recursos. Extraia APIs, se necessário.
  • Organização da equipe
    Em algumas organizações, as equipes trabalham em recursos e em outras em camadas. Isso influencia a organização do código, usa-o para formalizar APIs ou incentivar a cooperação.
  • Implantação e controle de versão
    Colocar tudo em um módulo torna a implantação e controle de versão mais simples, mas a correção de erros é mais difícil. A divisão de coisas permite melhor controle, escalabilidade e disponibilidade.
  • Responder à mudança Um
    código bem organizado é muito mais simples de mudar do que uma grande bola de barro.
  • Tamanho (pessoas e linhas de código)
    Quanto maior, mais formalizado / padronizado ele precisa ser.
  • Importância / qualidade
    Alguns códigos são mais importantes que outros. APIs devem ser mais estáveis ​​que a implementação. Portanto, ele precisa ser claramente separado.
  • Nível de abstração e ponto de entrada
    Deve ser possível que alguém de fora saiba sobre o que é o código e por onde começar a ler olhando para a árvore de pacotes.

Exemplo:

com/company/module
  + feature1/
    - MainClass          // The entry point for exploring
    + api/               // Public interface, used by other features
    + domain/
      - AggregateRoot
      + api/             // Internal API, complements the public, used by web
      + impl/ 
    + persistence/       
    + web/               // presentation layer 
    + services/          // Rest or other remote API 
    + support/            
  + feature2/
  + support/             // Any support or utils used by more than on feature
    + io
    + config
    + persistence
    + web

Este é apenas um exemplo. É bem formal. Por exemplo, ele define 2 interfaces para recurso1 . Normalmente, isso não é necessário, mas pode ser uma boa ideia se usado de maneira diferente por pessoas diferentes. Você pode deixar a API interna estender o público.

Não gosto dos nomes 'impl' ou 'support', mas eles ajudam a separar as coisas menos importantes das importantes (domínio e API). Quando se trata de nomear, gosto de ser o mais concreto possível. Se você possui um pacote chamado 'utils' com 20 classes, vá StringUtilspara support / string, HttpUtilsupport / http e assim por diante.

ThomasGran
fonte
13

Existem práticas recomendadas com relação à organização de pacotes em Java e o que há nelas?

Não, realmente não. Existem muitas idéias e opiniões, mas a "melhor prática" real é usar seu bom senso!

(Leia Nenhuma prática recomendada para obter uma perspectiva sobre "práticas recomendadas" e as pessoas que as promovem.)

No entanto, há um princípio que provavelmente tem ampla aceitação. Sua estrutura de pacote deve refletir a estrutura do módulo (informal) do seu aplicativo e você deve minimizar (ou idealmente evitar totalmente) quaisquer dependências cíclicas entre os módulos.

(Dependências cíclicas entre classes em um pacote / módulo são boas, mas os ciclos entre pacotes tendem a dificultar a compreensão da arquitetura do seu aplicativo e podem ser uma barreira para a reutilização de código. Em particular, se você usar o Maven, encontrará esse código cíclico. dependências entre pacotes / entre módulos significam que toda a bagunça interconectada deve ser um artefato do Maven.)

Gostaria também de acrescentar que não é uma boa prática amplamente aceito para nomes de pacotes. E é isso que os nomes dos pacotes devem começar com o nome de domínio da sua organização na ordem inversa. Se você seguir esta regra, reduz a probabilidade de problemas causados ​​pelo fato de seus nomes de classe (completos) colidirem com os de outras pessoas.

Stephen C
fonte
9

Eu já vi algumas pessoas promoverem 'pacote por recurso' em vez de 'pacote por camada', mas usei algumas abordagens ao longo de muitos anos e achei 'pacote por camada' muito melhor do que 'pacote por recurso'.

Além disso, descobri que uma estratégia híbrida: 'pacote por módulo, camada e recurso' funciona muito bem na prática, pois possui muitas vantagens de 'pacote por recurso':

  • Promove a criação de estruturas reutilizáveis ​​(bibliotecas com aspectos de modelo e interface do usuário)
  • Permite implementações de camada plug and play - praticamente impossível com 'pacote por recurso' porque coloca implementações de camada no mesmo pacote / diretório que o código do modelo.
  • Muito mais...

Explico em detalhes aqui: Estrutura e organização do nome do pacote Java mas minha estrutura de pacote padrão é:

revdomain.moduleType.moduleName.layer. [layerImpl] .feature.subfeatureN.subfeatureN + 1 ...

Onde:

revdomain Domínio reverso, por exemplo, com.mycompany

moduleType [app * | framework | util]

moduleName, por exemplo, myAppName, se o tipo de módulo for um aplicativo ou 'financeiro', se for uma estrutura contábil

camada [modelo | ui | persistência | segurança etc.,]

layerImpl por exemplo, wicket, jsp, jpa, jdo, hibernação (Nota: não usado se a camada for modelo)

recurso, por exemplo, finanças

subfuncionalN por exemplo, contabilidade

subfunçãoN + 1 por exemplo, depreciação

* Às vezes, 'app' fica de fora se moduleType for um aplicativo, mas colocá-lo lá torna a estrutura do pacote consistente em todos os tipos de módulos.

Volksman
fonte
5

Não estou ciente das práticas padrão para organização de pacotes. Geralmente, crio pacotes que abrangem um espectro razoavelmente amplo, mas posso diferenciar dentro de um projeto. Por exemplo, um projeto pessoal no qual estou trabalhando no momento tem um pacote dedicado aos meus controles personalizados da interface do usuário (cheio de classes subclassificando as classes swing). Eu tenho um pacote dedicado ao meu material de gerenciamento de banco de dados, um pacote para um conjunto de ouvintes / eventos que eu criei e assim por diante.

Por outro lado, um colega de trabalho criou um novo pacote para quase tudo o que ele fez. Cada MVC diferente que ele queria tinha seu próprio pacote, e parecia que um conjunto MVC era o único agrupamento de classes permitido para estar no mesmo pacote. Lembro-me que em um ponto ele tinha 5 pacotes diferentes, cada um com uma única classe. Eu acho que o método dele é um pouco extremo (e a equipe o forçou a reduzir a contagem de pacotes quando simplesmente não conseguimos lidar com isso), mas para um aplicativo não trivial, colocar tudo no mesmo pacote. É um ponto de equilíbrio que você e seus colegas de equipe precisam encontrar por si mesmo.

Uma coisa que você pode fazer é tentar voltar atrás e pensar: se você fosse um novo membro introduzido no projeto ou seu projeto fosse lançado como código-fonte aberto ou uma API, quão fácil / difícil seria encontrar o que você deseja? Porque para mim, é isso que realmente quero dos pacotes: organização. Semelhante à maneira como armazeno arquivos em uma pasta no meu computador, espero poder encontrá-los novamente sem precisar pesquisar minha unidade inteira. Espero ser capaz de encontrar a classe que desejo sem precisar pesquisar na lista de todas as classes no pacote.

Brian S
fonte