Pergunta

Em primeiro lugar, sei como construir uma aplicação Java.Mas sempre fiquei confuso sobre onde colocar minhas aulas.Há defensores da organização dos pacotes de maneira estritamente orientada ao domínio, outros os separam por níveis.

Eu mesmo sempre tive problemas com

  • nomeando,
  • colocação

Então,

  1. Onde você coloca suas constantes específicas de domínio (e qual é o melhor nome para essa classe)?
  2. Onde você coloca classes para itens que são tanto de infraestrutura quanto de domínio específico (por exemplo, eu tenho uma classe FileStorageStrategy, que armazena os arquivos no banco de dados ou, alternativamente, no banco de dados)?
  3. Onde colocar exceções?
  4. Há algum padrão ao qual eu possa me referir?
Foi útil?

Solução

Eu realmente comecei a gostar do Maven's Layout de diretório padrão.

Uma das ideias principais para mim é ter duas raízes de origem - uma para código de produção e outra para código de teste, assim:

MyProject/src/main/java/com/acme/Widget.java
MyProject/src/test/java/com/acme/WidgetTest.java

(aqui, src/main/java e src/test/java são raízes de origem).

Vantagens:

  • Seus testes têm acesso em nível de pacote (ou "padrão") às classes em teste.
  • Você pode facilmente empacotar apenas suas fontes de produção em um JAR descartando src/test/java como raiz de origem.

Uma regra prática sobre colocação de aulas e pacotes:

De modo geral, projetos bem estruturados estarão isentos de dependências circulares.Aprenda quando eles são ruins (e quando são não) e considere uma ferramenta como JDepend ou SonarJ isso o ajudará a eliminá-los.

Outras dicas

Sou um grande fã de fontes organizadas, por isso sempre crio a seguinte estrutura de diretórios:

/src - for your packages & classes
/test - for unit tests
/docs - for documentation, generated and manually edited
/lib - 3rd party libraries
/etc - unrelated stuff
/bin (or /classes) - compiled classes, output of your compile
/dist - for distribution packages, hopefully auto generated by a build system

Em /src estou usando os padrões Java padrão:Nomes de pacotes começando com seu domínio (org.seudominio.nomedoseuprojeto) e nomes de classes refletindo o aspecto OOP que você está criando com a classe (veja os outros comentaristas).Nomes de pacotes comuns como útil, modelo, visualizar, eventos também são úteis.

Costumo colocar constantes para um tópico específico em uma classe própria, como Constantes de Sessão ou Constantes de serviço no mesmo pacote das classes de domínio.

Onde estou trabalhando, usamos o Maven 2 e temos um arquétipo muito bom para nossos projetos.O objetivo era obter uma boa separação de interesses, por isso definimos uma estrutura de projeto utilizando múltiplos módulos (um para cada 'camada' de aplicação):- comum:Código comum usado pelas outras camadas (por exemplo, i18n) - entidades:As entidades de domínio - repositórios:Este módulo contém as interfaces e implementações DAOS - Services -Intf:Interfaces para os Serviços (por exemplo, UserService, ...) - Serviços -IMPL:implementações dos Serviços (por exemplo, UserServiceImpl) - Web:Tudo sobre o conteúdo da web (por exemplo, CSS, JSPs, Páginas JSF, ...) - WS:serviços web

Cada módulo tem suas próprias dependências (por exemplo, os repositórios podem ter jpa) e alguns abrangem todo o projeto (portanto, pertencem ao módulo comum).As dependências entre os diferentes módulos do projeto separam claramente as coisas (por exemplo, a camada web depende da camada de serviço, mas não conhece a camada de repositório).

Cada módulo possui seu próprio pacote base, por exemplo se o pacote da aplicação for "com.foo.bar", então temos:

com.foo.bar.common
com.foo.bar.entities
com.foo.bar.repositories
com.foo.bar.services
com.foo.bar.services.impl
...

Cada módulo respeita a estrutura padrão do projeto maven:

   src\
   ..main\java
     ...\resources
   ..test\java
     ...\resources

Os testes de unidade para uma determinada camada encontram facilmente seu lugar em \src est...Tudo o que é específico do domínio tem seu lugar no módulo de entidades.Agora, algo como FileStorageStrategy deve entrar no módulo de repositórios, já que não precisamos saber exatamente qual é a implementação.Na camada de serviços conhecemos apenas a interface do repositório, não nos importamos qual seja a implementação específica (separação de interesses).

Existem várias vantagens nesta abordagem:

  • separação clara de preocupações
  • cada módulo pode ser empacotado como um jar (ou um war no caso do módulo web) e, portanto, permite uma reutilização mais fácil do código (por exemplo, poderíamos instalar o módulo no repositório maven e reutilizá-lo em outro projeto)
  • independência máxima de cada parte do projeto

Sei que isso não responde a todas as suas perguntas, mas acho que pode colocá-lo no caminho certo e ser útil para outras pessoas.

Os nomes das classes devem sempre ser descritivos e autoexplicativos.Se você tiver vários domínios de responsabilidade por suas classes, eles provavelmente deverão ser refatorados.

Da mesma forma para seus pacotes.Eles devem ser agrupados por domínio de responsabilidade.Cada domínio tem suas próprias exceções.

Geralmente não se preocupe até chegar a um ponto em que ele se torne opressor e inchado.Então sente-se e não codifique, apenas refatore as classes, compilando regularmente para garantir que tudo funcione.Depois continue como fez antes.

Use pacotes para agrupar funcionalidades relacionadas.

Normalmente, o topo da sua árvore de pacotes é o seu nome de domínio invertido (com.domain.subdomain) para garantir a exclusividade e, geralmente, haverá um pacote para sua aplicação.Em seguida, subdivida isso por área relacionada, para que seu FileStorageStrategy pode entrar, digamos, com.domain.subdomain.myapp.storage, e então pode haver implementações/subclasses/qualquer coisa específica em com.domain.subdomain.myapp.storage.file e com.domain.subdomain.myapp.storage.database.Esses nomes podem ficar bem longos, mas import mantém todos eles no topo dos arquivos e os IDEs também podem ajudar a gerenciar isso.

As exceções geralmente vão no mesmo pacote que as classes que as lançam, então se você tivesse, digamos, FileStorageException iria no mesmo pacote que FileStorageStrategy.Da mesma forma, uma interface que define constantes estaria no mesmo pacote.

Não existe realmente nenhum padrão, apenas use o bom senso e, se tudo ficar muito confuso, refatore!

Uma coisa que achei muito útil para testes de unidade foi ter os diretórios myApp/src/ e também myApp/test_src/.Dessa forma, posso colocar testes de unidade nos mesmos pacotes das classes que eles testam e, ainda assim, posso excluir facilmente os casos de teste ao preparar minha instalação de produção.

Resposta curta:desenhe a arquitetura do seu sistema em termos de módulos, desenhados lado a lado, com cada módulo dividido verticalmente em camadas (por exemplo,visão, modelo, persistência).Em seguida, use uma estrutura como com.mycompany.myapp.somemodule.somelayer, por exemplo. com.minhaempresa.myapp.client.view ou com.minhaempresa.myapp.server.model.

Usando o nível superior de pacotes para aplicação módulos, no sentido antiquado da ciência da computação programação modular, deveria ser óbvio.Porém, na maioria dos projetos em que trabalhei acabamos esquecendo de fazer isso, e acabamos com uma confusão de pacotes sem aquela estrutura de nível superior.Esse antipadrão geralmente se mostra como um pacote para algo como 'ouvintes' ou 'ações' que agrupa classes não relacionadas simplesmente porque implementam a mesma interface.

Dentro de um módulo ou em uma aplicação pequena, use pacotes para as camadas de aplicação.Os pacotes prováveis ​​incluem coisas como o seguinte, dependendo da arquitetura:

  • com.minhaempresa.myapp.view
  • com.minhaempresa.myapp.model
  • com.minhaempresa.myapp.services
  • com.minhaempresa.myapp.rules
  • com.minhaempresa.myapp.persistence (ou 'dao' para camada de acesso a dados)
  • com.minhaempresa.myapp.util (cuidado para não ser usado como se fosse 'misc')

Dentro de cada uma dessas camadas, é natural agrupar as turmas por tipo, se houver muitas.Um antipadrão comum aqui é introduzir desnecessariamente muitos pacotes e níveis de subpacotes, de modo que haja apenas algumas classes em cada pacote.

Acho que mantenha as coisas simples e não pense demais.Não abstraia demais e faça camadas demais.Basta mantê-lo organizado e, à medida que cresce, refatorá-lo é trivial.Um dos melhores recursos dos IDEs é a refatoração, então por que não usá-la e economizar energia cerebral para resolver problemas relacionados ao seu aplicativo, em vez de meta-problemas, como organização de código.

Uma coisa que fiz no passado: se estou estendendo uma aula, tentarei seguir as convenções.Por exemplo, ao trabalhar com a estrutura da primavera, terei minhas classes de controlador MVC em um pacote chamado com.mydomain.myapp.web.servlet.mvc Se não estiver estendendo algo, eu apenas vou com o que é mais simples.com.mydomain.domain para objetos de domínio (embora se você tiver muitos objetos de domínio, este pacote pode ficar um pouco complicado).Para constantes específicas de domínio, na verdade as coloco como constantes públicas na classe mais relacionada.Por exemplo, se eu tiver uma classe "Membro" e uma constante de comprimento máximo do nome do membro, coloco-a na classe Membro.Algumas lojas criam uma classe Constants separada, mas não vejo valor em agrupar números e strings não relacionados em uma única classe.Já vi algumas outras lojas tentarem resolver esse problema criando classes SEPARATE Constants, mas isso parece uma perda de tempo e o resultado é muito confuso.Usando esta configuração, um projeto grande com vários desenvolvedores duplicará constantes em todos os lugares.

Gosto de dividir minhas aulas em pacotes relacionados entre si.

Por exemplo:Modelo Para chamadas relacionadas ao banco de dados

Visualizar Aulas que tratam do que você vê

Ao controle Classes de funcionalidade principal

Util Qualquer misc.classes que são usadas (normalmente funções estáticas)

etc.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top