VB .NET - Implementando o padrão Repository


Uma das maneiras de alcançar a "persistence ignorance" (ignorância em persistência) é construir uma fachada entre a camada de acesso a dados e a camada de lógica de negócios. Tal fachada irá prevenir o conhecimento da tecnologia usada no acesso a dados e como ele é feito. Esta abstração pode ser obtida usando o Padrão Repository.

Obs: Por persistence ignorance entendemos que uma entidade para ser persistida pelo Entity framework, não precisa herdar de uma classe específica, ou implementar interface específica.

Antes de continuar eu quero deixar bem claro que um padrão de projeto não esta vinculado a nenhuma linguagem de programação. Assim podemos implementar um padrão de projeto usando qualquer linguagem que tenha os recursos para isso e neste artigo eu vou usar a linguagem VB .NET mas poderia ter usado C#.

Obs: Vou usar as seguintes traduções no texto: Design Patters -> Padrões de Projeto , Pattern -> Padrão, Design -> Projeto, Vou usar o nome do padrão no original : Repository.

Martin Fowler descreveu a definição tradicional do padrão de projeto Repository (Repositório) como : "mediador entre as camadas de domínio e mapeamento de dados usando uma interface de coleção, como para acessar objetos de domínio ", ou seja, um repositório media o relacionamento entre o dominio e os dados.

Esta definição tradicional descreve o padrão de projeto Repository como uma classe que mapeia para tabelas do banco de dados, contendo, Insert, Update, Select, Delete e funções de coleções para persistir um objeto de determinada classe no banco de dados.

Na figura abaixo retirada de
http://www.martinfowler.com/eaaCatalog/repository.html temos uma visão de como funciona o padrão Repository:

Pela figura podemos deduzir que o nosso domínio ou camada de negócios vai sempre acessar o repositório para realizar as operações CRUD (create, update, delete) no banco de dados.

No nosso exemplo, vamos criar a nossa própria implementação do Padrão Repository e ela necessáriamente não tem obrigação de ser genérica nem de suportar o conjunto completo de funções CRUD, o objetivo é se beneficiar dos recursos do padrão de Repository como : o desacoplamento código e a separação lógica das camadas.

Implementando o padrão Repository em uma aplicação Windows Forms usando a linguagem VB .NET

Vamos criar uma aplicação Windows Forms usando o Visual Basic 2010 Express Edition com o nome de Padrao_Repository;

No menu File->New Project selecione Windows Forms Application informe o nome PadraoRepository e clique em OK;

Em seguida vamos incluir um novo projeto onde definiremos a nossa camada de acesso a dados usando o Entity Framework;

No menu File -> Add -> New Project selecione o item Class Library e informe o nome Model;

Precisamos definir o nosso domínio , o nosso modelo conceitual ou modelo de entidades e vamos fazer isso usando a ferramenta ORM Entity Framework da Microsoft.

Selecione o projeto Model criado e no menu Project -> Add New Item selecione ADO .NET Entity Data Model, informe o nome Aluno.edmx e clique em Add;

A seguir selecione o item Empty Model pois vamos criar a tabela a partir do modelo de entidades que vamos criar:

A seguir na janela do descritor vamos definir a entidade Aluno contendo as propriedades: Id , Nome, Idade e Email

Obs: Para incluir uma propriedade use o menu suspenso e selecione Add->Scalar Property definindo a seguir seu nome e tipo de dados;

A seguir vemos a entidade criada e os mapeamentos gerados:

 

Vamos gerar agora os scripts para criar a tabela Alunos. Antes devemos criar um banco de dados no SQL Server que irá conter a tabela e eu criei o banco de dados Cadastro.mdf;

Clicando com o botão direito sobre a entidade podemos escolher a opção : Generate DataBase from Model;

Obs: Aqui estamos usando o Model First que permite definirmos o nosso domínio dentro do Visual Studio e após concluído a especificação gerarmos o script de criação do banco de dados;

Será gerado o script para criação da tabela contido no arquivo Aluno.edmx.sql. Para criar a tabela basta se conectar com o banco de dados e executar o script sem sair do ambiente do IDE;

Após criar a tabela a partir do modelo eu inclui alguns registros na tabela conforme a figura abaixo:

Agora vamos acessar o modelo de entidades, obter informações dos alunos e exibir em um DataGridView no formulário form1.vb;

Abra o projeto PadroRepository e inclua o formulário form1.vb um botão de comando e um controle DataGridView conforme o leiaute abaixo:

Defina uma referência no projeto PadraoRepository para o projeto Model e não esqueça de copiar o arquivo App.Config para o projeto WIndows Forms;

Após isso no formulário form1.vb declare o seguinte código no evento Click do botão Alunos:

Imports Model
Public Class Form1

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAlunos.Click
        Dim entidades As New ClienteContainer
        Dim alunos = From a In entidades.Alunos Select a

        gdvAlunos.DataSource = alunos.ToList

    End Sub
End Class

Executando o projeto iremos obter:

Tudo bem, tudo certo , mas agora vamos implementar o tal padrão Repository.

Quando queremos usar o Padrão Repository geralmente começamos definindo uma interface que será a nossa fachada de acesso a dados.

Selecione o projeto Model e no menu Project->Add Class informe o nome IRepositoryAluno.vb e a seguir defina o seguinte código nesta interface:

Public Interface IRepositoryAluno

    Function ListaAll() As IList(Of Aluno)

End Interface

Acima temos a interface IRepostioryAluno contendo a assinatura do método ListaAll que retorna uma coleção de objetos Aluno;

Agora vamos definir uma classe concreta chamada AlunosRepository que implementa esta interface no projeto Model;

Public Class AlunosRepository
    Implements IRepositoryAluno

    Private ctx As AlunoContainer
    Public Sub New()
        ctx = New AlunoContainer
    End Sub

    Public Function ListaAll() As System.Collections.Generic.IList(Of Aluno) Implements IRepositoryAluno.ListaAll
        Dim alunos = From a In ctx.Alunos Select a
        Return alunos.ToList
    End Function
End Class

O objetivo desta classe é fazer o acesso às entidades e retornar uma lista de objetos Aluno.

Finalmente vamos alterar o código do botão de comando Alunos no formulário form1.vb:

Imports Model
Public Class Form1

    Private Sub btnAlunos_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAlunos.Click

        'Dim entidades As New AlunoContainer
        'Dim alunos = From a In entidades.Alunos Select a
        Dim alunosRepositorio As IRepositoryAluno = New AlunosRepository
        gdvAlunos.DataSource = alunosRepositorio.ListaAll
    End Sub
End Class

Observe que agora estamos acessando o repositório e usando o método ListaAll definido na classe AlunosRepositorio e não mais acessamos o Entity Framework diretamente.

Obs:Deixei as duas linhas da versão sem repositório comentadas para comparação.

Essa é uma implementação possível do padrão Repository. Na verdade uma implementação muito simples que tem apenas o propósito didático de mostrar a como implementar este padrão. Assim podemos fazer a implementação do padrão para Linq to SQL, NHibernate, ADO .NET, etc.

Motivos para usar o Padrão Repository:

  1. Testabilidade - Usando o padrão, podemos criar stubs que pode substituir os objetos de acesso a dados reais. Isso pode Ajude-nos a testar a nossa lógica de negócios sem se preocupar o que os acesso a dados está fazendo. O padrão repositório permite trocarmos a classe repositório e acessar outra fonte de dados sem quase nenhuma alteração na camada de negócios.
  2. Abstração - Usando padrão nós criamos uma abstração da nossa funcionalidade de acesso a dados. Essa abstração pode ajudar-nos quando desejamos mudar a implementação de acesso a dados em afetar o código da nossa camada de negócios.
  3. Injeção de Dependência - Usando o padrão podemos usar contâiners de Injeção de dependência para injetar objetos relevantes que desejamos usar em nosso código.

Resumindo: O padrão Repository é um padrão muito útil quando trabalhamos com acesso a dados usando uma arquitetura em camadas. Para aplicações muito pequenas você pode até achar um exagero usar o padrão mas não deixa de ser uma boa prática.

Aguarde em breve um novo artigo mostrando uma forma mais sofisticada de implementar o padrão Repository.

Pegue o projeto completo aqui: PadraoRepository.zip

Eu sei é apenas Design Patterns, mas eu gosto...

Referências:

José Carlos Macoratti