VB - Criando uma aplicação em 3 camadas - II


Na primeira parte deste artigo - VB - Criando uma aplicação em 3 camadas - falei da estrutura do projeto e de suas partes principais , vamos continuar agora mostrando como criar as classes do projeto.

Irei mostrar como criar o código para as classes e da função usada no projeto:

Criando as Classes do projeto

Para criar uma classe no VB6 selecione no menu Project a opção Add Class Module e selecione New Class . A primeira classe da qual falarei será a classe responsável pela conexão com o banco de dados , a classe cConexao.

1-) O código da classe cConexao.cls, responsável pela conexão com a fonte de dados , é o seguinte :

Option Explicit

'Declara um objeto ADO connection para usar
Private ADOConnection As ADODB.Connection

Public Sub OpenDB()

   If ADOConnection.State = adStateClosed Then

       ADOConnection.ConnectionString = "Provider = Microsoft.jet.OLEDB.4.0;" & _
                                                     "Data Source = " & App.Path & "
\Database\Agenda.mdb;Persist Security Info=False;"
       ADOConnection.Open

   End If
End Sub

Public Sub CloseDB()
   If ADOConnection.State = adStateOpen Then
         ADOConnection.Close
   End If
End Sub

Public Function RetornaRs(ByVal strSQL As String) As ADODB.Recordset
    'Retorna o registro do banco de dados
    Dim ADORecordset As ADODB.Recordset

    Set ADORecordset = New ADODB.Recordset
    ADORecordset.Open strSQL, ADOConnection, adOpenForwardOnly, adLockReadOnly
    Set RetornaRs = ADORecordset
    Set ADORecordset = Nothing
End Function

Public Sub Update(ByVal strSQL As String)
     ADOConnection.Execute strSQL
End Sub

Private Sub Class_Initialize()
   'instancia o objeto Ado Connection
   Set ADOConnection = New ADODB.Connection
End Sub

Private Sub Class_Terminate()
    Set ADOConnection = Nothing
End Sub

A classe cConexão possui o seguintes métodos :
  • OpenDB() - Abre o banco de dados
  • CloseDB() - fecha o banco de dados
  • RetornaRs(strSQL) - retorna o recordset
  • Update() - atualiza o recordset
  • Initialize() - executado na instância
  • Terminate() - executado ao destruir a instância da classe.
A notação UML para a classe pode ser feita da seguinte forma :                                              
Simbolo UML       Significado da notação UML
- O campo é privado (private)
+ O campo é público (public)
# O campo é protegido (protected)

2-) O código da classe cDadosDB.cls , responsável pelo acesso aos dados , é o seguinte :

Option Explicit
Private mobjConexao As cConexao

Public Function preencheLista()
  Dim strSQL As String
  Dim vntLista As Variant
  Dim rsLista As ADODB.Recordset

 
 'Abre o banco de dados
  mobjConexao.OpenDB

  
'Obtem o SQL
   strSQL = "SELECT enderecoID, Nome +', '+Sobrenome" & _
                " FROM tblEnderecos"

    
'Retorna as propriedades do comando SQL do banco de dados
    Set rsLista = mobjConexao.RetornaRs(strSQL)

   
 'Verifica se a tabela esta vazia
    If rsLista.EOF = True And rsLista.BOF = True Then
         vntLista = Empty
    Else
        
'se a tabela nao esta vazia então obtem as linhas
       vntLista = rsLista.GetRows
    End If

  
 'libera o objeto
   Set rsLista = Nothing

  
 'fecha o banco de dados
   mobjConexao.CloseDB

  
'retorna
   preencheLista = vntLista
End Function

Public Function getEnderecoDetalhes(ByVal lngEnderecoID As Long) As Variant
   Dim strSQL As String
   Dim vntEnderecoDetalhes As Variant
   Dim rsEnderecoDetalhes As ADODB.Recordset

   Set rsEnderecoDetalhes = New ADODB.Recordset

   strSQL = "SELECT *" & _
                "FROM tblEnderecos " & _
                " WHERE enderecoID =" & lngEnderecoID

   mobjConexao.OpenDB

   Set rsEnderecoDetalhes = mobjConexao.RetornaRs(strSQL)

   If rsEnderecoDetalhes.EOF = True And rsEnderecoDetalhes.BOF = True Then
         vntEnderecoDetalhes = Empty
   Else
        vntEnderecoDetalhes = rsEnderecoDetalhes.GetRows
   End If

   getEnderecoDetalhes = vntEnderecoDetalhes
   Set rsEnderecoDetalhes = Nothing
   mobjConexao.CloseDB

End Function

Public Sub SalvarEndereco(ByVal vntEnderecosInfo As Variant)

   Dim strSQL As String
   Dim command As New ADODB.command

   '
Aqui estou usando um procedimento armazenado no banco de dados
   ' o vetor abaixo é um array de todas as informações que desejamos colocar no banco de dados
   ' Como todas as informações do formulário vem atraves das camadas e é colocada no array
   ' nos podemos abrir o banco de dados , abrir o procedimento armazenado e preencher o array


   If vntEnderecosInfo(0, 0) = 0 Then
      Dim a(0 To 6) As Variant
      a(0) = vntEnderecosInfo(1, 0)
      a(1) = vntEnderecosInfo(2, 0)
      a(2) = vntEnderecosInfo(3, 0)
      a(3) = vntEnderecosInfo(4, 0)
      a(4) = vntEnderecosInfo(5, 0)
      a(5) = vntEnderecosInfo(6, 0)
      a(6) = vntEnderecosInfo(7, 0)

     Cria uma conexao com o banco de dados
     command.ActiveConnection = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" _
                                             & App.Path & "\Database\Agenda.mdb;Persist Security Info=False;"

     command.CommandText = "salvaEndereco" 'encontra o procedimento armazenado
     command.Execute , a() 'executa o array no procedimento armazeando

   Else
'se não esta incluindo entao atualiza

      Dim b(0 To 7) As Variant
      b(0) = vntEnderecosInfo(1, 0)
      b(1) = vntEnderecosInfo(2, 0)
      b(2) = vntEnderecosInfo(3, 0)
      b(3) = vntEnderecosInfo(4, 0)
      b(4) = vntEnderecosInfo(5, 0)
      b(5) = vntEnderecosInfo(6, 0)
      b(6) = vntEnderecosInfo(7, 0)
      b(7) = vntEnderecosInfo(0, 0)

     'Cria a conexao e executa o procedimento armazenado
      command.ActiveConnection = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & App.Path & "\Database\Agenda.mdb;Persist Security                                                Info=False;"
      command.CommandText = "atualizaEndereco" 'encontra o procedimento armazenado
      command.Execute , b() 'Executa o procedimento armazeando
   End If
   Set command = Nothing
End Sub

Public Sub excluiEnderecos(ByVal lngEnderecoID As Long)
   Dim strSQL As String

   strSQL = "DELETE *" & _
               " FROM tblEnderecos" & _
               " WHERE enderecoID= " & lngEnderecoID

   mobjConexao.OpenDB
   mobjConexao.Update (strSQL)
   mobjConexao.CloseDB
End Sub

Private Sub Class_Initialize()
   Set mobjConexao = New cConexao
End Sub

Private Sub Class_Terminate()
   Set mobjConexao = Nothing
End Sub
A classe cDadosDB possui o seguintes métodos :
  • preencheLista() - preenche uma caixa de listagem
  • getEnderecoDetalhes() - Obtem detalhes do endereço
  • SalvarEndereco(info) - salva os endereços.
  • excluiEnderecos(enderecoID) - exclui endereço
  • Initialize() - executado na instância da classe
  • Terminate() - executado ao destruir a instância da classe.
A notação UML para a classe pode ser feita da seguinte forma :                                              
Simbolo UML       Significado da notação UML
- O campo é privado (private)
+ O campo é público (public)
# O campo é protegido

3-) O código da classe cNegócios.cls , que define os atributos e propriedades dos clientes , é o seguinte :

Option Explicit

Private mobjDadosDB As cDadosDB

Private mstrNome As String
Private mstrSobrenome As String
Private mstrEndereco As String
Private mstrEstado As String
Private mstrPais As String
Private mstrCep As String
Private mstrTelefone As String
Private mlngEnderecoID As Long

Public Function preencheLista() As Variant

Dim vntList As Variant

' estamos conectando com a camada DadosDB e executando um sql para obter itens
vntList = mobjDadosDB.preencheLista

''Para passar as informações atraves da camadas precisamos empacotar tudo senao nao passa pela rede
preencheLista = vntList

End Function

Public Sub getEnderecoDetalhes(ByVal lngEnderecoID As Long)
Dim vntEnderecoDetalhes As Variant

' Executa o comando SQL pra encontrar os dados na base de dados
vntEnderecoDetalhes = mobjDadosDB.getEnderecoDetalhes(lngEnderecoID)

' aqui usamos um array para trazer os dados atraves da camada
lngEnderecoID = vntEnderecoDetalhes(0, 0)
mstrNome = vntEnderecoDetalhes(1, 0) & ""
mstrSobrenome = vntEnderecoDetalhes(2, 0) & ""
mstrEndereco = vntEnderecoDetalhes(3, 0) & ""
mstrCep = vntEnderecoDetalhes(4, 0) & ""
mstrEstado = vntEnderecoDetalhes(5, 0) & ""
mstrPais = vntEnderecoDetalhes(6, 0) & ""
mstrTelefone = vntEnderecoDetalhes(7, 0) & ""

End Sub

Public Sub SalvarEndereco()
'empacota as propriedades em um array e envia o array

Dim vntEnderecoInfo(7, 0) As Variant
vntEnderecoInfo(0, 0) = mlngEnderecoID
vntEnderecoInfo(1, 0) = mstrNome
vntEnderecoInfo(2, 0) = mstrSobrenome
vntEnderecoInfo(3, 0) = mstrEndereco
vntEnderecoInfo(4, 0) = mstrCep
vntEnderecoInfo(5, 0) = mstrEstado
vntEnderecoInfo(6, 0) = mstrPais
vntEnderecoInfo(7, 0) = mstrTelefone
mobjDadosDB.SalvarEndereco (vntEnderecoInfo)

End Sub

Public Sub excluirEndereco(ByVal mlngEnderecoID As Long)

mobjDadosDB.excluiEnderecos (mlngEnderecoID)

End Sub

'let permite atribuir valores
'get obtem valores

Public Property Let Nome(ByVal NewNome As String)
    mstrNome = NewNome
End Property

Public Property Get Nome() As String
   Nome = mstrNome
End Property

Public Property Let Sobrenome(ByVal NewSobrenome As String)
   mstrSobrenome = NewSobrenome
End Property

Public Property Get Sobrenome() As String
    Sobrenome = mstrSobrenome
End Property

Public Property Let Endereco(ByVal NewEndereco As String)
    mstrEndereco = NewEndereco
End Property

Public Property Get Endereco() As String
   Endereco = mstrEndereco
End Property

Public Property Let Cep(ByVal NewCep As String)
    mstrCep = NewCep
End Property

Public Property Get Cep() As String
  Cep = mstrCep
End Property

Public Property Let Estado(ByVal NewEstado As String)
   mstrEstado = NewEstado
End Property

Public Property Get Estado() As String
  Estado = mstrEstado
End Property

Public Property Let Pais(ByVal NewPais As String)
   mstrPais = NewPais
End Property

Public Property Get Pais() As String
   Pais = mstrPais
End Property

Public Property Let Telefone(ByVal NewTelefone As String)
  mstrTelefone = NewTelefone
End Property

Public Property Get Telefone() As String
   Telefone = mstrTelefone
End Property

Public Property Let EnderecoID(ByVal NewEnderecoID As Long)
   mlngEnderecoID = NewEnderecoID
End Property

Public Property Get EnderecoID() As Long
   EnderecoID = mlngEnderecoID
End Property

Private Sub Class_Initialize()
'incia a conexao coma proxima camada
  Set mobjDadosDB = New cDadosDB
End Sub

Private Sub Class_Terminate()
   Set mobjDadosDB = Nothing
End Sub

Além destas classes temos o arquivo Function.bas onde temos as funções usadas no projeto. Seu código é :

Option Explicit

Public Sub preencheEstado()
  'preenche a combobox com os estados
   Dim iFreeFile As Integer
   Dim strLine As String

   iFreeFile = FreeFile

   Open App.Path & "\Lista\Estados.txt" For Input As iFreeFile

   While Not EOF(iFreeFile)
       Line Input #iFreeFile, strLine
       frm3Camadas.cboEstado.AddItem "" & strLine & ""
   Wend
   Close iFreeFile
End Sub

Public Sub preenchePais()

   'preenche a combobox com os paises

   Dim iFreeFile As Integer
   Dim strLine As String

   iFreeFile = FreeFile
      Open App.Path & "\Lista\Paises.txt" For Input As iFreeFile
 
      While Not EOF(iFreeFile)
          Line Input #iFreeFile, strLine
          frm3Camadas.cboPais.AddItem "" & strLine & ""
      Wend

     Close iFreeFile
End Sub

Public Sub desabilitaCampos()
   Dim ctrl As Control

   For Each ctrl In frm3Camadas
       If TypeOf ctrl Is TextBox Then
          ctrl.Enabled = False
       End If
   Next

   For Each ctrl In frm3Camadas
       If TypeOf ctrl Is ComboBox Then
           ctrl.Enabled = False
      End If
   Next
End Sub

Public Sub habilitaCampos()
   Dim ctrl As Control

   For Each ctrl In frm3Camadas
      If TypeOf ctrl Is TextBox Then
         ctrl.Enabled = True
     End If
   Next

   For Each ctrl In frm3Camadas
      If TypeOf ctrl Is ComboBox Then
         ctrl.Enabled = True
      End If
   Next
End Sub

Public Function limpaCampos()
   Dim ctrl As Control

   For Each ctrl In frm3Camadas
      If TypeOf ctrl Is TextBox Then
         ctrl.Text = ""
      End If
   Next

   For Each ctrl In frm3Camadas
     If TypeOf ctrl Is ComboBox Then
       ctrl.Text = ""
     End If
   Next
End Function

Public Function desabilitaBotoes()
    frm3Camadas.cmdSalvar.Enabled = False
    frm3Camadas.cmdCancelar.Enabled = False
    frm3Camadas.cmdIncluir.Enabled = True
    frm3Camadas.cmdEditar.Enabled = True
    frm3Camadas.cmdExcluir.Enabled = True
End Function

Public Function habilitaBotoes()
   frm3Camadas.cmdSalvar.Enabled = True
   frm3Camadas.cmdCancelar.Enabled = True
   frm3Camadas.cmdIncluir.Enabled = False
   frm3Camadas.cmdEditar.Enabled = False
   frm3Camadas.cmdExcluir.Enabled = False
End Function

As rotinas preenchePais e preencheEstados utilizam o acesso de arquivos do
Visual Basic para preencher as combobox com os nomes dos estados e dos paises.

Os nomes dos paises estão no arquivo texto - Paises.txt

Os nomes dos estados estão no arquivo texto - Estados.txt

Como não teremos que dar manutenção nestas tabelas (creio que não é todo o dia
que se criam paises e estados) escolhemos esta metodologia por ser menos
onerosa para a aplicação.
Neste caso não se justifica criar e manter um banco de dados

Para habilitar , desabilitar e limpar campos estou percorrendo em um
laço For/Next a coleção de controles no formulário e verificando se o tipo de
controle é um TextBox ou ComboBox.

No código abaixo estou mostrando a sintaxe geral que pode ser usada:

 Dim ctrl As Control

   For Each ctrl In
formulário
      If TypeOf ctrl Is
controle Then         
        
'faz algo
      End If
   Next


Na terceira e última parte parte do artigo irei juntar todas as partes e mostrar o restante do código da camada de apresentação e testar a aplicação.

Acompanhe aqui : VB - Criando uma aplicação em 3 camadas III


José Carlos Macoratti