VB .NET - Usando padrões de projeto na prática - 2
Programar até que é fácil, já desenvolver software de qualidade é uma arte.
Continuando a primeira parte do artigo vamos prosseguir e identificar qual o próximo problema temos que resolver em nossa singela aplicação Windows Forms que inicialmente foi criada sem a preocupação em adotar boas práticas de programação.
Sem olharmos com mais atenção o código da nossa aplicação iremos perceber que ainda temos código cuja responsabilidade é acessar dados espalhado pela nossa aplicação, na camada de interface, incluindo ai comandos SQL e objetos ADO .NET. Isso não é recomendável.
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.
O padrão DAO - Data Access Object - faz exatamente isso. Seu objetivo é remover a alta dependência do modelo de acesso a dados da nossa aplicação, de forma que se no futuro resolvermos trocar o banco de dados ou adotar outra estratégia de persistência a alteração deverá ser feita apenas em um único lugar. Aliado a isso também temos que podemos ter equipes independentes trabalhando na camada de interface sem ter que conhecer comandos SQL ou ADO .NET.
Usaremos então o padrão Data Access Object - DAO para abstrair e encapsular todo o acesso a fonte de dados sendo que o padrão DAO gerencia a conexão com a fonte de dados para obter os dados armazenados.
Assim, na sua forma mais básica, o padrão DAO é responsável por operar o mecanismo de persistência em nome da aplicação executando as quatro operações básicas – Criar, Recuperar , Alterar, Apagar – conhecidas pela sigla CRUD : Create, Retrive, Update , Delete.
Então o nosso próximo passo será implementar o padrão de projeto DAO em nosso projeto removendo assim as instruções SQL e os objetos ADO .NET e suas referências para acesso a dados da camada de interface ou seja da aplicação Windows Forms.
Podemos criar uma nova classe em nosso projeto Persistencia que foi criado no artigo anterior para implementar o padrão DAO, mas, uma opção melhor é especificar o padrão DAO através de uma interface ao invés de uma classe concreta. Com isso facilitamos o trabalho de implementar novos processos de persistência e impedimos que sejam criadas referências a classes concretas diminuindo o acoplamento.
Uma interface é parecida com uma
classe abstrata; a diferença é que uma classe abstrata pode possuir
métodos que não estejam implementados e pode possuir métodos que estejam
implementados.
|
Para isso vamos criar a interface IClienteDAO no projeto Persistencia. Clique com o botão direito do mouse sobre o projeto Persistencia e selecione a opção Add -> New item;
A seguir selecione o template Interface e informe o nome IClienteDAO.vb e clique em Add;
Vamos definir na interface o código conforme abaixo:
Public Interface IClienteDAO(Of T) 'Sub Insert(ByVal Obj As T) 'Function Update(ByVal Obj As T) As Boolean 'Function Delete(ByVal Obj As T) As Boolean 'Function Find(ByVal id As ID) As T Function ExibirTodos() As List(Of T) Sub Gravar(ByVal obj As T) Function Consultar(ByVal nome As String) As DataTable End Interface |
Como nosso projeto Windows Forms é muito simples e até o momento possui somente as funcionalidades para Consultar e Incluir um cliente eu defini os métodos Gravar() que inclui um cliente e Consultar que consulta um cliente. O método ExibirTodos() que exibe todos os clientes nos vamos implementar na interface depois.
Obs: Os demais métodos que estão comentados foram colocados como exemplos pois são os mais comumente usados.
Observe que estamos trabalhando com Generics e que nossa interface é fortemente tipada (Of T).Estamos trabalhando com List(Of T) que representa uma lista fortemente tipada de objetos que podem ser acessados através de um índice. (Fornece os métodos Search, Sort e efetua a manipulação da lista. )
Dessa forma o método ExibirTodos retorna uma lista de um tipo e o método Gravar recebe um tipo. A que tipo estamos nos referindo ?
Para nossa aplicação trata-se do objeto do nosso domínio, ou seja, o Cliente. Dessa forma teremos que criar uma classe Cliente para representar o nosso objeto de domínio e que será o tipo usado na implementação da interface.
Clique com o botão direito sobre o projeto Persistencia e selecione o template class e informe o nome Cliente.vb e clique em Add;
A seguir vamos definir na classe Cliente 3 propriedades : Codigo, NomeCliente e idadeCliente;
Lembre-se que nossa tabela Clientes possui 3 campos : Id, nome e idade.
Public Class Cliente Private _id As Integer Private _nome As String Private _idade As Integer Public Property Codigo As Integer Get Return _id End Get Set(ByVal value As Integer) _id = value End Set End Property Public Property NomeCliente As String Get Return _nome End Get Set(ByVal value As String) _nome = value End Set End Property Public Property IdadeCliente() As Integer Get Return Me._idade End Get Set(ByVal value As Integer) If value > 100 Or value < 18 Then Throw New Exception("Idade Inválida") Else Me._idade = value End If End Set End Property End Class |
A classe Cliente apresenta somente 3 propriedades
:
Sendo que na propriedade
IdadeCliente temos uma restrição quando ao A propriedade somente aceita valores entre 18 e 100. A tentativa de atribuir um valor fora dessa faixa irá causar um exceção.
|
Agora que já temos definidos a interface IClienteDAO e a classe Cliente vamos implementar a interface definindo uma classe chamada ClienteDAO.
Abaixo temos o esquema de implementação do padrão DAO no nosso projeto:
Clique com o botão direito do mouse sobre o projeto Persistencia e selecione a opção Add -> New item;
A seguir selecione o template Interface e informe o nome ClienteDAO.vb e clique em Add;
O código da classe ClienteDAO.vb que é uma classe concreta que implementa a interface IClienteDAO é o seguinte:
1- Devemos usar os seguintes namespaces :
Imports
System.Data2- A definição da assinatura da classe deve conter a palavra Implements e o nome da interface a definição do tipo usado na implementação:
Public
Class ClienteDAO3- Ao teclar ENTER no final da definição da interface os métodos que devem ser implementados serão criados com suas assinaturas conforme abaixo:
Imports
System.Data Imports System.Data.SqlClient Public Class ClienteDAOImplements IClienteDAO(Of Cliente) Public Function Consultar(ByVal nome As String) As System.Data.DataTable Implements IClienteDAO(Of Cliente).Consultar End Function Public Function ExibirTodos() As System.Collections.Generic.List(Of Cliente) Implements IClienteDAO(Of Cliente).ExibirTodos End Function Public Sub Gravar(ByVal cliente As Cliente) Implements IClienteDAO(Of Cliente).Gravar End
Sub |
O código completo da classe concreta ClienteDAO é dado a seguir:
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 System.Collections.Generic.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
|
Além dos métodos Gravar, Consultar e ExibirTodos que foram definidos na interface e implementados temos o método GetInstance que retorna uma instância da classe ClienteDAO. Boa parte do código de implementação dos métodos foram retirados da camada de interface.
A instância é criada na declaração: Private Shared ReadOnly instancia As New ClienteDAO()
Como criamos a classe ClienteDAO implementando a interface IClienteDAO já temos o nosso padrão DAO que será o responsável pelo acesso e a persistência dos dados. Vamos agora usar o padrão cliente em nosso projeto Windows Forms.
A primeira providência será remover do projeto Windows Forms , os formulários do projeto qualquer referência aos objetos ADO .NET , instruções SQL , etc.
Em seguida vamos usar o padrão DAO criado no projeto Persistencia e para que o projeto Windows tenha acesso as classes criadas temos que incluir uma referência ao projeto Persistencia no projeto CadastroClientes;
Clique com o botão direito do mouse sobre o projeto CadastroClientes e selecione a opção Add Reference;
Em seguida na janela Add Reference selecione a aba Projects, selecione o projeto Persistencia e clique em OK;
Com isso podemos alterar o código do formulário frmConsultar.vb conforme vemos abaixo:
Imports Persistencia Public Class frmConsultar Private Sub btnConsultar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnConsultar.Click Try Dim cliente As DataTable = Persistencia.ClienteDAO.GetInstance.Consultar(txtNomeCliente.Text) gdvCliente.DataSource = cliente Catch ex As Exception MessageBox.Show("Erro : " & ex.Message) End Try End Sub End Class
|
Note que temos uma referência ao projeto Persistencia: Imports Persistencia
No código estamos obtendo uma referência da classe ClienteDAO e usando o método Consultar passando como parâmetro o nome informado no controle txtNomeCliente.text: Persistencia.ClienteDAO.GetInstance.Consultar(txtNomeCliente.Text)
Vamos alterar também o código do formulário frmIncluir.vb conforme a seguir:
Imports Persistencia Public Class frmIncluir Private Sub btnGravar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnGravar.Click Try Dim cliente As New Cliente cliente.NomeCliente = txtNome.Text cliente.idadeCliente = CInt(txtIdade.Text) Persistencia.ClienteDAO.GetInstance().Gravar(cliente) Catch ex As Exception MessageBox.Show("Erro" & ex.Message) End Try End Sub End Class |
Note que temos uma referência ao projeto Persistencia: Imports Persistencia
A seguir criamos uma instância da classe Cliente e atribuímos os valores informados nos controles TextBox ao objeto e depois obtemos uma instância da classe ClienteDAO e usamos o método Gravar passando o objeto atualizado.
Agora vamos incluir um novo formulário no projeto para exibir todos os clientes cadastrados através do método ExibirTodos que implementamos na classe ClienteDAO;
No menu Project selecione Add Windows Forms e informe o nome frmClientes.vb;
A seguir inclua um controle DataGridView (name=gdvClientes) no formulário e em através do DataGridVeiw Tasks clique no link : Dock in Parent Container;
Abaixo temos o leiaute do formulário frmClientes que exibirá todos os clientes no controle DataGridView:
O código do formulário é exibido abaixo:
Imports Persistencia Public Class frmClientes Private Sub frmClientes_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load Try Dim clientes As List(Of cliente) = Persistencia.ClienteDAO.GetInstance.ExibirTodos gdvClientes.DataSource = clientes Catch ex As Exception MessageBox.Show("Erro: " & ex.Message) End Try End Sub End Class |
Aqui temos novamente a referência ao projeto Persistencia: Imports Persistencia
Obtemos uma referência da classe ClienteDAO e usamos o método ExibirTodos;
Lembrando que o método retorna uma lista tipada de objetos Clientes que é exibida no DataGridView;
Para completar vamos incluir no formulário formulário frmMenu um link para abrir o formulário frmClientes;
Inclusão do
LinkLabel Exibir Clientes e no evento Click do LinkLabel temos o
código:
|
Já podemos executar o projeto e verificar se nossa implementação esta funcionando.
Abaixo temos o resultado da execução da opção Exibir Clientes:
Concluímos assim a implementação do padrão DAO - Data Access Object em nossa aplicação.
Aguarde mais artigos sobre a utilização de padrões de projetos.
Eu sei á penas Visual Basic e melhores práticas, mas eu gosto...
Simples, simples assim...
Referências: