Você está na página 1de 12

Artigos http://www.theclub.com.br/restrito/revistas/201310/prog1310.

aspx

Programando em camadas (padrão MVC)

Se você leu o título e ficou pensando que iríamos falar do ASP.NET MVC, se enganou. Vamos falar nesse artigo do
padrão de projeto MVC (Model View Controler) e aprender na prática, como fazer isso no Visual Studio. O MVC é um padrão
de projeto que tem por finalidade, separar dados ou a lógica da aplicação (regras) da interface que o usuário visualiza.
Uma grande vantagem do MVC, é que não temos dependências entre a camada de dados e a camada de interação com o
usuário, ou seja, podemos usar qualquer interface visual para o usuário. A camada do controle (regras) é que define como a
aplicação funcionará. Ela que retorna os dados para a interface e que executa as ações na camada de acesso a dados.
Mas claro, temos desvantagens também, pois nesse padrão, necessitamos de uma quantidade maior de análise (tempo) para
definir o projeto, além de que os profissionais que trabalham, devem ter uma experiência maior no desenvolvimento. Como
também, não é recomendado o uso do MVC para pequenos projetos.
O que pretendo mostrar aqui é apenas uma ideia de como podemos desenvolver aplicações onde as regras fiquem separadas
e podemos definir qual a interface visual o usuário pode usar, ou mesmo, usar mais de uma interface (aplicação Windows,
Web, mobile etc). Deixaremos uma camada apenas para trabalhar com o banco, para retornar dados e executar comandos
SQL.
Na Figura 1, temos um exemplo simples, de como funciona um modelo MVC.

Figura 1. Conhecendo o padrão de projeto MVC. Fonte:www.oficinadanet.com.br


 
Neste artigo, teremos uma camada (um projeto Class Library), responsável pelos dados, onde usaremos o Entity
Framework. Outra camada (Class Library) terá os métodos que buscam os dados da camada do banco e retornam para a
camada de apresentação.
Além disso, é responsável por executar as ações de manipulação de dados do cadastro. Outra dica importante, as
validações, regras da aplicação, serão feitas nessa camada.
Qual a vantagem disso? Independente a plataforma que utilizarmos (Windows ou Web) é nessa camada que os dados
serão validados, verificado a sua consistência, e não na apresentação. Por fim, a camada de apresentação, dependerá da
necessidade do desenvolvedor em utilizar.
 
Criando o projeto
Vamos criar o projeto. Caso você queira usar a versão comercial do Visual Studio, todos os projetos podem ficar na
mesma Solution. Usarei aqui, as versões Express do Visual Studio 2012, assim, são duas ferramentas separadas (Web e
desktop). O fonte pode ficar organizado nos mesmos diretórios.
Crie um novo projeto Class Library no Visual Studio 2012 Express for Desktop. Dê o nome de “DataAccess” ao
projeto. Crie um novo Class Library e dê o nome de “Business”. Crie um projeto Windows Forms e dê o nome de
“DesktopApp”. Comparando com o padrão MVC, o DataAccess seria o Model, o Bussiness o Controller e a aplicação
Windows seria a nossa View.
Veja na Figura 2 o Solution Explorer (arquivos Class1.cs removidos).

1 de 12 15/04/17 06:48
Artigos http://www.theclub.com.br/restrito/revistas/201310/prog1310.aspx

Figura 2. Solution Explorer com os projetos de exemplos


 
No projeto DataAccess vamos conectar com o banco de dados e usar o Entity Framework. Acesse Add>New Item no
menu de contexto do projeto e no editor escolha ADO.NET Entity Data Model.

Nota: se você não tem experiência com o EF, indico dois artigos publicados na The Club
sobre o assunto, que estão na seção Links.

 
Não vou me apegar ao banco de dados, você pode usar um de sua preferência, ou até mesmo pode criar um modelo
do zero e gerar o banco de dados. Depois de criado o modelo com o banco de dados teremos algo semelhante ao da Figura
3.

Figura 3. Modelo do EF criado

O EF mapeia as tabelas do banco e com isso podemos trabalhar com entidades. O DataAccess será nosso Model do
padrão, responsável pela conexão com os dados, ou seja, sua responsabilidade é: disponibilizar os dados quando solicitados
e realizar as ações de atualização, inserção e exclusão.
 
Criando a camada de dados

2 de 12 15/04/17 06:48
Artigos http://www.theclub.com.br/restrito/revistas/201310/prog1310.aspx

Temos o modelo criado, agora, vamos criar as classes para manipular esse modelo criando os métodos de
inserção/atualização, exclusão e pesquisas. Primeiramente, vamos criar uma classe para ser a base de todas as outras.
Clique com o botão direito no projeto e escolha Add>New Item. No editor, escolha Class, dando o nome de “BaseClass.cs”.
Na Listagem 1 temos a classe base.
 
Listagem 1. Classe base para o projeto DataAccess

namespace DataAccess
{
public class BaseClass<T>
{
public virtual bool Salvar(bool Insert, T objeto)
{
return false;
}
public virtual bool Excluir(T objeto)
{
return false;
}
public virtual T Pesquisar(int codigo)
{
return default(T);
}
public virtual List<T> PesquisarTodos()
{
return new List<T>();
}
public virtual List<T> PesquisarTexto(string descricao)
{
return new List<T>();
}
}
}

 
Criamos métodos virtuais que serão implementados nas classes que herdarem de BaseClass. O T indica o tipo de
objeto que vamos manipular, por exemplo, para a classe de Produtos, o T será nosso mapeamento de produtos.
Vamos agora, criar uma classe que herde da base. Crie uma classe, conforme a anterior, com o nome de “dalProduto.cs”.

Nota: Dê a nomenclatura que quiser, de acordo com seus padrões de desenvolvimento.

 
Vamos modificar a classe, conforme o código a seguir, para herdar da BaseClass.
 

public class dalProduto: BaseClass<PRODUTO>

 
Note que precisamos especificar qual a classe que vamos usar (o T da classe base). Isso é obrigatório. Agora, temos
que redeclarar os métodos virtuais da classe base, para que possamos implementar as funcionalidades da classe Produto.
Digite “public override ” e será aberto um menu com os métodos virtuais da classe base. Escolha o Salvar e o Visual Studio
completa a declaração do método, alterando o T pela classe indicada anteriormente (PRODUTO). Faça isso para todos os
métodos.
Claro, precisamos codificar os métodos, pois como estão no momento, não executam nada. Veja na Listagem 2 a
implementação de todos os métodos.
 
Listagem 2. Implementação dos métodos virtuais da classe base

using System.Collections.Generic;
using System.Data;
using System.Linq;

namespace DataAccess

3 de 12 15/04/17 06:48
Artigos http://www.theclub.com.br/restrito/revistas/201310/prog1310.aspx

{
public class dalProduto: BaseClass<PRODUTO>
{
public override bool Salvar(bool Insert, PRODUTO objeto)
{
using (EntityTheClubEntities db = new EntityTheClubEntities())
{
if (Insert)
db.AddToPRODUTO(objeto);
else
{
db.PRODUTO.Attach(objeto);
db.ObjectStateManager.ChangeObjectState(objeto,
EntityState.Modified);
}
return (db.SaveChanges() > 0);
}
}

public override bool Excluir(PRODUTO objeto)


{
using (EntityTheClubEntities db = new EntityTheClubEntities())
{
PRODUTO produto = (from p in db.PRODUTO
where p.nCdProduto == objeto.nCdProduto
select p).FirstOrDefault();
db.DeleteObject(produto);

return (db.SaveChanges() > 0);


}
}

public override PRODUTO Pesquisar(int codigo)


{
using (EntityTheClubEntities db = new EntityTheClubEntities())
{
return (from p in db.PRODUTO where p.nCdProduto == codigo
select p).FirstOrDefault();
}
}

public override List<PRODUTO> PesquisarTodos()


{
using (EntityTheClubEntities db = new EntityTheClubEntities())
{
return db.PRODUTO.ToList();
}
}

public override List<PRODUTO> PesquisarTexto(string descricao)


{
using (EntityTheClubEntities db = new EntityTheClubEntities())
{
return (from p in db.PRODUTO
where p.sNmProduto.ToUpper().Contains(descricao.ToUpper())
select p).ToList();
}
}
}
}

 
Usamos LINQ para os métodos de pesquisa. Para o Salvar usamos os métodos do EF para inserção ou atualização

4 de 12 15/04/17 06:48
Artigos http://www.theclub.com.br/restrito/revistas/201310/prog1310.aspx

do objeto Produto. O Excluir possui funcionalidade semelhante, apenas alterando o método que executa a ação. Fizemos uma
pesquisa para confirmar que estamos retornando o objeto certo para a exclusão, realizando uma pesquisa pelo código, assim
o objeto que passamos como parâmetro precisa ter apenas o código para excluir corretamente.
Faça o mesmo para as outras entidades do modelo. Para as entidades VENDA e VENDA_ITEM, não temos
necessidade de uma funcionalidade para pesquisa de descrição, então, retorne apenas null nesses métodos. Como eles estão
na classe base, devem ser declarados na classe herdade e precisam de um retorno.
 
Criando a camada de negócio
Agora, vamos entender o funcionamento do Business (Controller), o mais importante desse projeto em camadas. Nele
vamos criar as classes que vão invocar os métodos para manipular o banco (classes criadas anteriormente no DataAccess) e
também responsável por gerenciar as regras, validações etc.

Nota: precisamos adicionar ao projeto a referência ao DataAccess e na seção using


adicionar “DataAccess”.

 
Crie uma nova classe no projeto Business (dê o nome de “balProduto.cs”) e veja na Listagem 3 o código da classe.

Nota: caso queira, você também pode fazer uma classe base com os métodos padrões e usar
o mesmo conceito apresentado anteriormente.

 
 
Listagem 3. Classe para o projeto Business (Controller)

using DataAccess;
using System.Collections.Generic;

namespace Business
{
public class balProduto
{
private dalProduto produto { get; set; }

public balProduto()
{
produto = new dalProduto();
}

public bool Salvar(bool Insert, PRODUTO objeto)


{
return produto.Salvar(Insert, objeto);
}

public bool Excluir(PRODUTO objeto)


{
return produto.Excluir(objeto);
}

public PRODUTO Pesquisar(int codigo)


{
return produto.Pesquisar(codigo);
}

public List<PRODUTO> PesquisarTodos()


{
return produto.PesquisarTodos();

5 de 12 15/04/17 06:48
Artigos http://www.theclub.com.br/restrito/revistas/201310/prog1310.aspx

public List<PRODUTO> PesquisarTexto(string descricao)


{
return produto.PesquisarTexto(descricao);
}
}
}

 
Temos nesse exemplo, uma classe que apenas invoca métodos do DataAccess, usando uma propriedade privada que
instanciamos no construtor da classe. Após, temos que implementar as classes de todos os objetos do EF mostrados
anteriormente. Veja na Figura 4 todas as classes criadas nos dois projetos.

Figura 4. Classes criadas nos projetos


 
Validações e regras
Como comentamos anteriormente, a camada de negócio é a responsável pelas validações e regras que executa na
camada de banco (Model). Isso facilita, pois precisamos codificar e fazer a manutenção em apenas um local. Caso usássemos
a camada de apresentação para isso, precisaríamos codificar as regras e validações na aplicação Web e desktop, ou seja, em
cada tipo de camada de apresentação que usássemos, aumentando assim o trabalho de desenvolvimento.
Vamos implementar apenas um exemplo de como codificar regras e validações na camada de negócio. Alguns campos são
obrigatórios nos cadastros. Vamos modificar (Listagem 4) o método Salvar da classe produto para verificar, se os campos
obrigatórios estão preenchidos.
 
Listagem 4. Validando a obrigatoriedade do campo no Controller

using System;
...
public bool Salvar(bool Insert, PRODUTO objeto)
{
if (string.IsNullOrEmpty(objeto.sNmProduto))
throw new Exception("Campo Nome do Produto: preenchimento obrigatório.");

if (objeto.nVlProduto <= 0)
throw new Exception("Campo Valor do Produto: valor deve ser maior que zero.");

return produto.Salvar(Insert, objeto);


}

 
Verificamos se o campo sNmProduto foi preenchido e invocamos uma exceção para ser tratada na camada de
apresentação. Para o campo nVlProduto, verificamos se ele é maior que zero.

6 de 12 15/04/17 06:48
Artigos http://www.theclub.com.br/restrito/revistas/201310/prog1310.aspx

Nota: O Entity Framework possui a facilidade de usarmos o First Model e classes POCO,
assim, utilizando marcação de atributos (Data Annotations), podemos criar esse tipo de
regra/validação de forma mais simples.

 
 
Implementando a camada de apresentação
Bom, agora precisamos codificar a camada de apresentação. Qual usar? Web ou desktop? Independe, a escolha é
sua. Uma ou as duas, podem ser utilizadas nesse exemplo. Vamos primeiramente, criar uma aplicação desktop e novamente,
vamos usar Orientação a Objetos no exemplo.
Vamos usar herança visual de formulários para os cadastros. Será semelhante ao que fizemos com a classe base e as
classes herdadas, com a diferença que teremos nesse caso, formulários. Caso tenha mais interesse sobre o assunto, veja a
seção Links onde mostro em um artigo como fazer herança de formulários com Windows Forms.
Na Figura 5, temos o formulário base do cadastro.

Figura 5. Formulário base de cadastro


 
Criaremos um formulário que será o cadastro de produtos. Após herdar o mesmo do formulário base, vamos codificar
os métodos virtuais. Veja na Listagem 5 os métodos virtuais.
 
Listagem 5. Métodos implementados no cadastro de Produtos

public override void Pesquisar()


{
List<PRODUTO> lista = objProduto.PesquisarTexto(txtPesquisa.Text);

lvPesquisa.Items.Clear();
foreach (PRODUTO produto in lista)
{
ListViewItem item = new ListViewItem(produto.nCdProduto.ToString());
item.SubItems.Add(produto.sNmProduto);

lvPesquisa.Items.Add(item);
}

lblMensagem.Text = lista.Count.ToString() + " registro(s) encontrado(s) com o texto '"


+ txtPesquisa.Text + "'";
}

public override void PreencheControles()


{

7 de 12 15/04/17 06:48
Artigos http://www.theclub.com.br/restrito/revistas/201310/prog1310.aspx

PRODUTO produto = objProduto.Pesquisar(_nCdCodigo);

lblCodigo.Text = produto.nCdProduto.ToString();
txtNomeProduto.Text = produto.sNmProduto;
txtValor.Text = produto.nVlProduto.ToString();
txtQuantidade.Text = produto.nQtdeMin.ToString();
lblQtdeAtual.Text = produto.nQtdeAtual.ToString();
}

public override bool Salvar()


{
try
{
PRODUTO produto = new PRODUTO();

if (scStatus == StatusCadastro.scEditar)
produto.nCdProduto = Convert.ToInt32(lblCodigo.Text);

produto.sNmProduto = txtNomeProduto.Text;
produto.nVlProduto = Convert.ToDecimal(txtValor.Text);
produto.nQtdeMin = Convert.ToDecimal(txtQuantidade.Text);

return objProduto.Salvar(scStatus == StatusCadastro.scNovo, produto);


}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Erro", MessageBoxButtons.OK,
MessageBoxIcon.Error);
return false;
}
}

public override bool Excluir()


{
try
{
PRODUTO produto = new PRODUTO();
produto.nCdProduto = Convert.ToInt32(lblCodigo.Text);

return objProduto.Excluir(produto);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Erro", MessageBoxButtons.OK,
MessageBoxIcon.Error);
return false;
}
}

 
Como podemos ver, usamos os métodos do Business (Controller) que por sua vez, irá invocar os métodos do
DataAccess (Model). O objProduto, é uma variável privada da classe que é instanciada no construtor do formulário.
O Pesquisar, realizada a pesquisa, usando o PesquisaTexto, preenche os dados retornados no ListView e exibe uma
mensagem com a quantidade de registros retornados. O PreencheControles, apenas pesquisa pelo código do produto e
preenche os controles de tela. A variável _nCdCodigo é do formulário base e é preenchido quando o usuário da um duplo
clique no ListView para selecionar o registro.
No Salvar, preenchemos o objeto da entidade do modelo e passamos como parâmetro para realizar a inserção ou
atualização. A scStatus indica se estamos inserindo ou atualizando um registro. O Excluir, também é bastante simples, onde
apenas indicamos o valor do código do produto na entidade e passamos a mesma por parâmetro.

8 de 12 15/04/17 06:48
Artigos http://www.theclub.com.br/restrito/revistas/201310/prog1310.aspx

Nota: os métodos Salvar e Excluir possui um bloco try..catch para que possamos mostrar os erros ocorridos ou as
mensagens de validação que implementamos.
Criei um formulário principal para chamar os formulários de cadastro da aplicação. Veja na Figura 6 o cadastro em
execução.

Figura 6. Aplicação desktop em execução


 
Criando o projeto Web
Agora, se precisarmos trocar a camada de apresentação? Web é a nossa possibilidade. Precisamos mudar muita
coisa nas camadas de negócio e de dados? Eu diria, praticamente nada.

Nota: A plataforma Mobile tem características muito diferentes da Web e desktop,


portanto, podemos usar esse exemplo e pode ser necessário algumas modificações.

 
Vamos usar o Visual Studio 2012 for Web. Assim, precisamos pegar as DLLs do projeto (Business e DataAccess) para
usar nas referências. Caso você esteja usando a versão comercial do Visual Studio, pode criar a aplicação Web na própria
Solution que tem o projeto desktop e library.
Dê o nome de “WebApp” para o projeto. Para adicionar a referência das DLLs, clique no item References e escolha
Add Reference. No editor, clique em Browse e procure as DLLs do projeto. Após adicionar, basta usar o namespace Business
e DataAccess onde for necessário, que teremos acesso as classes da camada de negócios (Controller) e as entidades (Model).
Para o cadastro, vamos criar uma página simples, para os produtos. Nesse exemplo, não implementaremos a
pesquisa. Deixo como exercício para o leitor aumentar seus conhecimentos em aplicações ASP.NET J.
Veja na Figura 7 o cadastro de Produtos na app Web.

9 de 12 15/04/17 06:48
Artigos http://www.theclub.com.br/restrito/revistas/201310/prog1310.aspx

Figura 7. Criando o cadastro no ASP.NET

Nota: não me atentei ao layout da aplicação e suas funcionalidades, pois o importante


aqui é a utilização das classes criada anteriormente.

 
Veja na Listagem 6, o código dos métodos Salvar e Excluir.
 
Listagem 6. Métodos Salvar e Excluir

using DataAccess;
using Business;
...
protected void ImageButton2_Click(object sender, ImageClickEventArgs e)
{
try
{
balProduto objProduto = new balProduto();
PRODUTO produto = new PRODUTO();

produto.nCdProduto = Convert.ToInt32(lblCodigo.Text);
produto.sNmProduto = txtNomeProduto.Text;
produto.nVlProduto = Convert.ToDecimal(txtValor.Text);
produto.nQtdeMin = Convert.ToDecimal(txtQuantidade.Text);
produto.nQtdeAtual = Convert.ToDecimal(lblQuantidade.Text);

if (objProduto.Salvar(false, produto))
{
MessageBox1.ShowMessage("Registro salvo com sucesso.");
}
}
catch (Exception ex)
{
MessageBox1.ShowMessage(ex.Message);
}
}

protected void ImageButton3_Click(object sender, ImageClickEventArgs e)


{
try
{
balProduto objProduto = new balProduto();
PRODUTO produto = new PRODUTO();

produto.nCdProduto = Convert.ToInt32(lblCodigo.Text);

10 de 12 15/04/17 06:48
Artigos http://www.theclub.com.br/restrito/revistas/201310/prog1310.aspx

if (objProduto.Excluir(produto))
{
MessageBox1.ShowMessage("Registro excluido com sucesso.");
}
}
catch (Exception ex)
{
MessageBox1.ShowMessage(ex.Message);
}
}

 
Utilizei o valor dos controles de tela para preenche o objeto e salvar ou excluir o registro. Em uma aplicação real,
temos que usar outras facilidades, como variáveis de sessão etc. O código é muito parecido com a aplicação Windows
Forms. Criamos uma instância do Produto, preenchemos suas propriedades e chamamos o método Salvar, passando a
instância como parâmetro.
Como você deve ter notado, tanto na aplicação Windows, como na Web, o código esta dentro de um bloco try..catch.
Isso ocorre, por que as validações, dentro do Business (Controller), gera exceções quando alguma regra ou validação é
necessária.
Assim, na camada de apresentação que vamos mostrar para o usuário de maneira mais elegante, o erro ou
mensagem de validação. Para Windows Forms, é simples, basta usar o MessageBox, que mostra caixas de mensagem ou
confirmação, padrão do Windows. Para a Web, não temos um caixa de mensagem padrão.
Podemos contornar usando um controle Web desenvolvido para esse fim. Na seção Links temos um artigo sobre um
controle web para trabalhar com caixas de mensagem e de confirmação no ASP.NET.
Veja na Figura 8, as duas aplicações, usando a mesma validação.

Figura 8. Aplicações com a mesma validação


 
Note que a facilidade fica por conta que não precisarmos fazer a validação na camada de apresentação Web ou
desktop. Essa validação esta no Controller e será mostrada independente de plataforma. Precisamos apenas saber como
apresentar a mesma para o usuário de acordo com a plataforma usada.

Nota: tanto no projeto desktop, como Web é necessário ter no arquivo config a string de
conexão do Entity Framework com o banco de dados (com o mesmo nome).

 
 
Conclusões
Vimos nesse artigo, uma dica interessante para criar aplicações Web ou Windows Forms, onde usamos o padrão de
projetos MVC, para dividir a aplicação em camadas que podem conversar independente da plataforma usada, sem a
necessidade de mudanças na sua estrutura e código.
Isso proporciona também uma fácil manutenção e podemos dizer, nas alterações que se fazem necessárias. Mas fica
a dica de que usar o padrão MVC, não é recomendado para projetos muito pequenos, pois o tempo de análise pode ser
grande, assim como sua equipe tem que ter um nível de experiência bem alto.
Um grande abraço a todos e até a próxima!
 
Links
ADO.NET Entity Framework

11 de 12 15/04/17 06:48
Artigos http://www.theclub.com.br/restrito/revistas/201310/prog1310.aspx

www.lucianopimenta.com/post.aspx?id=242
ADO.NET Entity Framework – Parte II
www.lucianopimenta.com/post.aspx?id=243
Herança visual de formulários no Windows Forms
www.lucianopimenta.com/post.aspx?id=193
Mensagens no ASP.NET
www.lucianopimenta.com/post.aspx?id=37

 
Sobre o Autor

Luciano Pimenta (NOVO DOMINIO: www.lucianopimenta.com) é desenvolvedor


Delphi/C# para aplicações Web com ASP.NET, Windows com Win32 e Windows Forms com
.NET. Palestrante da 4ª edição da Borland Conference (BorCon) e da 1ª Delphi
Conference. É MVP Embarcadero, grupo de profissionais que ajudam a divulgar o Delphi
no mundo. Atualmente é desenvolvedor da SoftDesign fábrica de softwares em Porto
Alegre-RS. Autor de mais de 80 artigos e de mais de 600 vídeos aulas publicadas em
revistas e sites especializados, além de treinamentos presenciais e multimídias. É consultor
da FP2 Tecnologia (www.fp2.com.br) onde ministra cursos de programação e banco de
dados.

E-mail: www.lucianopimenta.net

12 de 12 15/04/17 06:48