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:
Controles 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…
***
Artigo de José Macoratti