Qual é a diferença entre os padrões Data Mapper, Table Data Gateway (Gateway), Data Access Object (DAO) e Repository?

133

Estou tentando aprimorar minhas habilidades de padrão de design e estou curioso para saber quais são as diferenças entre esses padrões. Todos eles parecem ser a mesma coisa - encapsula a lógica do banco de dados para uma entidade específica, para que o código de chamada não tenha conhecimento da camada de persistência subjacente. De minha breve pesquisa, todos eles geralmente implementam seus métodos CRUD padrão e abstraem os detalhes específicos do banco de dados.

Além das convenções de nomenclatura (por exemplo, CustomerMapper vs. CustomerDAO vs. CustomerGateway vs. CustomerRepository), qual é a diferença, se houver? Se houver uma diferença, quando você escolheria uma sobre a outra?

No passado, eu escrevia um código semelhante ao seguinte (simplificado, naturalmente - eu normalmente não usaria propriedades públicas):

public class Customer
{
    public long ID;
    public string FirstName;
    public string LastName;
    public string CompanyName;
}

public interface ICustomerGateway
{
    IList<Customer> GetAll();
    Customer GetCustomerByID(long id);
    bool AddNewCustomer(Customer customer);
    bool UpdateCustomer(Customer customer);
    bool DeleteCustomer(long id);
}

e tem uma CustomerGatewayclasse que implementa a lógica específica do banco de dados para todos os métodos. Às vezes, eu não usava uma interface e tornava estáticos todos os métodos no CustomerGateway (eu sei, isso o torna menos testável), para que eu possa chamá-lo assim:

Customer cust = CustomerGateway.GetCustomerByID(42);

Esse parece ser o mesmo princípio para os padrões Data Mapper e Repository; o padrão DAO (que é a mesma coisa que Gateway, eu acho?) também parece incentivar gateways específicos do banco de dados.

Estou esquecendo de algo? Parece um pouco estranho ter 3-4 maneiras diferentes de fazer a mesma coisa.

Wayne Molina
fonte

Respostas:

96

Seu exemplo de termos; DataMapper, DAO, DataTableGateway e Repository, todos têm um objetivo semelhante (quando eu uso um, espero recuperar um objeto Customer), mas com intenção / significado diferente e implementação resultante.

Um repositório "atua como uma coleção, exceto com capacidade de consulta mais elaborada" [ Evans, Domain Driven Design ] e pode ser considerado como um "objeto na fachada da memória" ( discussão do repositório )

Um DataMapper "move dados entre objetos e um banco de dados, mantendo-os independentes um do outro e do próprio mapeador" ( Fowler, PoEAA, Mapper )

Um TableDataGateway é "um Gateway (objeto que encapsula o acesso a um sistema ou recurso externo) a uma tabela do banco de dados. Uma instância lida com todas as linhas da tabela " ( Fowler, PoEAA, TableDataGateway )

Um DAO "separa a interface do cliente de um recurso de dados dos seus mecanismos de acesso a dados / adapta a API de acesso de um recurso de dados específico a uma interface genérica do cliente" permitindo "que os mecanismos de acesso a dados sejam alterados independentemente do código que usa os dados" ( Sun Blueprints )

O repositório parece muito genérico, não expondo nenhuma noção de interação com o banco de dados. Um DAO fornece uma interface que permite que diferentes implementações de banco de dados subjacentes sejam usadas. Um TableDataGateway é especificamente um invólucro fino em torno de uma única tabela. Um DataMapper atua como um intermediário, permitindo que o objeto Model evolua independentemente da representação do banco de dados (ao longo do tempo).

Pierce Hickey
fonte
15
Na verdade, não há grande diferença entre o DAO e o TableDataGateway e em [Fowler, PoEAA] [1] eles dizem exatamente isso: "[Alur et al.] [2] discute o padrão Data Access Object, que é um Table Data Gateway. .. Eu usei um nome diferente, em parte porque vejo esse padrão como um uso particular do conceito mais geral do Gateway (466) e quero que o nome do padrão reflita isso. " [1]: martinfowler.com/books/eaa.html [2]: books.google.pt/books/about/…
Miguel Gamboa
9
Bom ponto. Minha impressão é que a definição fornecida por PoEAA de TableDataGateway é mais estreita que DataAccessObject. O primeiro parece implicar um mapeamento individual com uma tabela de banco de dados (relacional), onde um DAO pode atuar como uma fachada para vários recursos não relacionais subjacentes. A ênfase em um DAO é a capacidade de substituir o armazenamento de dados subjacente, a ênfase em TableDataGateway é o encapsulamento de operações SQL em uma única tabela (não necessariamente de maneira neutra / portátil do armazenamento de dados).
Pierce Hickey
31

Existe uma tendência no mundo do design de software (pelo menos eu acho) de inventar novos nomes para coisas e padrões antigos bem conhecidos. E quando temos um novo paradigma (que talvez seja um pouco diferente das coisas já existentes), geralmente ele vem com um conjunto inteiro de novos nomes para cada camada. Assim, "Business Logic" se torna "Services Layer" apenas porque dizemos que fazemos SOA, e o DAO se torna Repositório apenas porque dizemos que fazemos DDD (e cada um deles não é realmente algo novo e único, mas novamente: novos nomes para conceitos já conhecidos reunidos no mesmo livro). Portanto, não estou dizendo que todos esses paradigmas e siglas modernos significam EXATAMENTE a mesma coisa, mas você realmente não deveria estar muito paranóico com isso. Principalmente esses são os mesmos padrões, apenas de famílias diferentes.

Dmitry Perets
fonte
4
@MladenMihajlovic, apenas porque você não entende ou concorda, não significa que esta resposta não seja válida ou que o evento esteja correto.
Cypher
2
@MladenMihajlovic não é o que esta resposta diz. A última frase resume isso.
Cypher
2
@ Code Estes padrões são basicamente os mesmos? Não, eles não são. A implementação do padrão de gateway é diferente da implementação do padrão de repositório. Eles podem parecer iguais aos olhos não treinados, mas não são. Além disso, como Mladen Mihajlovic apontou corretamente, esta resposta está completamente errada. A lógica de negócios e a camada de serviço são duas coisas diferentes.
Frederik Krautwald
1
@ Cypress Não é realmente uma questão de opinião, mas fatos. O padrão Gateway foi formulado por Martin Fowler em seu PoEAA e está principalmente relacionado aos padrões Facade ou Adapter [GoF]. As distinções são que o Gateway foi escrito para um uso específico e geralmente não existe uma interface existente. O Gateway, geralmente, envolve apenas dois objetos, e o recurso que está sendo agrupado não tem conhecimento do Gateway. (continua ...)
Frederik Krautwald
3
Isso é mais um comentário do que uma resposta.
Pétur Ingi Egilsson
31

Data Mapper vs Table Data Gateway Para resumir uma longa história:

  • o Mapeador de Dados receberá o objeto Modelo de Domínio (Entidade) como parâmetro e o utilizará para implementar as operações CRUD
  • o Table Data Gateway receberá todos os parâmetros (como primitivos) dos métodos e não saberá nada sobre o objeto Modelo de Domínio (Entidade).

    No final, os dois atuarão como mediadores entre os objetos na memória e o banco de dados.

  • nascar
    fonte
    6
    o link ficou obsoleto
    imel96
    15

    Você tem um bom argumento. Escolha o que você está mais familiarizado. Eu gosto de apontar algumas coisas que podem ajudar a esclarecer.

    O Gateway de dados da tabela é usado principalmente para uma única tabela ou exibição. Ele contém todas as seleções, inserções, atualizações e exclusões. Portanto, o Cliente é uma tabela ou uma visualização no seu caso. Portanto, uma instância de um objeto de gateway de dados da tabela lida com todas as linhas da tabela. Geralmente, isso está relacionado a um objeto por tabela do banco de dados.

    Enquanto o Data Mapper é mais independente de qualquer lógica de domínio e é menos acoplado (embora eu acredite que haja ou não acoplamento). É apenas uma camada intermediária para transferir os dados entre objetos e um banco de dados, mantendo-os independentes um do outro e do próprio mapeador.

    Portanto, normalmente em um mapeador, você vê métodos como inserir, atualizar, excluir e, no gateway de dados da tabela, encontrará getcustomerbyId, getcustomerbyName, etc.

    O objeto de transferência de dados difere dos dois padrões acima, principalmente porque é um padrão de distribuição e não um padrão de fonte de dados como acima dos dois padrões. Use-o principalmente quando estiver trabalhando com interface remota e precisar tornar suas chamadas menos tagarelas, pois cada chamada pode ficar cara. Por isso, geralmente projete um DTO que possa ser serializado por fio que possa transportar todos os dados de volta ao servidor para aplicar outras regras ou processamento de negócios.

    Não sou muito versado no padrão de repositório, pois não tive a chance de usá-lo até agora, mas estarei olhando para as respostas de outras pessoas.

    Srikar Doddi
    fonte
    1

    Abaixo está apenas o meu entendimento.

    TableGateWay / RowDataGateWay : nesse contexto, o Gateway está se referindo a uma implementação específica que tem cada "objeto de domínio" mapeado para cada "gateway de objeto de domínio". Por exemplo, se tivermos Person , teremos um PersonGateway para armazenar o objeto de domínio Person no banco de dados. Se tivermos Pessoa, Funcionário, Cliente, etc., teremos PersonGateway, EmployeeGateway e CustomerGateway. Cada gateway terá uma função CRUD específica para esse objeto e não tem nada a ver com outro gateway. Não há código / módulo reutilizável aqui. O gateway pode ser dividido em RowDataGateway ou TableGateway, depende se você passar um "id" ou um "objeto". O gateway geralmente é comparado ao registro ativo. Ele vincula seu modelo de domínio ao esquema do banco de dados.

    Repositório / DataMapper / DAO : Eles são a mesma coisa. Todos eles se referem à camada Persistência que transfere entidades do banco de dados para o modelo de domínio. Ao contrário do gateway, o Repositório / DataMapper / DAO oculta a implementação. Você não sabe se existe uma PersonGateway atrás da Person. Pode ou não, você não se importa. Tudo que você sabe é que deve haver operações CRUD suportadas para cada objeto de domínio. Ele desacopla a fonte de dados e o modelo de domínio.

    Hao Lu
    fonte