Tuesday, July 10, 2012

Aplicando os padrões "Repository" e "Unity of Work"


No último post, abordei uma maneira de construir aplicações persistentes usando o entity Framework Code First Library. Hoje irei mostrar como podemos aplicar os padrões "Repository" e "Unity of Work" nestas aplicações, mesmo que não tenhamos o modelo do banco pré-definido.

O Padrão Repository:


Media as camadas de domínio e mapeamento de dados usando uma interface de coleção, para acessar objetos do domínio. Utilizado para atingir um ou mais dos seguintes objetivos:

·         Maximizar a quantidade de código que pode ser testada com  automação e isolar a camada de dados para suportar os testes.
·         Você pode acessar a fonte de dados de diversas localidades e deseja aplicar gerenciadores centrais, regras de acesso consistentes e lógica.
·         Implementar e centralizar uma estratégia de cache para a fonte de dados.
·         Melhorar a manutenção do código e a legibilidade.
·         Usar entidades fortemente tipadas para que você possa identificar os problemas em tempo de compilação em vez de em tempo de execução.
·         Associar um comportamento com os dados relacionados. Por exemplo, você deseja calcular campos ou impor relações complicadas ou aplicar regras de negócios entre os elementos de dados dentro de uma entidade.
·         Você deseja aplicar um modelo de domínio para simplificar a lógica de negócios complexos.



O Padrão Unity Of Work:


Um dos padrões de design mais comuns em EAA, este padrão "mantém uma lista de objetos afetados por uma transação e coordena a escrita de alterações e a resolução dos problemas de concorrência.".

Este padrão aparece em quase todos os frameworks de persistência mais comuns no mercado de hoje. Por exemplo: a interface ITransaction em NHibernate, a classe DataContext no LINQ to SQL, e a classe ObjectContext no Entity Framework.

Se você fosse construir o seu próprio Unity of Work, seria provavelmente algo parecido com esta interface:
public interface IUnitOfWork {
  void MarkDirty(object entity);
  void MarkNew(object entity);
  void MarkDeleted(object entity);
  void Commit();
  void Rollback();
}
Sua classe deve conter métodos para marcar entidades como alteradas, novas ou excluídas e para confirmar ou reverter todas as mudanças.
De certa forma, você pode pensar no Unit of Work como um lugar para despejar todo o código de manipulação de transação.
As responsabilidades da Unidade de Trabalho são:
Gerenciar as transações.
Ordenar as inserções de banco de dados, exclusões e atualizações.
Impedir duplicação de atualizações.



Aplicação Prática:
Desta vez vamos construir um projeto que será desenvolvido por uma equipe. Vamos usar o team Foundation System como controlador de versão do nosso código.

01 - Abra o Visual Studio 2010, clique em File > New > Team Project.


02 - Escolha um nome para o projeto e o template de desenvolvimento (Agile ou PMP).
03 - Escolha "Create an empty source control folder" e clique em Finish.


04 - Abra seu projeto no Source Control Explorer
05 - Crie as pastas para controle de branching. Eu sempre crio as seguintes pastas:
Dev: Contém os branchs criados para desenvolvimento.
Main: Conttém o Trunk Principal da aplicação
QA: Sempre que o código é promovido para o ambiente de homologação criamos um novo branch nesta pasta e dividimos em Original e Fixes.
Prod: Sempre que o código é promovido para o ambiente de produção criamos um novo branch nesta pasta e dividimos em Original e Fixes.



06 - Crie uma pasta com a data atual dentro do folder Dev e mapeie o diretorio raiz do projeto para um folder local.
07 - Crie uma nova "Empty Solution" neste folder, no meu caso escolhi o nome PeopleOrganizer
08 - Adicione a solution recém criada um projeto "Class Library" com o nome DataAccessLayer.
09 - Crie no projeto DataAccessLayer os seguintes diretórios:
DataContexts
Model
Repositorios
UnityOfWork
10 - Adicione a referência a biblioteca Microsoft ADO.NET Entity Framework Feature CTP5 (ver post anterior)
11 - Adicione ao diretório UnityOfWork uma classe Base.cs, ela será responsável por fornecer uma classe base para implementação do padrão Unity Of Work em N datacontexts. Ela deve conter  o seguinte código:



12 - Adicione ao diretório Repositorios um novo diretório chamado Base.
13 - Neste diretório adicione uma classe IRepositorio.cs, ela será responsável por definir o contrato básico de todos os repositórios do projeto. Ela deve conter  o seguinte código:

14 - Ainda no mesmo diretório adicione uma classe Repository.cs, ela servirá como classe base para nossos repositórios,  implementando IRepository e um DataContext genérico através da injeção de dependência no construtor. Segue o código abaixo:



15 - Agora vamos criar uma classe POCO que representa uma entidade no nosso modelo. Dentro da pasta Model, crie uma sub-pasta chamada Core e dentro desta uma pasta chamada Autenticacao.

16 - Adicione uma referência a System.ComponentModel.DataAnnotations ao projeto.

17 - Dentro da pasta Autenticacao, crie uma classe Usuario.cs com o seguinte código



18 - Agora vamos criar um repositório para a entidade Usuario. Dentro da pasta Repositorios, crie uma pasta Core, dentro desta pasta crie uma classe Usuarios com o código abaixo.



19 - Agora vamos criar nosso Contexto e a unidade de trabalho responsável por administra-lo. Dentro da pasta DataContexts, crie uma pasta Core e dentro dela uma classe Context.cs com o seguinte código



20 - Crie agora uma classe UnityOfWork.cs  , que será responsável por administrar todas as operações feitas no contexto Core. Segue abaixo o código.



21 - Podemos criar o método de testes abaixo para validar nosso modelo. (Crie um App.config para informar a connection string)



22 - Após executar o teste, vemos o resultado positivo e o registro incluido no banco de dados recém criado pelo EF.




A estrutura final do projeto deve ficar parecida com a imagem abaixo:





1 comment: