.NET - Apresentando o padrão DAO - Data Access Object
Você conhece o padrão de projeto DAO - Data Access Object ? |
Se você trabalha com aplicações com acesso a dados talvez já tenha até usado o padrão em seu código sem saber; mas hoje você será apresentado formalmente ao padrão DAO.
O padrão DAO é um padrão de projeto que abstrai e encapsula os mecanismos de acesso a dados escondendo os detalhes da execução da origem dos dados.
Já deu para notar que esse padrão é muito usado em aplicações que utilizam banco de dados relacionais.
No princípio era o caos
Não é muito difícil encontrar na web exemplos de código na linguagem VB .NET ou C# que mostram como fazer o acesso a um banco de dados relacional e realizar as tão conhecidas operações CRUD (Create, Update e Delete).
O problema é que em grande parte dos exemplos que são apresentados geralmente o código esta embutido no formulário ou página da aplicação.
Tomemos como exemplo um formulário ou página de cadastro onde são realizadas as operações para incluir, alterar, atualizar e excluir registros de uma tabela de um banco de dados.
Geralmente esses exemplos trazem o código de acesso e persistência de dados no próprio formulário e de forma geral você terá espalhado pela interface da aplicação trechos de código como o abaixo que fazem o acesso aos dados :
..... Dim conexao As OleDbConnection Dim myCommand As OleDbCommand conexao = New OleDbConnection("PROVIDER=Microsoft.Jet.OLEDB.4.0;DATASource=c:\Teste.mdb" ) conexao.Open() comando = New OleDbCommand( "Insert INTO Teste ( Nome ) Values ( 'Macoratti' )", conexao ) comando.ExecuteNonQuery() conexao.Close() ........... |
A 'arquitetura' usada neste modelo pode ser vista na figura abaixo:
Mas essa abordagem fere um dos princípios básicos das boas práticas : a separação das responsabilidades.
As boas práticas recomendam que a camada de interface não deve conhecer particularidades de acesso a dados, e, que essa responsabilidade deve estar concentrada em uma camada separada e independente. Desta forma a camada de interface, aqui representada pela aplicação Windows Forms, não deveria ter código de acesso a dados e deveríamos criar uma outra camada contendo o código cuja responsabilidade seria realizar as tarefas pertinentes ao acesso a dados
Essa prática é adotada por ser mais rápida e intuitiva de ser feita mas traz grandes desvantagens como:
Para resolver este problema temos o padrão DAO que é um dos muitos padrões que podemos usar para desacoplar o código de acesso e persistência dos dados da lógica da aplicação. O objetivo do padrão é tornar o código mais organizado, fácil de manter e entender e de poder ser reutilizado em outras aplicações.
O padrão DAO - Data Access Object
Este padrão permite criar as classes de dados independentemente da fonte de dados ser um BD relacional, um arquivo texto, um arquivo XML, etc. Para isso, ele encapsula os mecanismos de acesso a dados e cria uma interface de cliente genérica para fazer o acesso aos dados permitindo que os mecanismos de acesso a dados sejam alterados independentemente do código que utiliza os dados.
Existem diversas implementações do padrão DAO mas em geral podemos relacionar algumas características desejáveis em uma implementação do padrão DAO:
- Todo o acesso aos
dados deve ser feita através das classes DAO de forma a se ter o
encapsulamento;
- Cada instância da DAO é responsável por um objeto de
domínio;
- O DAO deve ser responsável pelas operações CRUD no domínio;
- O DAO não deve ser responsável por transações , sessões ou
conexões que devem ser tratados fora do DAO;
Nas figura abaixo vemos o
diagrama de classe mostrando os relacionamentos para o padrão
DAO e o diagrama de sequência mostrando a interação entre os
participantes:
(fonte: http://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html)
|
Diagrama DAO
|
Na figura abaixo vemos o diagrama para uma implementação do padrão DAO:
A classe CustomerDAO
(DataAccessObject) é a classe concreta que implementa a
interface ICustomerDAO sendo responsável pelo acesso e
persistência dos dados do cliente; A classe Customer é a classe do domínio e representa um cliente; |
Exemplo de código VB .NET e C# para a interface IClienteDAO (DataAccessObject):
Vamos definir na interface o código conforme abaixo:
Public Interface IClienteDAO(Of T) Function ExibirTodos() As List(Of T) Sub Gravar(ByVal obj As T) Function Consultar(ByVal nome As String) As DataTable End Interface |
public interface IClienteDAO<T> { List<T> ExibirTodos( ); void Gravar(T obj); DataTable Consultar(string nome); } |
Exemplo de código para definição da classe Cliente (TransferObject)
Public
Class Cliente Private _id As Integer Private _nome As String Public Property Codigo As Integer Get |
public class Cliente |
A classe Cliente apresenta somente 2 propriedades :
Exemplo de código para a classe ClienteDAO que implementa a interface IClienteDAO:
Imports System.Data Imports System.Data.SqlClient Public Class ClienteDAO Implements IClienteDAO(Of Cliente) Private Shared ReadOnly instancia As New ClienteDAO() Sub New() End Sub Public Shared Function GetInstance() As ClienteDAO Return instancia End Function Public Function Consultar(ByVal nome As String) As DataTable Implements IClienteDAO(Of Cliente).Consultar Try Using con As SqlConnection = ConexaoBD.GetInstancia.GetConnection() Try con.Open() Dim sql As String = ("Select nome, idade from clientes where nome = '" & nome & "'") Dim cmd As SqlCommand = New SqlCommand(sql, con) Dim da As SqlDataAdapter = New SqlDataAdapter(cmd) Dim cliente As DataTable = New DataTable da.Fill(cliente) Return cliente Catch ex As SqlException Throw ex Finally con.Close() End Try End Using Catch ex As Exception Throw ex End Try End Function Public Sub Gravar(ByVal cliente As Cliente) Implements IClienteDAO(Of Cliente).Gravar Try Using con As SqlConnection = ConexaoBD.GetInstancia.GetConnection() Try con.Open() Dim cmd As SqlCommand = New SqlCommand() cmd.Connection = con cmd.CommandText = "INSERT INTO Clientes (nome, idade) values (@nome, @idade)" Dim parNome As SqlParameter = New SqlParameter("@nome", cliente.NomeCliente) Dim parIdade As SqlParameter = New SqlParameter("@idade", cliente.IdadeCliente) cmd.Parameters.Add(parNome) cmd.Parameters.Add(parIdade) cmd.ExecuteNonQuery() Catch ex As SqlException Throw ex Finally con.Close() End Try End Using Catch ex As Exception Throw ex End Try End Sub Public Function ExibirTodos() As List(Of Cliente) Implements IClienteDAO(Of Cliente).ExibirTodos Try Using con As SqlConnection = ConexaoBD.GetInstancia.GetConnection() Try con.Open() Dim sql As String = ("Select Id,nome, idade from clientes") Dim listaClientes As IList(Of Cliente) = New List(Of Cliente) Dim cmd As SqlCommand = New SqlCommand(sql, con) Dim dr As SqlDataReader = cmd.ExecuteReader While (dr.Read) Dim cliente As New Cliente cliente.Codigo = CLng(dr("Id")) cliente.NomeCliente = dr("nome") cliente.idadeCliente = CInt(dr("idade")) listaClientes.Add(cliente) End While Return listaClientes Catch ex As SqlException Throw ex Finally con.Close() End Try End Using Catch ex As Exception Throw ex End Try End Function End Class |
Linguagem Visual Basic .NET |
public class ClienteDAO : IClienteDAO<Cliente> |
LInguagem C# |
Lembrando que o padrão DAO não depende da linguagem de programação usada e pode ser implementado em qualquer linguagem, e que existem diversas implementações possíveis.
"E disse-lhes : Ide por todo o mundo, pregai o evangelho a toda a criatura. Quem crer e for batizado será salvo; mas quem não crer será condenado." Marcos 16:15-16
Referências: