Estrutura de aplicativos Java: divisão horizontal versus vertical

15

Discutindo um pouco sobre a estrutura inicial do projeto (usando o Maven / Eclipse) para um grande aplicativo Java.

Opção 1:

entities (i.e. the whole database using Hibernate classes-first)
services (i.e. sets of read/write operations on the entities)
app (perhaps split up more further down the line)

Opção 2:

area1-entities
area1-services
area1-app
area2-entities
area2-services
area2-app
...
(where area1, area2 etc. are functional areas of the system)

A opção 2 resultará claramente em muito mais projetos / módulos do Maven e significa que as classes que gerariam o banco de dados serão distribuídas entre vários projetos. Alguém poderia aconselhar os prós / contras de cada abordagem?

Steve Chambers
fonte
3
Nem. IMHO (aqui vamos nós), devemos parar de separar as camadas técnicas que simplesmente levam a uma grande bola de lama. Em vez disso, empacote funcionalmente. Apenas area1 / area2, que deve conter o núcleo do seu aplicativo (entidades, serviços (dividido em interface pública e implementação privada de pacotes), repositórios (se necessário). Agora você deve conectar sua camada web / ws / messaging a esse núcleo. quer dar uma olhada aqui e aqui
Ainda é opinado :). Mas vou fazer um polimento para colocar em resposta.
Obrigado, mas esta questão é sobre a estrutura do projeto, em vez de estrutura do pacote
Steve Chambers

Respostas:

29

Eu sugeriria não fazer nenhum.

Tentar aplicar uma camada técnica com uma estrutura de pacote leva a muito emaranhamento em seu aplicativo. Sem mencionar o fato de tentarmos esconder tudo por trás de uma interface de serviço e a primeira coisa que fazemos (principalmente devido ao empacotamento) é tornar tudo a public class. Isso se torna doloroso quando há uma separação técnica entre a x.y.z.servicee o x.y.z.repositorypacote, agora tudo pode acessar o repositório. Crescimento lá vai o seu encapsulamento dentro da camada de serviço.

Em vez disso, você deve seguir uma abordagem mais funcional e baseada em cebola ( arquitetura limpa , arquitetura hexagonal ). Isso também está alinhado com o Princípio de responsabilidade única (quando aplicado a uma embalagem) e também de acordo com os princípios de embalagem

  1. Coisas que mudam juntas são empacotadas juntas
  2. As coisas que são usadas juntas são empacotadas juntas

Oliver Gierke escreveu um bom post sobre componentes de empacotamento em Java. Simon Brown escreveu uma história mais geral sobre o assunto.

Eu me esforçaria por uma estrutura de pacote principal, como a seguir, para manter o núcleo do seu aplicativo:

x.y.z.area1
x.y.z.area2

Agora, se você tiver uma interface da web, adicione, por exemplo, um websubpacote, ao serviço da web a wsou restpacote para armazenar apenas isso. Basicamente, ele se conecta ao núcleo.

x.y.z.area1.web
x.y.z.area1.ws
x.y.z.area2.rest

Agora você pode reutilizar os objetos de dentro do seu núcleo para as outras camadas, mas IMHO é melhor usar um domínio específico para essa camada. Assim como no mapeamento de Objeto para SQL, há (frequentemente) uma incompatibilidade no que queremos mostrar na tela ou usar como XML no serviço da Web e como a lógica de negócios é implementada. Dependendo da complexidade dos domínios de negócios e da web, você pode considerá-los como domínios de problemas separados para resolver quais precisam ser conectados, basicamente 2 contextos limitados diferentes .

Para usar uma cotação de um recurso CQRS

Não é possível criar uma solução ideal para pesquisar, gerar relatórios e processar transações utilizando um único modelo.

Não tente colocar tudo em um único modelo (domínio), separe as responsabilidades. Você provavelmente acaba com mais classes (menores), mas com uma separação mais limpa entre as camadas do seu aplicativo.

Nota final

Lembre-se de que criar uma arquitetura é decidir as vantagens e desvantagens de uma solução para outra. Depende muito da complexidade do domínio e deve ser direcionado principalmente pelos requisitos funcionais do seu aplicativo. No entanto, é influenciado pelas restrições não funcionais (desempenho, segurança) e ambientais (idioma a usar, plataforma, experiência). E a arquitetura, como a codificação, nunca é concluída, cada novo requisito pode (e talvez deveria?) Levar a um redesenho do aplicativo.

aviso Legal

Sim, também tentei colocar tudo em um único modelo e, também, tentei usar uma separação técnica em meus aplicativos. No entanto, após alguns anos de experiência na criação de camadas emaranhadas de aplicativos (a princípio parece uma boa idéia, o aplicativo começa a crescer ...), imaginei que deveria haver outra maneira.

Ligações

  1. Arquitetura Limpa, Tio Bob Martin
  2. Arquitetura hexagonal (aka portas e adaptadores), Alistair Cockburn
  3. Opa onde foi minha arquitetura, Oliver Gierke
  4. Princípios de OOD, tio Bob Martin
  5. Erros ao aplicar DDD, Udi Dahan
  6. Contextos limitados, Martin Fowler
  7. Estilo de codificação arquitetonicamente evidente, Simon Brown

Livros

  1. Crescimento de software orientado a objetos, guiado por testes
  2. Arquitetura de aplicativos Java: padrões de modularidade com exemplos usando OSGi (Robert C. Martin Series)
  3. Design Orientado a Domínio: Lidando com a Complexidade no Coração do Software
  4. Arquitetura de software para desenvolvedores
  5. Implementando o design orientado a domínio
M. Deinum
fonte
1
Resposta agradável :) Eu gostaria de acrescentar uma leitura obrigatória para resolver este assunto: amazon.com/Growing-Object-Oriented-Software-Guided-Tests/dp/...
Mik378
1
Bom, acrescentou mais alguns à minha resposta original.
1
É de longe o melhor livro sobre design que já li;) Você pode mencionar o livro Vaughn Vernon, muito bom também: amazon.com/Implementing-Domain-Driven-Design-Vaughn-Vernon/dp/…
Mik378
@ M.Deinum +1 Ótimo para referência!
1
@ Mik378 Eu tenho dois livros em minha biblioteca digital, entre muitos outros.