Relação entre Repositório e Unidade de Trabalho

17

Vou implementar um repositório e gostaria de usar o padrão UOW, pois o consumidor do repositório poderia executar várias operações, e quero confirmá-las de uma só vez.

Depois de ler vários artigos sobre o assunto, ainda não entendo como relacionar esses dois elementos, dependendo do artigo que está sendo feito de uma maneira ou de outra.

Às vezes, o UOW é algo interno ao repositório:

public class Repository
{
    UnitOfWork _uow;

    public Repository()
    {
       _uow = IoC.Get<UnitOfWork>();
    }

    public void Save(Entity e)
    {
        _uow.Track(e);
    }

    public void SubmittChanges()
    {
        SaveInStorage(_uow.GetChanges());
    }
}

E às vezes é externo:

public class Repository
{
    public void Save(Entity e, UnitOfWork uow)
    {
        uow.Track(e);
    }

    public void SubmittChanges(UnitOfWork uow)
    {
        SaveInStorage(uow.GetChanges());
    }
}

Outras vezes, é o UOW quem faz referência ao Repositório

public class UnitOfWork
{
    Repository _repository;

    public UnitOfWork(Repository repository)
    {
       _repository = repository;
    }

    public void Save(Entity e)
    {
        this.Track(e);
    }

    public void SubmittChanges()
    {
       _repository.Save(this.GetChanges());
    }
}

Como esses dois elementos estão relacionados? O UOW rastreia os elementos que precisam ser alterados e o repositório contém a lógica para persistir essas alterações, mas ... quem chama quem? O último faz mais sentido?

Além disso, quem gerencia a conexão? Se várias operações tiverem que ser feitas no repositório, acho que usar a mesma conexão e até a transação é mais sólida, então talvez coloque o objeto de conexão dentro da UOW e essa dentro do repositório faça sentido também.

Felicidades

NullOrEmpty
fonte

Respostas:

7

Re: "UOW rastreia os elementos que precisam ser alterados, e o repositório contém a lógica para persistir essas alterações, mas ... quem chama quem?"

Você entende as responsabilidades básicas dessas classes. Você diz que cada um dos artigos que você leu os conecta de maneiras diferentes. Isso implica que a decisão sobre "quem liga para quem" depende de você.

Eu tentava esboçar o problema em termos de 'camadas' enquanto era guiado por princípios básicos de bom design de software, como Coesão , Desacoplamento , Reutilização , Testabilidade de Unidade etc.

Para citar Eric Evans Domain Driven Design, (2004) Addison Wesley, página 69 :

O princípio essencial [das arquiteturas em camadas] é que qualquer elemento de uma camada depende apenas de outros elementos na mesma camada ou de elementos das camadas "abaixo" dela.

Na minha opinião, tanto o UOW quanto o Repo são duas classes muito diferentes que têm responsabilidades claras e independentes. Para começar, eu não faria nem invocar o outro.

Eu acho que você precisa de uma terceira classe de cliente (ou seja, um controllerou service class) que realmente saiba 'quando e o que obter' do repositório e 'quando' para salvar a transação. Esse cliente fica relativamente alto na arquitetura (para saber mais sobre classes) e pode fazer alguma orquestração entre as duas.

--------------------------------

         [Client]
           /   \
----------/---- \---------------
         /       \
        V         V
[Unit Of Work]  [Repo]


--------------------------------
JW01
fonte
2

Os métodos são mais comumente dados à interface UOW (que normalmente é construída via fábrica).

Você normalmente chama métodos em uma interface UOW a partir de classes / fachada de padrão de comando. Como o UOW simplesmente adia a IO do banco de dados até mais tarde (para impedir que você tenha transações de longa duração ou várias chamadas desnecessárias ao banco de dados), trabalhar com o UOW deve estar no mesmo nível em que você normalmente trabalha com o banco de dados.

A Microsoft tem uma publicação muito completa sobre o padrão UOW:

http://msdn.microsoft.com/en-us/magazine/dd882510.aspx

Graeme Wicksted
fonte