VB .NET - Usando padrões de projeto na prática
Programar até que é fácil, já desenvolver software de qualidade é uma arte. |
Neste artigo eu procuro mostrar como usar os padrões de projeto na prática em uma aplicação Windows Forms. Vale lembrar que padrões de projeto não pertencem a uma tecnologia ou a uma empresa; os padrões de projeto são soluções para problemas que alguém um dia teve e resolveu aplicando um modelo que foi documentado e que você pode adaptar integralmente ou de acordo com necessidade de sua solução.
Além dos padrões de projetos documentados e conhecidos (Padrões Gof) existem os padrões comuns que são inerentes ao conhecimento humano e que são usados intuitivamente para resolver problemas do dia a dia.
Os padrões de projetos não são difíceis de entender mas usá-los com sabedoria e bom senso na prática é uma questão de experiência.
Neste artigo eu procuro abordar de forma natural como reconhecer e saber como aplicar o padrão de projeto adequado a situação problema.
Para começar vamos criar uma aplicação Windows Forms com acesso a dados, que usa ADO .NET via código, onde teremos um banco de dados SQL Server chamado Cadastro.mdf e uma tabela Clientes.
A aplicação Windows Forms deverá realizar as operações de incluir e consultar dados da tabela Clientes.
A estrutura da tabela Clientes é a seguinte : Id, Nome, Idade onde Id é chave primária e do tipo Identity.
Irei criar a aplicação usando o VS 2010 Professsional (trial edition) onde irei criar uma aplicação Windows Forms padrão que usa o código embutido nos eventos dos controles do formulário para depois ir mostrando como podemos usar padrões de projeto para tornar a aplicação mais robusta, escalável e fácil de manter e testar.
Criando um Cadastro de Clientes sem usar padrões de projeto
Abra o VS 2010 e no menu File selecione New Project;
A seguir selecione Other Project Types -> Visual Studio Solutions -> Blank Solution;
Informe o nome UsandoPadroesProjetos e clique no botão OK;
A seguir , na janela Solution Explorer, clique com o botão direito do mouse sobre a solução criada e escolha : Add -> New Project;
Escolha a linguagem Visual Basic e selecione o template Windows Forms Application; Informe o nome CadastroClientes e clique em OK;
Vamos alterar o nome do formulário form1.vb criado por padrão para frmIncluir.vb e vamos incluir mais três formulários no projeto;
No menu Project selecione Add Windows Forms e informe o nome frmConsultar.vb;
Repita a operação e inclua o formulário frmMenu.vb;
A seguir vamos definir em cada um dos formulários: frmMenu, frmConsultar e frmIncluir, o seguinte leiaute :
- Dois controles
LinkLabel: - Consultar Clientes: No evento LInkClicked: My.Forms.frmConsultar.Show() - Incluir Clientes : Código do evento LinkClicked: My.Forms.frmIncluir.Show() |
|
|
- Um controle Label - Nome do
Cliente - Um controle TextBox - txtNomeCliente - Um Button - btnConsultar - Um DataGridView - gdvCliente |
|
Dois controles Label - Nome do
Cliente e Idade do Cliente - Um controle
TextBox - txtNome - Um Button - btnGravar
|
Vamos agora definir o código que estarão nos eventos dos controles:
1- Formulário Consultar Clientes:
No evento Click do botão Consultar inclua o código a seguir:
Private
Sub
btnConsultar_Click(ByVal
sender As
System.Object,
ByVal
e As
System.EventArgs)
Handles
btnConsultar.Click
Dim strsql = "Data Source=MAC-PC\SQLEXPRESS;Initial Catalog=Cadastro;Integrated Security=True" Using con As New SqlConnection(strsql) con.Open() Dim sql As String = ("Select nome, idade from clientes where nome = '" & txtNomeCliente.Text & "'") Dim cmd As SqlCommand = New SqlCommand(sql, con) Dim da As SqlDataAdapter = New SqlDataAdapter(cmd) Dim cliente As DataTable = New DataTable da.Fill(cliente) gdvCliente.DataSource = cliente con.Close() End Using End Sub |
2- Formulário Incluir Clientes:
No evento Click do botão Gravar inclua o código a seguir:
Private Sub btnGravar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnGravar.Click Dim strsql = "Data Source=MAC-PC\SQLEXPRESS;Initial Catalog=Cadastro;Integrated Security=True" Using con As New SqlConnection(strsql) 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", txtNome.Text) Dim parIdade As SqlParameter = New SqlParameter("@idade", CInt(txtIdade.Text)) cmd.Parameters.Add(parNome) cmd.Parameters.Add(parIdade) cmd.ExecuteNonQuery() con.Close() End Using End Sub |
Concluímos dessa forma nossa aplicação Windows Forms onde a partir do formulário frmMenu podemos chamar o formulário de consulta e do inclusão.Uma aplicação muito simples na verdade, mas que já serve para nosso propósito.
Antes de continuar eu quero alertar que ninguém aplica padrões de projeto nessa sistemática que estamos usando, ou seja, primeiro desenvolve uma solução e depois procura identificar qual padrão pode ser aplicado a ela. Usar padrões de projeto é como andar de bicicleta ou dirigir um carro, depois que você incorporou o conceito e teve um tempo de experiência você passa usá-los naturalmente.
Aplicando padrões de projeto
Mesmo sendo muito simples e tendo pouco código podemos identificar na nossa aplicação que o código para consultar e para incluir usam a mesma string de conexão, ou seja, ela esta esparramada pela aplicação e, se houver uma alteração nessa string de conexão, teremos que alterar o código dos dois formulários. Imagine se a aplicação tivesse uns 20 formulários usando essa mesma string de conexão ????
Quem nos poderá ajudar a resolver este problema ??
Aqui o primeiro padrão entra em cena, o padrão Singleton que é classificado como um padrão Criacional pois trata da criação de objetos.
Diagrama de classes simplificado para o padrão Singleton |
Eu já tratei desse padrão no artigo: O padrão Singleton portanto não vou entrar em detalhes.
Em resumo: O padrão Singleton faz com que uma classe só possa ter uma instância com um ponto global de acesso a ela.
Como vamos implementar o padrão Singleton em nosso projeto ?
Poderíamos fazer isso de diversas formas mas em nosso exemplo eu vou criar um novo projeto chamado Persistencia e incluí-lo na nossa solução e nesse projeto irei criar uma classe que implementa o padrão SIngleton.
No menu File clique em Add e a seguir em New Project;
A seguir selecione o template Class Library, informe o nome Persistencia e clique em Ok;
Terminada esta etapa teremos uma solução chamada UsandoPadroesProjetos com dois projetos: CadastroClientes e Persistencia;
A seguir altere o nome da classe Class1.vb para ConexaoBD.vb e inclua o seguinte código na classe:
Imports System.Data Imports System.Data.SqlClient Public Class ConexaoBD #Region "Métodos" ''' <summary> ''' O objeto intancia representa uma instância única da classe ConexaoBD; ''' *private = indica que o objeto só poderá ser acessado dentro da classe de origem, ''' *shared = define o atributo instancia como um objeto da classe, e, não da instância da classe ''' *readonly = implica que seu valor só poderá ser alterado na sua declaração ou dentro de um método construtor. ''' </summary> Private Shared ReadOnly instancia As New ConexaoBD() ''' <summary> ''' Restringimos o construtor padrão com o modificador private, o que implica ''' que apenas a própria classe pode se instanciar, ou seja, não pode ser ''' instanciada diretamente. ''' </summary> Private Sub New() End Sub ''' <summary> ''' Método estático que retorna a única instância da classe. ''' Só por este método as outras classes do sistema poderão utilizar ''' a instância de ConexaoBD. ''' </summary> ''' <returns>Instância única da classe</returns> Public Shared Function GetInstancia() As ConexaoBD Return instancia End Function ''' <summary> ''' Retorna uma conexão com o banco de dados. ''' </summary> ''' <returns>objeto de conexão com o banco de dados.</returns> Public Function GetConnection() As SqlConnection ' Obtem a string de conexão Dim strConexao As String = "Data Source=MAC-PC\SQLEXPRESS;Initial Catalog=Cadastro;Integrated Security=True" ' Retorna uma conexão. Return New SqlConnection(strConexao) End Function #End Region End Class |
Com esta classe resolvemos o problema da string de conexão esparramada pelo código agora somente esta classe conhece a string de conexão e retorna uma instância da conexão com o banco de dados. Qualquer mudança nesse quesito bastará alterar esta classe.
Agora temos que remover a string de conexão do código dos formulários e alterar a forma como a conexão com o banco de dados é obtida.
Antes temos que fazer uma referência no projeto CadastroClientes a projeto Persistencia, para isso clique com o botão direito do mouse sobre o projeto CadastroClientes e selecione a opção Add Reference;
Em seguida abra a guia Projects e selecione o projeto Persistencia e clique em OK;
Agora no vamos alterar os formulários frmIncluir.vb e frmConsultar.vb conforme abaixo:
1- Novo código do formulário frmConsultar.vb:
Imports System.Data Imports System.Data.SqlClient Imports Persistencia Public Class frmConsultar Private Sub btnConsultar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnConsultar.Click Try Using con As SqlConnection = ConexaoBD.GetInstancia.GetConnection() Try con.Open() Dim sql As String = ("Select nome, idade from clientes where nome = '" & txtNomeCliente.Text & "'") Dim cmd As SqlCommand = New SqlCommand(sql, con) Dim da As SqlDataAdapter = New SqlDataAdapter(cmd) Dim cliente As DataTable = New DataTable da.Fill(cliente) gdvCliente.DataSource = cliente Catch ex As SqlException Throw ex Finally con.Close() End Try End Using Catch ex As Exception Throw ex End Try End Sub End Class |
2- Novo código do formulário frmIncluir.vb:
Imports System.Data Imports System.Data.SqlClient Imports Persistencia Public Class frmIncluir Private Sub btnGravar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnGravar.Click 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", txtNome.Text) Dim parIdade As SqlParameter = New SqlParameter("@idade", CInt(txtIdade.Text)) 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 End Class |
Desta forma acabamos de aplicar o primeiro padrão de projeto a nossa aplicação. Na próxima parte estaremos aplicando mais padrões de projeto de forma a tornar a aplicação mais robusta.
Aguarde continuação em : VB .NET - Usando padrões de projeto na prática - 2
Eu sei á penas Visual Basic e melhores práticas, mas eu gosto...
Simples, simples assim...
Referências: