Camada de aplicação vs camada de domínio?


47

Estou lendo Design Orientado a Domínio por Evans e estou discutindo a arquitetura em camadas. Acabei de perceber que as camadas de aplicativo e domínio são diferentes e devem ser separadas. No projeto em que estou trabalhando, eles meio que se misturam e não sei dizer a diferença até ler o livro (e não posso dizer que isso esteja muito claro para mim agora), na verdade.

Minhas perguntas, como as duas dizem respeito à lógica do aplicativo e devem estar limpas aos aspectos técnicos e de apresentação, quais são as vantagens de estabelecer um limite entre essas duas?

Respostas:


36

Eu li recentemente DDD. Quando cheguei a esta seção, fiquei agradavelmente surpreso ao descobrir que descobri a mesma arquitetura de quatro camadas que Evans fez. Como o @lonelybug apontou, a camada do domínio deve ser completamente isolada do resto do sistema. No entanto, algo precisa traduzir valores específicos da interface do usuário (cadeias de consulta, dados POST, sessão etc.) em objetos de domínio. É aqui que a camada do aplicativo entra em cena. Seu trabalho é traduzir entre a interface do usuário, a camada de dados e o domínio, ocultando efetivamente o domínio do resto do sistema.

Agora vejo muitos aplicativos ASP.NET MVC onde quase toda a lógica está nos controladores. Esta é uma tentativa fracassada de implementar a arquitetura clássica de 3 camadas. Os controladores são difíceis de testar por unidade, porque eles têm muitas preocupações específicas da interface do usuário. De fato, escrever um controlador para que ele não se preocupe diretamente com os valores "Contexto Http" é um sério desafio por si só. Idealmente, o controlador deve apenas executar a tradução, coordenar o trabalho e cuspir a resposta.

Pode até fazer sentido validação básica na camada de aplicação. Não há problema em o domínio assumir que os valores inseridos fazem sentido (esse é um ID válido para esse cliente e essa sequência representa uma data / hora). No entanto, a validação envolvendo lógica de negócios (posso reservar uma passagem de avião no passado?) Deve ser reservada para a camada de domínio.

Martin Fowler, na verdade, comenta sobre como a maioria das camadas de domínio é plana atualmente . Mesmo que a maioria das pessoas nem saiba o que é uma camada de aplicativo, ele descobre que muitas pessoas fazem objetos de domínio bastante burros e camadas de aplicativos complexas que coordenam o trabalho dos diferentes objetos de domínio. Eu também sou culpado disso. O importante não é construir uma camada, porque alguns livros lhe pediram. A idéia é identificar responsabilidades e separar nosso código com base nessas responsabilidades. No meu caso, a "camada de aplicação" evoluiu naturalmente à medida que aumentava o teste de unidade.


9
Eu não acho que o que você declara aqui está correto: "No entanto, algo precisa traduzir valores específicos da interface do usuário (cadeias de consulta, dados POST, sessão etc.) em objetos de domínio. É aqui que a camada do aplicativo entra em ação". O que você está se referindo é, nos termos do DDD, a camada "Apresentação". Supõe-se que a camada de aplicativo lide com problemas de encanamento, simultaneidade e questões transversais, sendo apenas um pequeno invólucro sobre a camada de domínio. O que você está descrevendo corresponderia a uma (sub) camada na camada de apresentação.
devorado elysium

23

Partindo dos padrões de design corporativo de Martin Fowler, as camadas mais comuns são:

  • Apresentação - são visualizações, modelos de apresentação que geram a interface de interação para seu aplicativo (estou usando a interação caso seu aplicativo seja acessado por outros sistemas através de serviços da Web ou RMI, portanto, pode não ser uma interface de usuário). Isso também inclui controladores que decidem como as ações serão executadas e como.

  • Domínio - é onde residem suas regras e lógica de negócios, seus modelos de domínio são definidos etc.

  • Fonte de dados - essa é a camada de mapeamento de dados (ORM) e a fonte de dados (banco de dados, sistema de arquivos etc.)

Como você desenha os limites entre as três camadas:

  • Não coloque lógica específica de apresentação em seus modelos ou objetos de domínio

  • Não coloque lógica nas suas páginas e controladores, ou seja, lógica para salvar objetos no banco de dados, criar conexões com o banco de dados, etc., o que tornará sua camada de apresentação quebradiça e difícil de testar

  • Use um ORM que permita dissociar o acesso e as ações da fonte de dados do modelo

  • Siga o paradigma thin controller - modelo de gordura, os controladores são para controlar o processo de execução que não está sendo executado, mais em http://www.littlehart.net/atthekeyboard/2007/04/27/fat-models-skinny-controllers/ e http://weblog.jamisbuck.org/2006/10/18/skinny-controller-fat-model model, view and controller,


17

A camada de domínio modela os negócios do seu aplicativo. Esta deve ser sua interpretação clara de suas regras, sua dinâmica de componentes e contém seu estado a qualquer momento.

A camada de aplicação está "preocupada com" definir os trabalhos necessários para realizar uma determinada tarefa de aplicação. Principalmente, é responsável por determinar o trabalho de domínio necessário e interage com outros serviços (externos ou não).

Por exemplo , meu aplicativo de software financeiro possui uma operação de usuário para alterar o estado de uma entidade modelo (entidade conforme definida em DDD [89]):

  • "O chefe de operações pode aprovar uma proposta financeira".

Mas, como um processo de aplicação, além de todas as consequências do modelo desta operação, tenho que enviar uma comunicação interna para outros usuários da aplicação. Esse tipo de trabalho é "orquestrado" na camada do aplicativo. Eu não gostaria que minha camada de domínio pensasse em direcionar um serviço de mensagens. (e certamente isso não é uma responsabilidade da camada de apresentação). De qualquer maneira, uma coisa é certa: preciso de uma nova camada, pois minha camada de domínio é sobre o negócio principal e minha camada de apresentação é sobre interpretação de comandos do usuário e apresentação de resultados.

Notas:

  • Negócios é uma daquelas palavras que freqüentemente levam a várias interpretações de seu significado, mas com certeza você pode encontrar muitos exemplos e discussões sobre DDD;
  • DDD significa livro de Design Orientado a Domínio de Eric Evans e número entre colchetes para número de página.

6

A Camada de Domínio deve ser projetada como uma camada de isolamento, o que significa que a lógica e as regras de negócios não devem ser afetadas com nenhum código (na Camada de Aplicativos, Camada de Apresentação e Camada de Infra-estrutura).

A Camada de Aplicação deve ser projetada para fornecer algumas funções sobre o que uma interface de sistema (aplicativo) (pense como uma API ou RESTful) pode fazer. Por exemplo, os usuários podem efetuar login em um sistema e, nessa ação do aplicativo (login), os códigos da camada de aplicativo serão os códigos do cliente para a Camada de Domínio (ou Camada de Infra-estrutura), na qual recupera o objeto Domínio do usuário e aplica os métodos desse objeto para implementar o método função 'login'.

A Camada de Aplicação também deve ser projetada como uma camada de isolamento, o que significa que o comportamento do aplicativo não deve ser afetado por nenhum código (na Camada de Apresentação, Camada de Domínio e Camada de Infra-estrutura).


2
Pelo menos em literatura como Design Orientado a Domínio (Evans), é reconhecido que as camadas têm uma dependência unidirecional ... o fato é que, em algum momento, seu código depende de alguma coisa . A interface do usuário depende do aplicativo, mas não vice-versa. A aplicação depende do domínio, mas não o contrário. Domínio na infraestrutura, não vice-versa.

1
Dependência é sobre como sua programação, a camada de isolamento, é sobre como você projeta as camadas do sistema. A dependência unidirecional não quebra o conceito de isolamento aqui, porque quando você programa, o código da camada superior deve depender da interface da camada inferior e não das classes de implementação.
stevesun21

Isso é ótimo e tudo está no papel, mas, na prática, os requisitos de negócios resultam em mudanças que podem afetar a interface da camada de aplicativos de tal maneira que as mudanças passam pela camada de apresentação e, às vezes, até a camada de armazenamento. Isso é tudo o que eu queria chegar ...

O design da camada de isolamento não significa que nenhuma alteração seja permitida no futuro. Ao contrário, torna as alterações muito mais fáceis - mais fáceis de testar e mais fáceis de estimar os trabalhos. Sim, um novo requisito comercial significa que você pode precisar mudar de cima para baixo, não é assim que você implementou a função existente antes? Se você pode projetar cada camada com base nos princípios do SOLID, pode descobrir que pode reutilizar as funções existentes da camada inferior.
stevesun21

3

O objetivo da Modelagem Orientada a Domínio é separar o modelo de domínio essencial e fazê-lo existir sem nenhuma dependência de outras camadas e outros problemas de aplicativo.

Isso permite que você se concentre no próprio domínio sem distrações (como a coordenação entre a interface do usuário e os serviços de persistência).


Então, a fonte de dados (um ORM) está dentro do domínio?
Maykonn

@ Maykonn - Poderia ser. No entanto, um ORM não é uma fonte de dados. É uma ferramenta entre seu código e a fonte de dados real (um banco de dados relacional). Como você acessa os dados não deve ser uma preocupação do domínio - construtores e fábricas podem lidar com isso (e um ORM, se você tiver um).
Oded

Concordo. E eu estava errado sobre fonte de dados e ORM. Obrigado!
Maykonn 27/10/2013

3
  • A Camada de Aplicação e a Camada de Domínio estão incluídas no escopo da implementação.
  • Camada de aplicação atua como API.
  • A camada de domínio atua como uma implementação da API, contém lógica de negócios e também é chamada de camada de lógica de negócios.

insira a descrição da imagem aqui


nunca pensei nisso dessa maneira .... Sinto-me iluminado
Nikos

2

A principal razão para essas fronteiras é a separação de preocupações . O código que acessa o armazenamento de dados deve ter que se preocupar apenas em acessar o armazenamento de dados. Não deve ser responsável por impor regras aos dados. Além disso, a interface do usuário deve ser responsável por atualizar os controles na interface do usuário, obtendo valores da entrada do usuário e convertendo-os em algo que a camada de domínio possa usar e nada mais. Ele deve chamar as operações fornecidas pela camada de domínio para executar as ações necessárias (por exemplo, salve este arquivo). Um serviço da web chamado deve ser responsável pela conversão do meio de transmissão para algo que a camada de domínio possa usar e, em seguida, chamar a camada de domínio (a maioria das ferramentas faz muito desse trabalho para você).

Essa separação, quando implementada corretamente, pode oferecer a você a capacidade de alterar partes do seu código sem afetar outros. Por exemplo, talvez a ordem de classificação de uma coleção de objetos retornada precise ser alterada. Como você sabe que a camada responsável pela manipulação de dados (geralmente a camada da lógica de negócios) lida com essas coisas, é possível identificar facilmente onde o código precisa ser alterado. Além de não precisar modificar como é recuperado do armazenamento de dados ou de qualquer aplicativo que utilize o domínio (a interface do usuário e o serviço da web do meu exemplo acima).

O objetivo final é tornar seu código o mais fácil de manter possível.

Como uma observação lateral, algumas coisas não podem ser colocadas em uma camada específica do domínio (por exemplo, log, validação e autorização). Esses itens são comumente referidos como preocupações transversais e, em alguns casos, podem ser tratados como uma camada que permanece por si só e que todas as outras camadas podem ver e usar.

Pessoalmente, acho que a abordagem em camadas está desatualizada e que a abordagem de serviço é melhor. Você ainda tem a linha gritante desenhada na areia sobre quem faz o quê, mas isso não o força a ser tão hierárquico. Por exemplo, um serviço de pedido de compra, um serviço de cobrança e um serviço de remessa, da perspectiva do aplicativo, todos esses serviços representam seu domínio, e o adiamento da responsabilidade que descrevi acima ainda é válido nesse contexto, ele acabou de ser alterado que seu domínio existe em vários locais, utilizando ainda o conceito de separação de preocupações.


Fiquei curioso sobre o posicionamento da lógica de autorização e, pelo que estou tentando entender, ela se encaixa na 'camada de aplicativo'. Você se importaria em compartilhar algumas idéias sobre por que não seria melhor contê-las nessa camada de lógica?

1
Esse é o tipo perfeito de pergunta para este site. Você deve publicá-lo, para que todos tenham a chance de responder.
Charles Lambert

@tuespetre Você poderia fornecer um link para esse post?
Drizzie
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.