Desenvolvendo uma aplicação Multicamadas em Visual Basic .NET – Parte 3 Final.

Término do exemplo de uma aplicação para um Disk-Pizza. Objetivo explorar o conceito de programação em multicamadas em Visual Basic 2005.

Este é o terceiro e último artigo da série os quais mostram, através de um exemplo prático e simples, uma abordagem do desenvolvimento de software em camadas no Visual Basic 2005.

No primeiro artigo foi apresentado um cenário para o desenvolvimento da aplicação e criamos o Banco de Dados com as respectivas tabelas e o mapeamento Entidade Relacionamento. Chamamos o conjunto de dados dentro de um DataSet, o que denominamos nossa camada de dados.

No segundo artigo foram apresentadas as classes da camada “2 – Camada Intermediaria” que representam a lógica de negócio (regras de negócio) e a lógica do controlador (classe que faz a interface com os dados). Sua função é assegurar a confiabilidade dos dados antes que o servidor de Banco de Dados atualize ou exiba as informações ao cliente do aplicativo (camada de apresentação).

A Camada intermediária isola as regras, da interface do sistema. Essa camada funciona como o próprio nome diz serve como intermediária entre os dados da camada “1 – Camada de Dados” e da camada “3 – Camada de Apresentação” cliente do aplicativo.

Ainda no segundo artigo foi iniciado a criação da última camada “3 – Camada de Apresentação”. Onde foram criados os formulários de clientes e de pesquisa genérica.

Nesse terceiro e último iremos continuar a definir as classes de negócio e criaremos na camada de apresentação a interface para cadastro dos pedidos de pizza.

Com o projeto devpizza aberto, abra a pasta “2 – Camada Intermediaria”. Subpasta “2.2 – Logica de Negocio”

Dê um duplo clique sobre a classe clnPedidos.vb

Digite o seguinte código:

Imports System.Data Imports System.Data.SqlClient Imports System.Text Public Class clnPedidos Campos membros Private mIdPedido As Integer Private mData As Date Private mHora As DateTime Private mIdCliente As Integer Private mValorTotal As Decimal atributos Public Property IdPedido() As Integer Get Return mIdPedido End Get Set(ByVal value As Integer) mIdPedido = value End Set End Property Public Property Data() As String Get Return mData End Get Set(ByVal value As String) mData = value End Set End Property Public Property Hora() As String Get Return mHora End Get Set(ByVal value As String) mHora = value End Set End Property Public Property IdCliente() As String Get Return mIdCliente End Get Set(ByVal value As String) mIdCliente = value End Set End Property Public Property ValorTotal() As String Get Return mValorTotal End Get Set(ByVal value As String) mValorTotal = value End Set End Property

Métodos da Classe Pedidos

Public Sub Buscar() Dim cSql As String cSql = "Select * From Pedidos Where IdPedido=" & mIdPedido Dim ds As DataSet Dim DtPizza As New ClsDados() ds = DtPizza.RetornarDataSet(cSql) If ds.Tables(0).Rows.Count > 0 Then IdPedido = ds.Tables(0).Rows(0).Item(0) Data = ds.Tables(0).Rows(0).Item(1) Hora = ds.Tables(0).Rows(0).Item(2) IdCliente = ds.Tables(0).Rows(0).Item(3) ValorTotal = ds.Tables(0).Rows(0).Item(4) End If End Sub Public Function BuscarId() As Integer Dim cSql As String cSql = "Select Top 1 (IdPedido) From Pedidos order by IdPedido desc" Dim IdBuscado As Integer Dim DtPizza As New ClsDados() IdBuscado = DtPizza.RetornarIdNumerico(cSql) Return IdBuscado End Function Public Function BuscarTotal() As Decimal Dim cSql As String cSql = "Select Sum(Quantidade * ValorProduto)as Total From PedidosItens where IdPedido=" &am ; mIdPedido Dim ValorBuscado As Integer Dim DtPizza As New ClsDados() ValorBuscado = DtPizza.RetornarValorTotal(cSql) Return ValorBuscado End Function Public Sub Editar() Dim sValorTotal As String = mValorTotal.ToString sValorTotal = Replace(sValorTotal, ",", ".") Dim strQuery As New StringBuilder strQuery.Append("Update Pedidos ") strQuery.Append("set ") strQuery.Append("IdPedido=") strQuery.Append(mIdPedido) strQuery.Append(", Data=") strQuery.Append(Format(mData, "MM/dd/yyyy")) strQuery.Append(", Hora=") strQuery.Append(mHora.ToShortTimeString) strQuery.Append(", IdCliente=") strQuery.Append(mIdCliente) strQuery.Append(", ValorTotal=") strQuery.Append(sValorTotal) strQuery.Append(" where IdPedido=") strQuery.Append(mIdPedido & ";") Dim BancoPizza As New ClsDados() BancoPizza.ExecutarComando(strQuery.ToString) End Sub Public Sub Excluir() Dim strQuery As New StringBuilder strQuery.Append("Delete From Pedidos ") strQuery.Append("where IdPedido=") strQuery.Append(mIdPedido) Dim BancoPizza As New ClsDados() BancoPizza.ExecutarComando(strQuery.ToString) End Sub Public Sub Gravar() Dim sValorTotal As String = mValorTotal.ToString sValorTotal = Replace(sValorTotal, ",", ".") Dim strQuery As New StringBuilder strQuery.Append("Insert into Pedidos ") strQuery.Append(" (") strQuery.Append("IdPedido,") strQuery.Append("Data,") strQuery.Append("Hora,") strQuery.Append("IdCliente,") strQuery.Append("ValorTotal") strQuery.Append(") ") strQuery.Append(" VALUES (") strQuery.Append(mIdPedido) strQuery.Append(", " & Format(mData, "MM/dd/yyyy") & "") strQuery.Append(", " & mHora.ToShortTimeString & "") strQuery.Append(", " & mIdCliente) strQuery.Append(", " & sValorTotal) strQuery.Append(");") Dim BancoPizza As New ClsDados() BancoPizza.ExecutarComando(strQuery.ToString) End Sub Public Function Pesquisar(ByVal Campo As String, _ ByVal Parametro As String, ByVal Valor As String, _ ByVal tipo As String) As DataSet Dim strQuery As New StringBuilder strQuery.Append("Select * From PEdidos ") strQuery.Append("where " & Campo & " ") strQuery.Append(Parametro & " ") strQuery.Append(Valor) Dim a As String = strQuery.ToString() Dim ds As DataSet Dim BancoPizza As New ClsDados() ds = BancoPizza.RetornarDataSet(strQuery.ToString) Return ds End Function End Class

Ainda na Camada 2. Dê um duplo clique sobre a classe clnPedidosItens e digite o código abaixo:

Imports System.Data Imports System.Data.SqlClient Imports System.Text Public Class clnPedidosItens Campos membros Private mIdPedido As Integer Private mIdProduto As Integer Private mQuantidade As Integer Private mValorProduto As Decimal atributos Public Property IdPedido() As Integer Get Return mIdPedido End Get Set(ByVal value As Integer) mIdPedido = value End Set End Property Public Property IdProduto() As String Get Return mIdProduto End Get Set(ByVal value As String) mIdProduto = value End Set End Property Public Property Quantidade() As String Get Return mQuantidade End Get Set(ByVal value As String) mQuantidade = value End Set End Property Public Property ValorProduto() As String Get Return mValorProduto End Get Set(ByVal value As String) mValorProduto = value End Set End Property

Métodos da Classe Pedidos Detalhes.

Public Sub Buscar() Dim cSql As String cSql = "Select * From PedidosItens Where IdPedido=" & mIdPedido Dim ds As DataSet Dim DtPizza As New ClsDados() ds = DtPizza.RetornarDataSet(cSql) If ds.Tables(0).Rows.Count > 0 Then IdPedido = ds.Tables(0).Rows(0).Item(0) IdProduto = ds.Tables(0).Rows(0).Item(1) Quantidade = ds.Tables(0).Rows(0).Item(2) ValorProduto = ds.Tables(0).Rows(0).Item(3) End If End Sub Public Function BuscarId() As Integer Dim cSql As String cSql = "Select Top 1 (IdPedido) From PedidosItens order by IdPedido desc" Dim IdBuscado As Integer Dim DtPizza As New ClsDados() IdBuscado = DtPizza.RetornarIdNumerico(cSql) Return IdBuscado End Function Public Sub Editar() tratando o campo mValorProduto Dim sValorProduto As String = mValorProduto.ToString Dim strQuery As New StringBuilder strQuery.Append("Update PedidosItens ") strQuery.Append("set ") strQuery.Append("IdPedido=") strQuery.Append(mIdPedido) strQuery.Append(", IdProduto=") strQuery.Append(mIdProduto) strQuery.Append(", Quantidade=") strQuery.Append(mQuantidade) strQuery.Append(", ValorProduto=") strQuery.Append(sValorProduto) strQuery.Append(" where IdPedido=") strQuery.Append(mIdPedido & ";") Dim BancoPizza As New ClsDados() BancoPizza.ExecutarComando(strQuery.ToString) End Sub Public Sub Excluir() Dim strQuery As New StringBuilder strQuery.Append("Delete From PedidosItens ") strQuery.Append("where IdPedido=") strQuery.Append(mIdPedido) Dim BancoPizza As New ClsDados() BancoPizza.ExecutarComando(strQuery.ToString) End Sub Public Sub Gravar() tratando o campo mValorProduto Dim sValorProduto As String = mValorProduto.ToString sValorProduto = sValorProduto.Replace(",", ".") Dim strQuery As New StringBuilder strQuery.Append("Insert into PedidosItens ") strQuery.Append(" (") strQuery.Append("IdPedido,") strQuery.Append("IdProduto,") strQuery.Append("Quantidade,") strQuery.Append("ValorProduto") strQuery.Append(") ") strQuery.Append(" VALUES (") strQuery.Append(mIdPedido) strQuery.Append("," & mIdProduto) strQuery.Append("," & mQuantidade) strQuery.Append("," & sValorProduto) strQuery.Append(");") Dim BancoPizza As New ClsDados() BancoPizza.ExecutarComando(strQuery.ToString) End Sub Public Function Pesquisar(ByVal Campo As String, _ ByVal Parametro As String, ByVal Valor As String, _ ByVal tipo As String) As DataSet Dim strQuery As New StringBuilder strQuery.Append("Select * From PedidosItens ") strQuery.Append("where " & Campo & " ") strQuery.Append(Parametro & " ") strQuery.Append(Valor) Dim a As String = strQuery.ToString() Dim ds As DataSet Dim BancoPizza As New ClsDados() ds = BancoPizza.RetornarDataSet(strQuery.ToString) Return ds End Function End Class

Agora na Camada 3. Adicione um novo formulário a esse projeto e dê o nome de FrmPedidos, crie o formulário com a seguinte interface.

Altere a propriedade name dos botões lançar pedido, adicionar e fechar respectivamente para cmdLancar, cmdAdicionar e cmdFechar.

Altere a propriedade name do DataGridView para DgvItens.

Bom, nesse ponto vamos adicionar um novo formulário, que será o principal da aplicação, onde incluiremos um menu com as opções para abrir os formulários de clientes, produtos (que não implantamos, fica por sua conta) e Lançar os pedidos.

Na pasta “3 – Camada de Apresentacao” adicione um novo formulário, altere seu nome para FrmPrincipal.vb.

Monte a interface acrescentado o menustrip conforme abaixo:

Acrescente o código para chamar o formulário de Pedidos, clicando duas vezes sobre o menu pedidos. PedidosToolStripMenuItem.

Private Sub PedidosToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PedidosToolStripMenuItem.Click FrmPedidos.Show() End Sub

Clique com o botão direito do mouse sobre o nome do projeto e selecione properties. Altere o formulário de entrada para FrmPrincipal e o modo de encerramento da aplicação conforme abaixo:

Alterne para o formulário de pedidos FrmPedidos.vb e acrescente o código abaixo no evento Load do formulário.

Private Sub FrmPedidos_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load GroupBox1.Enabled = True GroupBox2.Enabled = False Dim BuscaIdPedido As New clnPedidos Dim id As Integer = BuscaIdPedido.BuscarId() Se a busca retornou zero é que não há pedidos entao alterei o id para um. Nesse momento já registro o pedido para não ocorrer problemas em um ambiente de rede ou seja, outro ponto adicionar um novo pedido antes de fechar o corrente (aconteceria erro de chave primária). If id = 0 Then id = 1 IdPedidoTextBox.Text = id DataTextBox.Text = Date.Today.ToShortDateString HoraTextBox.Text = Date.Now.ToShortTimeString IdPedidoTextBox.Enabled = False DataTextBox.Enabled = False HoraTextBox.Enabled = False Gravando Dim GravParcial As New clnPedidos GravParcial.IdPedido = IdPedidoTextBox.Text GravParcial.Data = DataTextBox.Text GravParcial.Hora = HoraTextBox.Text Gravar IdCliente e ValorTotal com Zero nesse momento Depois será feita a alteração GravParcial.IdCliente = 0 GravParcial.ValorTotal = 0 GravParcial.Gravar() IdClienteTextBox.Focus() End Sub

Acrescente o código abaixo para o evento TextChanged da caixa de texto IdClienteTextBox.

Private Sub IdClienteTextBox_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles IdClienteTextBox.TextChanged Dim Cliente As New clnClientes Cliente.IdCliente = Val(IdClienteTextBox.Text) Cliente.Buscar() If Cliente.NomeRazao <> Nothing Then NomeRazaoLabel.Text = Cliente.NomeRazao EnderecoLabel.Text = Cliente.Endereco TelefoneLabel.Text = Cliente.Telefone CidadeLabel.Text = Cliente.Cidade EstadoLabel.Text = Cliente.Estado Else NomeRazaoLabel.Text = Nothing EnderecoLabel.Text = Nothing TelefoneLabel.Text = Nothing CidadeLabel.Text = Nothing EstadoLabel.Text = Nothing End If End Sub

O Código acima é responsável por localizar o cliente e trazer os dados para os controle Labels. Caso não exista o cliente cadastrado será “limpo” os mesmo labels.

Agora é hora de registrar o pedido atualizando o dado do pedido acrescentando o código do cliente caso tenha sido encontrado, se não, emite uma mensagem de alerta para o usuário.

Acrescente o código abaixo para o evento Click do cmdLancar, botão lançamento.

Private Sub cmdLancar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdLancar.Click If NomeRazaoLabel.Text = Nothing Then MsgBox("Cliente não cadastrado, gentileza cadastrar", 16, "Aviso") Exit Sub End If Dim Atualiza As New clnPedidos Atualiza.IdPedido = IdPedidoTextBox.Text Atualiza.Data = DataTextBox.Text Atualiza.Hora = HoraTextBox.Text Atualiza.IdCliente = IdClienteTextBox.Text Atualiza.ValorTotal = 0 Atualiza.Editar() Bloqueia o GroupBox1 para evitar alterações Até o fechamento do pedido GroupBox1.Enabled = False GroupBox2.Enabled = True IdProdutoTextBox.Focus() End Sub

Nesse momento o GroupBox2 já está liberado e o foco do cursor deve aparecer na caixa de texto IdProdutoTextBox. Vamos colocar o código que responderá ao evento IdProdutoTextBox_TextChanged(). Seu funcionamento é idêntico ao IdClienteTextBox_TextChanged() visto anteriormente, é responsável por mostrar os dados do produto, como descrição e preço.

Código do IdProdutoTextBox_TextChanged().

Private Sub IdProdutoTextBox_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles IdProdutoTextBox.TextChanged Dim Produto As New clnProdutos Produto.IdProduto = Val(IdProdutoTextBox.Text) Produto.Buscar() If Produto.Descricao <> Nothing Then DescricaoLabel.Text = Produto.Descricao ValorProdutoTextBox.Text = Produto.Preco Else DescricaoLabel.Text = Nothing ValorProdutoTextBox.Text = Nothing End If End Sub

Quando o Campo Valor do Produto perder o foco, é calculado o valor total do item. Vamos adicionar o mesmo código sendo chamado a partir do GotFocus do botão Adicionar, ou seja, caso o usuário digite o valor e clique direto no botão adicionar, ele responderá ao evento (ganhar o foco) antes do evento clique, isso fará com que não ocorra erro no lançamento. Para isso vamos adicionar um procedimento público no escopo do formulário de pedidos chamado Calculo.

Dentro da classe FrmPedidos no final acrescente o sub procedimento abaixo para o cálculo citado.

Public Sub Calculo() Dim Qtd As Decimal If QuantidadeTextBox.Text = Nothing Then Qtd = 0 Else Qtd = QuantidadeTextBox.Text End If Dim Preco As Decimal If ValorProdutoTextBox.Text = Nothing Then Preco = 0 Else Preco = ValorProdutoTextBox.Text End If Dim Total As Decimal = Qtd * Preco TotalItemTextBox.Text = FormatCurrency(Total) End Sub

Código do evento ValorProdutoTextBox_LostFocus().

Private Sub ValorProdutoTextBox_LostFocus(ByVal sender As Object, ByVal e As System.EventArgs) Handles ValorProdutoTextBox.LostFocus Calculo() End Sub

Código repetido para evento CmdAdicionar_GotFocus().

Private Sub cmdAdicionar_GotFocus(ByVal sender As Object, ByVal e As System.EventArgs) Handles cmdAdicionar.GotFocus Calculo() End Sub

Agora abaixo o código que responde ao evento clique do botão adicionar. Comentado.

Private Sub cmdAdicionar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdAdicionar.Click Gravando os itens Dim GravaItem As New clnPedidosItens GravaItem.IdPedido = IdPedidoTextBox.Text GravaItem.IdProduto = IdProdutoTextBox.Text GravaItem.Quantidade = QuantidadeTextBox.Text GravaItem.ValorProduto = ValorProdutoTextBox.Text GravaItem.Gravar() limpando as caixas de Texto do GroupBox2 For Each ctl As Control In GroupBox2.Controls If TypeOf ctl Is TextBox Then ctl.Text = Nothing End If Next IdProdutoTextBox.Focus() Dim ds As New DataSet Dim Busca As New ClsDados Dim Csql As New StringBuilder Csql.Append("Select *,(Quantidade * ValorProduto)As Total From PedidosItens") Csql.Append(" where IdPedido=" & IdPedidoTextBox.Text) ds = Busca.RetornarDataSet(Csql.ToString) Me.DgvItens.AutoGenerateColumns = True Me.DgvItens.DataSource = ds.Tables(0) End Sub

No exemplo acima o objeto Csql.ToString armazena como conteúdo uma query Sql que “cria” um campo calculado chamado total que armazena o total do item, obtido através da multiplicação da quantidade pelo valor do produto. E O Objeto DgvItens(DataGridView) recebe o ds.Tables(0) que é o resultado da busca na tabela com o campo calculado.

Agora para finalizar, vamos ao último código, o do botão Fechar. Código do botão fechar

Private Sub cmdFechar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdFechar.Click Dim ValorTotal As New clnPedidos ValorTotal.IdPedido = IdPedidoTextBox.Text ValorTotalTextBox.Text = FormatCurrency(ValorTotal.BuscarTotal) Dim Atualiza As New clnPedidos Atualiza.IdPedido = IdPedidoTextBox.Text Atualiza.Data = DataTextBox.Text Atualiza.Hora = HoraTextBox.Text Atualiza.IdCliente = IdClienteTextBox.Text Atualiza.ValorTotal = ValorTotalTextBox.Text Atualiza.Editar() Bloqueia o GroupBox1 e GroupBox2 para evitar alterações GroupBox1.Enabled = False GroupBox2.Enabled = False IdProdutoTextBox.Focus() MsgBox("Pedido efetuado com sucesso", 64, "Aviso") MsgBox("Aqui você poderia criar um rotina para imprimir o pedido") Fecha o Formulário de Pedido Me.Close() End Sub

Nessa série de três artigos vimos, através de um exemplo prático e simples, uma abordagem do desenvolvimento de software em três camadas no Visual Basic 2005.

No primeiro artigo foi apresentado um cenário para o desenvolvimento da aplicação e criamos o Banco de Dados com as respectivas tabelas e o mapeamento Entidade Relacionamento

No segundo artigo foram apresentadas as classes da camada “2 – Camada Intermediaria” que representam a lógica de negócio (regras de negócio) e a lógica do controlador (classe que faz a interface com os dados). Vimos que a Camada intermediária, isola as regras, da interface do sistema. Essa camada funciona como o próprio nome diz, serve como intermediária entre os dados da camada “1 – Camada de Dados” e da camada “3 – Camada de Apresentação” cliente do aplicativo.

Nesse terceiro e último definimos as classes de negócio e criamos na camada de apresentação a interface para cadastro dos pedidos de pizza.

A biblioteca NHibernate baseada em .NET para persistir os objetos para bases de dados relacionais, não foi explorada nesse exemplo. O NHibernate é baseado em uma ferramenta de persistência de dados da linguagem Java, chamado Hibernate, o NHibernate tem a finalidade de persistir os objetos .NET em uma base de dados relacional subjacente. Essa camada estaria disposta entre a camada de dados e a nossa camada intermediária(lógica de controlador e lógica de negócio) em nossa aplicação. Essa seria a camada “Persistência de Dados”. O NHibernate gera o código SQL verificando se os tipos e valores são consistentes.

Taí um bom assunto para um artigo futuro, tenho notado que todos os novos conceitos tem sido amplamente difundidos com o uso do C#, denotando assim, ao meu ver uma tendência de migração gradativa para essa linguagem. Como existem milhares de programadores Visual Basic ao redor do mundo, não sei se isso é uma boa idéia. O que vocês acham?


Links Úteis

  • Curso de Xamarin: Primeiros passos: O Xamarin é uma plataforma para desenvolvimento de aplicações móveis dentro da plataforma .NET, utilizando o C#.
  • Curso de Lógica de Programação: Neste curso veremos uma introdução a algoritmos, utilizando como linguagem de apoio o Portugol. Para isso, abordaremos assuntos como descrição narrativa, fluxogramas e pseudocódigos, fundamentais para quem está iniciando na programação.
  • Curso de HTML5: Neste curso de HTML 5 veremos o que desenvolvimento da linguagem HTML (HyperText Markup Language) ficou parada na versão 4 desde 1999. Durante esse período, a W3C se focou em linguagens como XML (Extensible Markup Language) e SVG (Scalable Vector Graphics - gráficos vetoriais em navegadores).
  • Como aprender PHP: Neste Guia de Consulta você encontrará todo o conteúdo que precisa para aprender PHP, uma linguagem de programação amplamente utilizada para a construção de aplicações web.

Saiba mais sobre Visual Basic ;)

Artigos relacionados