Repositórios: pra que te quero?

Domain-Driven Desing não é sobre padrões – isso gera muita discussão. Domain-Driven Design (ou simplesmente DDD) é sobre fazer software de maneira mais simples – e sei que muitos não vão concordar com isso, pois “parece” que é mais fácil e muitos se sentem muitos produtivos ligando Table Modules diretamente às telas e abusando de Transaction Scripts.

O objetivo deste artigo não é falar sobre o que a literatura diz sobre repositórios e nem tenho a pretensão de escrever o “post definitivo sobre Repositórios”. O objetivo aqui é demonstrar como tenho aplicado Repositórios nesses 3 anos de experiência em aplicação e ensino de DDD.

O que são Repositórios afinal?

Antes de mais nada, orientamos a aplicação ao domínio. O exemplo que vou montar aqui não é real, mas é bem próximo daquilo que apliquei em alguns projetos. Orientar a aplicação ao domínio significa que seu código será limpo e principalmente sua camada de negócios demonstrará o NEGÓCIO, suas regras, seu estado e suas associações. Se sua aplicação é de vendas, é esperado que o vocabulário do domínio “vendas” seja encontrado nas suas classes. As classes do domínio também não devem ser poluídas com o domínio técnico: o domínio “vendas” não sabe o que são tabelas, filas, sistema de arquivos e nem SMTP. O domínio técnico e do domínio do negócio tentam ao máximo não se misturar numa aplicação Domain-Driven.

Se minhas classes de negócio traduzem a linguagem de vendas, quero que você tente pensar num modelo que resolva os seguintes requisitos:

1. Um pedido de vendas possui cliente e itens
2. O valor total do pedido é a soma do valor dos itens
3. Somente produtos disponíveis podem ser vendidos

Imagine agora, como um ator Vendedor utilizaria o sistema. Ele criaria um pedido, colocaria alguns itens com produtos disponíveis e finalizaria este caso de uso. Quero que você pense bastante em como você resolveria o requisito número 3. No meu código, surgiria algo deste tipo:

[photopress:ddd_diag_1_1.jpg,full,pp_image]

A primeira pergunta natural é: Por que o repositório está como uma interface? Muitas vezes o Repositório simplesmente é uma abstração do domínio cuja responsabilidade é representar coleções de entidades, porém, ele ainda é um elemento do domínio. Muitas vezes nós temos um elemento que realiza esta interface para fornecer implementação para essas buscas.

[photopress:ddd_diag_2_1.jpg,full,pp_image]

Usar repositórios como interfaces é bom para a saúde da testabilidade da sua aplicação e ainda posso me beneficiar de injeção de dependência. Isso facilita o uso de Mocks e Stubs para testes unitários ou de integração, além de deixar seus objetos desacoplados.

Teve algumas situações peculiares onde a interface TodosProdutos era um elemento do domínio e a implementação TodosProdutosImpl era puramente infra-estrutura. Neste caso, TodosProdutos (a interface) estava empacotada no domínio (geralmente uso o nome domain) e a TodosProdutosImpl estava empacotado como infra-estrutura.

De qualquer forma, para a discussão aqui, simplesmente destaco que o repositório TodosProdutos é algo puramente do vocabulário de negócios. “Todos os Produtos” é algo que o meu usuário sabe o que significa. E TodosProdutos.getDisponiveis – a minha operação – faz mais sentido ainda para os usuários, pois eles também sabem o que são produtos disponíveis para venda (se isso para eles é uma interface ou uma classe isso é completamente irrelevante).

Repositórios como Coleções Parciais

Teve uma certa aplicação que desenvolvi que nas conversas com os especialistas de negócio um determinado termo era muito recorrente. Eles se referiam a um determinado conjunto de entidades com um nome especial: pedidos faturados. E nesse sistema, os “pedidos faturados” tinham uma força tão grande na Ubiquitous Language da DDD que passou a ser um contexto separado.

[photopress:ddd_diag_3.jpg,full,pp_image]

Várias vezes mostrei esse diagrama a arquitetos e programadores e muitos não entenderam isso facilmente. É bastante comum as pessoas associarem um repositório por entidade, enxergando-os como 1 para 1 com DAOs. Muitos desses programadores que não entendem DDD questionaram: – Por que separar isso? Minha resposta: – Não fui eu que separei isto… no domínio do negócio isso é separado. Não é uma opção arquitetural, somente estou transparecendo o domínio.

A maioria das respostas sobre a camada de negócios numa aplicação Domain-Driven é dada pelos usuários e especialistas do domínio e não pelos arquitetos e programadores.

O nome não deve ser XptoRepository?

Durante algum tempo, seguindo a linha do Hibernate, minhas classes de busca eram [NomeDaEntidade]DAO. Depois de um tempo meus DAOs eram repositórios, mas continuava chamando-os de DAOs, pois odeio o nome Repository dentro do meu código. Acho pior ainda o nome “Repositório” – que é uma tradução livre corrente. O nome Repositório é bem pouco expressivo em português (que raios é repositório?) – o termo em inglês é mais claro.

Ao fim de tudo isso, vejo que é bem pouco proveitoso chamar uma classe de domínio de PedidoRepository ou PedidoRepositorio. Teve uma aplicação que chamei meus repositorio de “Pedidos”, mas últimamente tenho usado mesmo “TodosPedidos”, “TodosClientes”, “PedidosFaturados”, “ClientesInadimplentes” e etc… Uso esses termos pois são mais próximos do domínio e não vejo a mínima razão para ter o nome do padrão no nome ou empacotamento das classes.

Pedido é uma entidade, nem por isso o chamamos de PedidoEntity, o mesmo vale para Value Objects, Services e Repositórios. O BufferedInputStream do Java é um Decorator, nem por isso chamamos ele de BufferedInpuStreamDecorator.

Repositórios mais Complexos

Associar repositórios com buscas nem sempre é verdadeiro. Repositórios respondem por conjuntos de entidades, não importando a dificuldade de se obter esse conjunto. Há repositórios que podem ter código de negócio complexo em sua execução onde determinadas operações podem à primeira vista aparentar simplesmente uma busca. Você deve levar em consideração se há inteligência de domínio envolvida, caso afirmativo seu repositório deverá ter essa inteligência embutida. Vamos colocar mais requisitos:

4. Se o pedido é para entrega imediata, os produtos disponíveis são aqueles que eu tenho em estoque no momento da venda
5. Se o pedido é para entrega futura, os produtos disponíveis são aqueles que estarão em estoque na data de entrega

[photopress:ddd_diag_4.jpg,full,pp_image]

Neste “TodosProdutos” refatorado, para obter os produtos disponíveis na data da entrega é necessário pegar o saldo atual do estoque, subtrair os pedidos de venda já comprometidos (saídas) e somar os pedidos de compra (entradas) até a data desejada. Tudo isso é inteligência de domínio que não deve ser delegado para o banco de dados. É um repositório que tem regras e pode até orquestrar junto a outros repositórios e services para cumprir o seu propósito.

Um ponto importante a destacar é que muitas outras variações de implementações de repositórios existem. O objetivo do artigo é somente destacar algumas implementações interessantes que implementei em alguns projetos.

É lícito acessar o EntityManager diretamente?

Discussões sobre Domain-Driven e implementações de respositórios são muito recorrentes em listas de discussões, principalmente no GUJ e na DotNetArchitects (sou novo nessa lista).

Uma das perguntas comuns é: “É licito eu acessar diretamente o EntityManager ou Sessão do Hibernate?”. Particularmente eu sou da opinião que se você está fazendo buscas que não são importantes para o negócio não há problemas acessar diretamente seu framework de persistência. Logicamente que isso não deve ser levado a ferro e a fogo, testabilidade e complexidade são pontos a considerar.

Um exemplo seria: imagine que para emitir o pedido eu tenha que preencher um combo com o tipo de venda (um dado simplesmente informativo). Se é uma busca de uma entidade fraca, que significa muito pouco para o domínio, para reduzir a complexidade, o repositório pode ser descartado sem muito prejuízo para a testabilidade.

About The Author

rodrigoy

Instrutor e Consultor Sênior - ASPERCOM

Deixe sua opinião!

41 Comments

  • Tarso

    Reply Reply 11/08/2009

    Rodrigo, ótimo post.

    Seu texto me fez perceber que o nome Repository era o único nome de padrão que eu ainda não tinha retirado das minhas classes de negócio. Eu também sempre fui avesso a usar nome de padrões nas classes mas sempre usei XPTORepository sem raciocinar muito. Também acho válido seu comentário sobre o EntityManager.

    Obrigado por (mais) essa contribuição. Abraços.

  • Luiz Costa

    Reply Reply 11/08/2009

    Oi Rodrigo, ótimo post.

    Achei muito interessante a forma como vc chama os Repositórios. Muito melhor e mais expressivo.
    Agora uma dúvida. Quando vc diz que um repositório pode processar regras de negócio, onde estas regras são processadas? Isso acontece na camanda de Infra? Eu imagino que nestes casos o repositório além de ter uma interface no domínio, tem também uma implementação concreta para processar estas regras de negócio, e além disso, delega para um objeto de infra as buscas no BD. Meu pensamento está correto?

    Valeu
    Luiz Costa

  • Bruno Viana

    Reply Reply 11/08/2009

    Gostei muito do artigo. Deu pra abrir um pouco mais a mente e me dar mais algumas ideias.

    Atuamente tenho estudado e tentado aplicar o conceito de Domain Specific Language. Acho que no caso dos repositórios seria mais interessante ao inves de fazer:

    PedidosFaturados.getAtrasados();

    Utilizar:

    TodosPedidos.faturados().atrasados();

    Não sei se seria bem assim, foi algo que se passou agora pela minha cabeça. O que acha?

  • Belo Post Yoshi!
    Estou montando uma série sobre DDD no meu blog e nas palestas aqui da empresa e vou utilizar isso como exemplo, ok?! rs

    Sobre a sua ideia de nomeação, sou extremamente a favor que as denominações tenham mais expressividade para a UL do que para os desenvolvedores, fazendo que o PedidoRepository se transforme em Pedidos.

    Só um questionamento: Se Reporitorios são para gerir as regras de negócio do domínio e, para uma maior testabilidade, eles devem ser/ter interface, vc apoia repositorios genêricos, para as ações comuns, como listarTodos, salvar, atualizar, excluir, etc?

  • Rodrigo Yoshima

    Reply Reply 11/08/2009

    @Tarso

    Obrigado Tarso.

    @Luiz Costa

    Luiz, o repositório sempre terá uma implementação e essa implementação vai responder pela interface. A implementação também é um elemento do domínio se ele tiver código de negócio. Na tecnologia atual, a implementação do seu ORM é que considero infra. Isso visa deixar as coisas mais simples.

    Seu pensamento está correto sim.

    @Bruno

    Na minha implementação é possível fazer isso: TodosPedidos.getFaturados().getAtrasados(). Só depende da forma que você obtém a instância de PedidosFaturados.

    Se o problema é a palavra “get”, isso é um jargão do Java, uma convenção apesar de parecer feio. Isso vem de longa data, antes mesmo do Java. Atualmente em Java eu vejo que “gets” é o que definimos na UML com operações sem efeito colateral (que não muda o estado do objeto).

    Se quiser tirar fique à vontade. Atualmente eu os mantenho.

    @Rodrigo Allemand

    Vou te falar que já usei também repositórios genéricos, mas ví também que isso poluia um pouco meus repositórios. Depois de um tempo tirei eles fora. Teve um determinado projeto que eu fiz um unico Repositório responsável por add e remove. Até gostei. Também teve projetos que para inserir e remover eu acessava EntityManager direto. De qualquer forma, eu não tenho usado repositórios genéricos não. Listar Todos é algo que não é usado em todas as entidades, então, não é motivo para generalizar…

  • Rodrigo Yoshima

    Reply Reply 11/08/2009

    Pessoal, mais um ponto… estou fazendo código Java destes exemplos, já que o post teve bons feedbacks. Assim que estiver pronto eu posto aqui…

    Abraços!

  • Dilter Porto

    Reply Reply 11/08/2009

    Yoshi, muito esclarecedor o post.
    Uma dúvida que me surgiu foi: eu tenho, portanto, lógica de negócios espalhada em repositórios, services e em métodos das Entidades de negócio ?

  • Rodrigo Yoshima

    Reply Reply 11/08/2009

    @Dilter

    Exatamente. Todos são elementos de domínio e a inteligência de negócio está neles. Se a responsabilidade é natural da entidade, então está na entidade. Se a responsabilidade não se aloca naturalmente a nenhuma entidade, então, crie um service. Se a responsabilidade é pertencente ao conjunto/grupo de entidades, então está no repositório.

    • Ricardo Longa

      Reply Reply 06/03/2013

      Caramba, ler este trecho “Se a responsabilidade é pertencente ao conjunto/grupo de entidades, então está no repositório.” me pareceu como um estalar de dedos. Fez cair a minha ficha quanto a uma dúvida antiga sobre DDD: uma pessoa tem a responsabilidade de retornar uma lista de pessoas (inclusive contendo ela mesma)?

      Agora sim as peças (entidades, serviços e repositórios) se encaixaram (espero ter entendido corretamente, desta vez).

  • Nossa, fazia tempo que não lia um post sobre repositórios e aprendia algo. Gostei da forma como você nomeia seus repositórios, vou passar a copiar hehe
    Ótimo post, podia virar um artigo na mundo java, seria infinitamente melhor para comunidade que artigos falando do demoiselle 😛

  • Rodrigo, muito bom o artigo. Concordo plenamente com a nomenclatura dada aos Repositórios, assim como o @Tarso mencionou, eu também percebi que os meus repositórios ainda recebiam o *Repository. Essa expressividade é muito pequena, na verdade sendo apenas mais uma “desinformação” no código. Muito tentou se falar sobre as diferenças entre DAOs e Repositories, para introduzir a idéia de Repository. E você conseguiu de uma forma simples e direta.
    Muito legal, parabéns!

  • Marcelo Menezes

    Reply Reply 11/08/2009

    Rodrigo, excelente post. Estou aguardando o fonte java.

    Abraço

  • Rafael Ponte

    Reply Reply 11/08/2009

    Muito bom Yoshi.

    O post ficou muito bom, e com certeza vai abrir a mente de muitos que ainda não leram o livro do Eric Evans ou mesmo não entenderam, de fato, o conceito de DDD.

    Os seus exemplos de Repository sem nomenclatura “XptoRepository” estão muito claros, e com certeza vai confundir a cabeça de muitos desenvolvedores acostumados a adotar nomenclaturas rígidas (não que em alguns casos elas não sejam importantes).

    Quanto ao uso do EntityManager (ou Session do Hibernate) eu sou a favor, seguindo a sua mesma linha de raciocínio. Se não faz diferença para o domínio então não há problemas em utiliza-lo. Existem exceções é claro, mas não fazer da exceção a regra é questão de bom senso.

    Eu cheguei a blogar sobre isso (http://www.rponte.com.br/2009/06/08/no-more-daos/), houve algumas discussões interessantes, mas a maior está hoje no GUJ.

    Sobre repositórios você pode ir até mais além dos teus exemplos, como uma entidade acessar um repositório em determinado momento (seja via construtor ou método que executa um comportamento especifico). Não há problemas nisso pois repositórios fazem parte do modelo de domínio. O problema é que estes casos não são muito comuns, ao menos não foram para mim até o momento, principalmente quando usamos um ORM como Jpa/Hibernate.

    Enfim, excelente post.

  • rodrigo saito

    Reply Reply 11/08/2009

    Muito bom o Post.
    Só que tenho algumas dúvidas.
    Se por exemplo, tivessemos uma outra entidade Fabricante, pois um produto tem um fabricante.
    Criariamos um repositório “TodosFabricantes” ou os métodos para inserir, buscar … fabricantes ficaria no repositório “TodosProdutos”?

  • Rubem Azenha

    Reply Reply 11/08/2009

    Excelente exemplos Rodrigo!

  • Rodrigo Yoshima

    Reply Reply 11/08/2009

    @Luiz Gustavo @Daniel
    Pode copiar a vontade, aliás, se pararmos para pensar deveríamos chamá-los sempre assim. Cara, este ano não escreví nada para a MundoJava. Eu tenho preferido escrever aqui de maneira mais rápida e com mais leitores.

  • Rodrigo Yoshima

    Reply Reply 11/08/2009

    @Rafael Ponte

    Eu injeto services e repositories nas minhas entidades sem problema nenhum. O único ponto é que para isso tem que fazer “magia negra” com AOP ou Interceptors do Hibernate. Pelo que me falaram uma vez o Spring tem uma maneira mais clean de fazer isso.

  • Rodrigo Yoshima

    Reply Reply 11/08/2009

    @rodrigo saito

    Um repositório por entidade. Não é conceitualmente certo e nem bonito um repositório responder por buscas de outras entidades mas há exceções. No nosso curso OOAD com UML eu dou um exemplo. Existe um requisito num sistema de hotel que é: O sistema apresenta a lista de quartos disponíveis para o período. Pergunta: Quem me fornece a lista de quartos disponíveis? a. O Repositório de Quartos ou b. Repositório de Reservas?

  • Ótimo post esclarecedor.

    Uma coisa que gostaria de acrescentar é que hoje em dia tenho evitado o prefixo get, exceto quando preciso usar o objeto por alguma taglib que necessita dessa convenção.

    Portanto, acho que poderia ficar mais legal TodosPedidos.cancelados() do que TodosPedidos.getCancelados().

    Grande abraço,

    Emerson

  • Leandro Silva

    Reply Reply 12/08/2009

    Ótimo post, Rodrigo!

    Concordo com muita coisa que você escreveu, cara. De dois anos pra cá (quando comecei com DDD), aprendi bastante coisa, mudei algumas opiniões, refinei outras, mas o principal: Aprendi que DDD não é sobre patterns — como você bem colocou.

    Ah! Achei bem legal os nomes dos seus repositórios. Sem o sulfixo “Repository” fica bem melhor mesmo. Há um tempo eu estava pensando em uma maneira de arrancar esse sulfixo bizarro, que não tem nada a ver com o negócio; acho que achei uma. E a próxima vitima seria o sulfixo Service. 🙂

  • Régis Soares

    Reply Reply 20/08/2009

    Olá Yoshima, primeiramente: excelente post! Esclareceu muitas dúvidas. Parabéns.

    Vamos a minha dúvida: como trata as questões de paginação em suas aplicações: no próprio repositório ou em um componente (camada) independente? Visto que é inviável ter em qualquer aplicação algo como TodosPedidos.getTodos()

    Pensei em algo como ConsultasPedidos.getPorIntervalo(inicio, tamanho), – os nomes estão péssimos, mas foi a primeira coisa que veio na mente – colocando isso em um componente independente (fora do domínio), pois para o cliente (usuário) isso não importa, é um detalhe de implementação. O que acha?

    abs

  • Rodrigo Yoshima

    Reply Reply 20/08/2009

    Nada impede deixar as paginações no repositório, porém, de fato, isso não é lá muito elegante, pois paginações são responsabilidades do caso de uso (camada de aplicação) e não do domínio.

    A última vez que tive que fazer isso a responsa foi para o repositório, mas estou pensando uma coisa aqui agora: será que não seria possível deixar isso para a camada de aplicação usando alguma estratégia de lazy loading?

    Algo para pensarmos.

  • Régis Soares

    Reply Reply 20/08/2009

    O lazy loading é, quase sempre, uma boa prática. Porém, mesmo a carga tardia dos dados, pode trazer muita coisa, e o intervalo terá q ser passado para o repositório em algum momento. Tenho mais perguntas do que respostas em minha cabeça nesse momento.

    PS: aguardo seus códigos deste post

  • Magno Machado

    Reply Reply 21/08/2009

    Faz pouco tempo que comecei a estudar conceitos como repositório e DDD, e este seu post foi uma das melhores fontes de informação que encontrei sobre repository até agora.
    Mas ficou uma dúvida: Se o repositório não vai acessar o mecanismo de persistencia diretamente, então como seria? através de DAO?

    • Ricardo Longa

      Reply Reply 06/03/2013

      Pelo o que eu entendi sim, pelo DAO (infra-estrutura).

      Como o Repositório trata (e contém regras de negócio) de uma coleção de entidades, deve fazer parte do seu domínio. Logo, o DAO fica com a responsabilidade apenas de comunicação com a base de dados, ou seja, um objeto da sua camada de infra-estrutura.

      Lembre-se que o Repositório não sabe onde as entidades estão armazenadas (arquivo texto, base de dados, …), esta inteligência fica sob responsabilidade da sua infra-estrutura (seus DAOs).

      Me corrijam se eu estiver errado.

      • Ricardo. Seu raciocínio está certo. O domínio não precisa saber sobre infra-estrutura. Abraços!

  • Antonio Jr

    Reply Reply 21/08/2009

    Yoshima,
    Meus parabéns! Muito esclarecedor o enfoque que voce deu aos “Repositorios”.
    Estou, no momento, lendo o livro “Clean Code” do Robert Martin (Uncle Bob) e logo no início ele defende a importância na escolha dos nomes de variáveis, classes, métodos, etc. É como escolher o nome dos seus filhos.
    Esses prefixos e sufixos que nós desenvolvedores utilizamos na implementação, realmente, não acrescenta nada ao domínio do negócio, pelo contrário, só atrapalha.
    Vou ficar aguardando o código…

  • Eu gosto da nomenclatura pelo fato de ela deixar bem explícito o que aquele objeto significa. Se você lê PedidoRepository, você sabe que está implementando o Repository Pattern.

    Mas aí você comentou sobre o ProdutoEntity, não precisamos do Entity pois produto já é algo bem concreto para todo mundo.

    Se você colocar todos os repositórios dentro de um pacote model.repositories, por exemplo, aí resolve, fica fácil dar uma identidade para as classes deste pacote.

    Ótimo post.

  • Rodrigo Yoshima

    Reply Reply 26/08/2009

    Guilherme, eu considero o empacotamento também algo do domínio, isto é, muito do empacotamento eu também discuto com o usuário, principalmente o empacotamento do domínio.

  • Mateus

    Reply Reply 05/09/2009

    Rodrigo,

    Mesmo com AOP ou Hibernate interceptores ainda falta uma perna com relação a injeção de Repositories. Quando eu dou apenas um “new” em meu POJO, como os repositories seriam injetados automaticamente? Via AOP é possível?

    Abraço

  • Ótimo post, Rodrigo.
    Estou lendo o livro DDD, do Evans, e fiquei com uma dúvida quanto a sua implementação: não percebi a necessidade de criação de dois respositórios para a entidade Pedido (TodosPedidos e PedidosFaturados). Não seria “Faturado” um predicado de Pedido? Dessa maneira, teríamos apenas a interface Pedidos e, poderíamos implementar esse predicado como uma especificação(Specification pattern). Escrevi um pouco sobre essa implementação no meu blog (http://hamonvitorino.wordpress.com/2009/09/03/ddd-implementando-repository-com-specifications/) e gostaria de entender o motivo da sua abordagem.

    Abraços

  • Mateus, é possível fazer com AOP, mas deve valer a pena colocar essa complexidade. As vezes isso prejudica um pouco a testabilidade se o que você for injetar for difícil de mockar.

    Hamon, uso Specifications mais para “buscas que podem receber vários parâmetros opcionais”, como uma tela de busca e coisas do tipo. Usar specification para termos firmes da linguagem do domínio fica pouco ubiquitous. Entendeu? Note também que neste caso em específico “PedidosFaturados” só foi criado pois era um termo recorrente na linguagem. Para esse caso fez sentido criar um elemento com semântica própria.

  • Rodrigo, specifications devem apoiar-se em termos recorrentes da linguagem, mais precisamente nos predicados que podemos aplicar a uma entidade.
    Se entendi bem o que você quis dizer, a criação do repositório PedidosFaturados deu-se devido à existência de predicados aplicáveis somente a esse tipo de Pedido, correto?

  • Otávio

    Reply Reply 15/09/2009

    Olá Rodrigo, parabéns pela iniciativa de escrever sobre DDD, estou muito interessado em aprender realmente DDD, até consegui entender vários pontos, mais ainda tenho algumas duvidas, uma delas é a seguinte se a minha regra de negócio fica na entidade (quando diz respeite a seu estado) e no repository, o que sobra para o service? Validações da entidade? E a outra pergunta é a seguinte, sempre da minha camada de apresentação, tenho que chamar minha service(Aplicação) que chama assim o repositorio(Dominio)? Se algum conceito estiver errado por favor me corriga. E seria pedir demais, pra quando tiver um tempo disponibilizar um CRUD da vida em java aplicando DDD?

    Abraço

  • @Hamom

    Isso mesmo! O termo PedidosFaturados era tão recorrente e tinha tanta coisa que acontecia com eles especificamente que valeu a pena criar um elemento com semântica própria.

    @Otávio
    Os services na maioria das vezes orquestram algumas tarefas que não são naturalmente alocáveis a nenhuma entidade. O melhor exemplo é o faturamento. Para faturar é necessário mudar o status do pedido, emitir uma nota fiscal, analisar crédito do cliente, gerar duplicatas e etc… Como o próprio Evans diz, certos elementos não são coisas, são processos. Validações da entidade estão na própria entidade. Sobre Layering (camadas) a discussão é grande, mas é comum aparecer esse padrão que você falou, a tela associada a uma facade de aplicação e a facade lidando com o domínio. Nada impede que um elemento de domínio vaze para a tela.

  • Otávio

    Reply Reply 23/09/2009

    Obrigado pela resposta Rodrigo, me expressei de forma equivocada, quando quis dizer validações de entidade, estava falando de verificar se a entidade populada por exemplo que recebi de um client, esta com os argumentos válidos, seguindo a idéia de “contratos” (Verifico a entrada para saber se é válido o objeto). Onde ficaria estas validações? não imagino como ficaria isso na própria entidade. E uma coisa que acho que estava quebrando um pouco meu DDD, é utilizar Repository como se fosse um DAO, uma classe que fornece recurso externos para o objeto (entidade) em questão, mais pelo que vi vc descrever o repository envolve regras de negócio do domínio tb, e não apenas na entidade.

  • Eldon

    Reply Reply 30/09/2009

    Rodrigo Yoshima,

    A respeito do repositório PedidosFaturados, lhe pergunto, qual a sua agregação neste caso, sim porque o Evans deixa claro que os repositórios devem ser descritos para uma agregação, Perceba que pedidos faturados é uma característica do pedido, o conceito de negócio é o pedido e provavelmente deve ser a sua raiz de agregação. Imagine em um sistema grande, criar repositórios para cada carecterística forte de um conceito, imagine, por exemplo, no domínio de negócio recursos humanos, os seguintes “repositórios” funcionários em férias, funcionários em aviso prévio, funcionários em licença maternidade, etc. A raiz da agregação é o funcionário!

    Outra coisa, sei que a interface do repositório faz parte do domínio, mas existe algumas dúvidas em relação ao seu uso diretamente nas Entidades. Perceba que os métodos do repositório podem receber como parâmetros objetos de negócio do domínio, então em uma entidade talvez não seja natural acessar tais métodos, já que isto levaria a um acoplamento da entidade a conceitos não naturalmente acoplados a ela.

    Em relação a implementação de regras de negócio na classe que implementa a interface do repositório sou contra. Evans deixa claro que o papel dos repositórios e a reconstituição ou simples contagem de objetos. No seu exemplo, IMHO, estas regras deveriam ser escritas em um serviço (logicamente com o auxílo do repositório) ou até mesmo em uma entidade que acesse o repositório. Em seu exemplo, o cumprimento das regras de negócio envolvidas na operação “obter produtos disponíveis na data de entrega” vai além das responsabilidades de um repositório.

  • Marco Testa

    Reply Reply 28/04/2011

    Oi Rodrigo,

    Tenho uma duvida: digamos que tenho uma classe chamada Cliente, e ela possui uma propriedade chamada Pedidos, que retorna a coleção de pedidos daquele cliente.

    É coerente utilizar a interface do repositorio dentro da classe Cliente (injentando mais tarde a sua implementação), e quando eu acessar a propriedade Pedidos, ele já consulta o repositório específico, retornando os pedidos daquele cliente?

  • Veranildo Veras

    Reply Reply 11/01/2014

    Pode até existir um repositório para uma classe, isso depende do contexto. Na maioria das vezes eles representam coleções de objetos “Acho que também posso dizer agregações de classes”.

    Outra coisa, o domínio não conhece os repositórios pois os mesmo devem fica na layer “Layer, neste caso refere-se a camada lógica” de infra, no máximo o que o repositório pode fazer é perguntar se o objeto do domínio no qual está sendo tratado é válido.

    Turma espero ter contribui, abraços.

Leave A Response

* Denotes Required Field