.NET

24 jan, 2013

VB .NET – 7 passos para criar uma aplicação em 3 Camadas – Parte 03

Publicidade

Na segunda parte deste artigo iniciamos a definição das camadas da nossa solução iniciando com a camada DTO e a camada de acesso a dados. Continuando a nossa caminhada cujo objetivo é criar uma aplicação em camadas usando o VB .NET.

Iremos, agora, continuar a definição das camadas da nossa aplicação, desta vez abordando a camada de negócios – CamadaBLL – que é responsável pelas regras de negócio do nosso domínio e onde iremos efetuar as validações. O objetivo da camada de negócios é implementar a lógica da aplicação, expondo esta lógica para a camada de apresentação e outras aplicações, e também acessar a camada de acesso a dados.

Passo 6. Definindo as classes do nosso domínio na camada de negócio – CamadaBLL

Como já escrevi, nosso modelo é muito simples e estamos usando o padrão DAO para implementar as funcionalidades da nossa solução. Nada muito sofisticado, mas funcional, seguindo o padrão KISS – Keept Simple Stupid (é um princípio que defende que toda a complicação desnecessária deve ser evitada. Então se o jeito simples é o “certo”, por que complicamos? Por pura falta de competência e preguiça. “Simples” não é sinônimo de fácil).

Seguindo este padrão, vamos criar as classes da camada de negócio – CamadaBLL -, onde para cada classe do nosso domínio teremos uma classe de negócio relacionada. Vamos definir as classes e nelas vamos definir os métodos que acessam a camada de acesso a dados. Eu não estou realizando nenhuma validação nesta camada para deixar o exemplo mais limpo e fácil de entender, mas qualquer validação de negócio deverá ser feita nesta camada.

1. Criando a classe ClasseBLL

Clique com o botão direito do mouse sobre o projeto CamadaBLL e selecione Add->Class. Depois selecione o template Class e informe o nome ClasseBLL.vb e clique no botão Add. A seguir, vamos definir o código abaixo nesta classe:

Imports CamadaDTO
Imports CamadaDAL
Public Class ClasseBLL
Public Function GetTodasClasses() As List(Of Classe)
Dim db As New ClasseDAL
Return db.GetClasses()
End Function
Public Function GetClassePorCodigo(ByVal _CodigoClasse As Integer) As Classe
Dim db As New ClasseDAL
Return db.GetClassePorId(_CodigoClasse)
End Function
Public Function Salvar(ByVal cls As Classe)
Dim db As New ClasseDAL
Return db.Salva(cls)
End Function
Public Function DeletarClasse(ByVal _CodigoClasse As Integer)
Dim db As New ClasseDAL
Return db.DeletaClasse(_CodigoClasse)
End Function
End Class

A classe ClasseBLL possui os métodos:

  • GetTodasClasses;
  • GetClassePorCodigo;
  • Salvar;
  • DeletarClasse.

Esta classe está apenas usando os métodos criados para acessar os métodos correspondentes na camada CamadaDAL.

2. Criando a classe AlunosBLL

Clique com o botão direito do mouse sobre o projeto CamadaBLL e selecione Add->Class. Selecione o template Class e informe o nome AlunosBLL.vb e clique no botão Add. A seguir, vamos definir o código abaixo nesta classe:

Imports CamadaDTO
Imports CamadaDAL
Public Class AlunosBLL
Public Function GetTodosAlunos() As List(Of Aluno)
Dim db As New AlunosDAL
Return db.GetAlunos
End Function
Public Function GetAlunosPorCodigo(ByVal _alunoId As Integer) As Aluno
Dim db As New AlunosDAL
Return db.GetAlunoPorId(_alunoId)
End Function
Public Function GetAlunosPorClasse(ByVal _classeId As Integer)
Dim db As New AlunosDAL
Return db.GetAlunosPorClasse(_classeId)
End Function
Public Function SalvaAluno(ByVal _aluno As Aluno)
Dim db As New AlunosDAL
Return db.SalvaAluno(_aluno)
End Function
Public Function DeletaAluno(ByVal _alunoId As Integer)
Dim db As New AlunosDAL
Return db.DeletaAlunoPorId(_alunoId)
End Function
End Class

A classe AlunosBLL possui os métodos:

  • GetTodosAlunos;
  • GetAlunosPorCodigo;
  • GetAlunosPorClasse;
  • SalvaAluno;
  • DeletaAluno.

Esta classe está apenas usando os métodos criados para acessar os métodos correspondentes na camada CamadaDAL.

As duas classes definidas nesta camada atuam da mesma forma criando uma instância da camada de acesso a dados e usando o método definido para realização da operação.

As validações de negócio devem ser realizadas nesta camada. Isso não está sendo feito neste exemplo pela simplicidade do projeto.

Passo 7. Definindo a camada de apresentação – CamadaWin

Vamos agora definir a camada de apresentação onde criaremos um projeto Windows Forms para permitir que o usuário gerencie as classes e os alunos realizando as seguintes operações:

  • Cadastrar Classe;
  • Alterar Classe;
  • Cadastrar Aluno;

Meu objetivo será mostrar que na camada de apresentação deveremos tratar apenas da apresentação e tratamento das informações, pois a lógica do negócio e a persistência dos dados estão em camadas separadas. Dessa forma, a camada de apresentação não deve saber nada sobre a lógica de negócios nem sobre a persistência de dados.

A camada de apresentação para atualizar as informações irá usar os serviços da camada de acesso aos dados via camada de negócios, realizando nesta as validações pertinentes.

No formulário form1.vb que foi criado por padrão vamos definir o leiaute conforme mostra a figura abaixo:

vbn_cam31Controles principais do formulário:

GroupBox – grpNovaClasse – Text = Classes

  • CboClasses;
  • txtNovaClasse;
  • btnNovaClasse;
  • btnSalvarClasse.

GroupBox – grpAlunos – Text = Alunos

  • dgvAlunos;
  • txtNovoAluno;
  • bntSair;
  • btnSalvarAluno.

ErrorProvider – ErrorProvider1

Vamos declarar a utilização dos namespaces:

Imports CamadaDTO
Imports CamadaBLL

Isso é necessário pois precisamos acessar os métodos da camada de negócios e os objetos na camada DTO.

Precisamos definir uma enumeração para declarar qual a ação que desejamos realizar. A seguir, temos a enumeração FlagAcao que define três tipos de operação: Insert, Update, Delete e NoAction:

Public Enum FlagAction
Insert = 1
Update = 2
Delete = 3
NoAction = 0
End Enum

No formulário vamos declarar as variáveis para tratar as classes Aluno e Classe:

Private _alunos As List(Of Aluno)
Private _aluno As Aluno
Private _classe As Classe
Private _classes As List(Of Classe)

Esses objetos permitirão acessar e obter informações sobre alunos e classes.

No evento Load do formulário form1.vb vamos carregar a combobox cboClasses e o DataGridView dgvAlunos com as informações das classes e alunos:

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
carregaCombo()
carregaGrid(cboClasses.SelectedValue)
End Sub

O código do procedimento carregaCombo() é o seguinte:

Sub carregaCombo()
Dim clsBLL As New ClasseBLL
_classes = clsBLL.GetTodasClasses
With cboClasses
.DataSource = _classes
.DisplayMember = "NomeClasse"
.ValueMember = "ClasseId"
End With
End Sub

O código acessa o método GetTodasClasses da camada de negócios e preenche o combobox com as classes.

O código do procedimento carregaGrid() é o seguinte:

Sub carregaGrid(ByVal classeID As Integer)
Dim alnBLL As New AlunosBLL
_alunos = alnBLL.GetAlunosPorClasse(classeID)
With dgvAlunos

.DataSource = _alunos
.ColumnHeadersVisible = True

.ColumnHeadersDefaultCellStyle.ForeColor = Color.BurlyWood
.Columns.Item("ClasseId").Visible = False
.Columns.Item("AlunoId").HeaderText = "Codigo do Aluno"
.Columns.Item("NomeAluno").HeaderText = "Nome do Aluno"
.Columns.Item("Acao").Visible = False
End With
End Sub

O código acessa o método GetAlunosPorClasse() passando o código da classe e forma a obter e exibir os alunos de acordo com a classe selecionada.

No evento SelectedIndexChanged da combobox cboClasses temos o código que obtém as classes e conforme a alteração da classe selecionada carrega e atualiza o datagridview com os alunos pertencentes à classe selecionada:

Private Sub cboClasses_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cboClasses.SelectedIndexChanged
If cboClasses.SelectedIndex = -1 Then Exit Sub
Dim cls As Classe
Dim clsBLL As New ClasseBLL
cls = clsBLL.GetClassePorCodigo(cboClasses.SelectedIndex + 1)
If Not IsNothing(cls) Then
carregaGrid(cls.ClasseId)
Me.txtNovaClasse.Text = cls.NomeClasse
End If
End Sub

No evento Click, do botão nova classe, apenas preparamos a interface para incluir uma nova classe ou cancelar a operação:

Private Sub btnNovaClasse_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnNovaClasse.Click
If btnNovaClasse.Text = "Nova Classe" Then
btnNovaClasse.Text = "Cancelar"
btnSalvarClasse.Enabled = True
Me.txtNovaClasse.Text = ""
Me.cboClasses.SelectedIndex = -1

grpNovaClasse.Text = "Informe uma nova Classe"
grpNovaClasse.BackColor = Color.MintCream
grpAlunos.Visible = True
grpAlunos.Enabled = False

Me.txtNovaClasse.Focus()
ElseIf btnNovaClasse.Text = "Cancelar" Then
grpNovaClasse.BackColor = Color.Pink
grpAlunos.Visible = True
grpAlunos.Enabled = True
btnNovaClasse.Text = "Nova Classe"
End If
End Sub

No evento Click do botão Salvar chamamos o procedimento SalvarClasse():

Private Sub btnSalvarClasse_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSalvarClasse.Click
SalvarClasse()
End Sub

O procedimento SalvarClasse() realizar a inclusão de uma nova classe ou atualização de uma classe existente:

Sub SalvarClasse()

Dim bln As Boolean
Dim clsBLL As New ClasseBLL
Dim cls As New Classe

If txtNovaClasse.Text = String.Empty Or txtNovaClasse.Text.Length < 5 Then
MsgBox("Informe o nome da nova classe (minímo 5 caracteres).")
txtNovaClasse.Focus()
Return
End If

cls.NomeClasse = Me.txtNovaClasse.Text.Trim

If cboClasses.SelectedIndex = -1 Then
cls.Acao = FlagAcao.Insert
Else
cls.ClasseId = cboClasses.SelectedValue
cls.Acao = FlagAcao.Update
End If

bln = clsBLL.Salvar(cls)

If bln Then
MessageBox.Show("Dados Atualizados com sucesso !")
If cboClasses.SelectedIndex = -1 Then
carregaCombo()
cboClasses.SelectedIndex = 0
End If
Refresh(cboClasses.SelectedIndex)
grpNovaClasse.Visible = True
grpAlunos.Enabled = True
btnSalvarClasse.Enabled = False
Else
MessageBox.Show("Ocorreu um erro ao atualizar os dados !!")
btnSalvarClasse.Enabled = False
End If
End Sub

No código do evento Click do botão Salvar (grpAlunos) verificamos se existe uma classe selecionada e um nome de aluno informado para chamar o procedimento SalvarAluno():

Private Sub btnSalvarAluno_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSalvarAluno.Click
ErrorProvider1.Clear()
If cboClasses.SelectedIndex = -1 Then
ErrorProvider1.SetError(Me.cboClasses, "Selecione uma Classe!!")
Exit Sub
End If
If Me.txtNovoAluno.Text.Trim() = "" Then
ErrorProvider1.SetError(Me.txtNovoAluno, "Informe o nome do Aluno !!")
Exit Sub
End If
SalvarAluno()
End Sub

O procedimento SalvarAluno() obtém a classe e o nome do aluno, define a ação e chama o método SalvaAluno() passando o objeto Aluno para persistência dos dados:

Sub SalvarAluno()
Dim alnBLL As New AlunosBLL
Dim aln As New Aluno
Dim cls As New Classe
Dim clsBLL As New ClasseBLL
Try
'obtem a classe selecionada
cls = clsBLL.GetClassePorCodigo(cboClasses.SelectedIndex + 1)
'obtem o id da classe
aln.ClasseId = cls.ClasseId
'obtem o nome do aluno
aln.NomeAluno = Me.txtNovoAluno.Text
'define a ação
aln.Acao = FlagAcao.Insert
'usa o método para salvar o aluno
alnBLL.SalvaAluno(aln)
MessageBox.Show("Dados do aluno atualizado com sucesso !!")
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub

Estamos sobrescrevendo o método Refresh do formulário onde atualizamos o controle combobox cboClasses conforme abaixo:

Public Overloads Sub Refresh(ByVal intID As Integer)

cboClasses.DataSource = _classes
cboClasses.Refresh()
cboClasses.SelectedIndex = intID

End Sub

Finalmente o evento CLick do botão Sair encerra a aplicação:

Private Sub btnSair_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSair.Click
Application.Exit()
End Sub

Como podemos observar, nossa camada de apresentação não utiliza nenhuma referência para realizar a persistência. Ao invés disso ela usa os métodos da camada de negócios para realizar tais operações. Assim, qualquer mudança na camada de acesso a dados não afeta diretamente nossa camada de apresentação.

O exemplo da camada de apresentação não está completo e foi usado apenas para ilustrar a separação das responsabilidades em camadas. Assim, completamos a nossa caminhada em sete passos onde percorremos as etapas básicas e em cada passo abordamos os conceitos relacionados à separação de responsabilidades e a criação de camadas.

Pegue o projeto completo aqui: AppTresCamadas.zip

Agora para concluir, vou fazer uma pergunta: você acha que nossa aplicação pode ser considerada uma aplicação orientada a objetos? Não. Ele usa uma abordagem procedural que mescla a utilização dos recursos da orientação a objetos disponíveis na linguagem VB .NET. Em uma aplicação totalmente orientada a objetos a abordagem seria diferente…