segunda-feira, junho 30, 2008

Desenvolvimento Multi-Camada Simplificado no C#

A expressão "desenvolvimento multi-camada" é usada com freqüência no
desenvolvimento de software, nem sempre com o mesmo significado. De uma forma geral, a idéia de quebrar um desenvolvimento em camadas tem por objetivos facilitar o desenvolvimento ("dividir para conquistar") e facilitar a substituição de partes do código em eventuais (inevitáveis?) versões futuras.

Neste post estou me referindo à divisão interna em camadas de um aplicativo PC tradicional do tipo client-server (ou seja, estou falando das camadas dentro da camada client). Vamos tomar como exemplo um aplicativo simples, que apresenta na tela uma tabela com as informações de livros que estão armazenadas em uma base de dados. Para simplificar o lado server, vou usar uma base de dados Access (é trivial substituí-la por uma base SQL Server ou qualquer outra acessível pelo ADO.Net).

Já faz bastante tempo que o desenvolvimento deste tipo de aplicação é facilitado pelos ambientes integrados. A maioria deles possui um componente visual que pode ser conectado diretamente a uma base de dados; a maior parte do desenvolvimento é feita clicando e arrastando, como pouca escrita de código. O problema desta solução é que fica tudo misturado em um único fonte. Se quisermos mudar a fonte dos dados ou o componente visual acabamos tendo que refazer tudo.

A solução clássica multi-camada para este tipo de aplicação envolve três camadas:

  • a camada de dados, responsável por acessar a base de dados recuperando e atualizando os dados necessários.
  • a camada de negócios, que define objetos que representam as entidades de negócio e implementam as regras de negócio. Esta camada faz a ligação entre as outras duas.
  • a camada de apresentação (ou interface com o usuário), responsável por apresentar os dados contidos em objetos de negócio.

Desta forma fica mais fácil alterar uma parte da aplicação sem interferir no resto.

A partir da versão 2 do C# e do .Net Framework existe uma forma bastante simples de desenvolver aplicações com estas três camadas. Segue abaixo um passo a passo para fazer a minha aplicação exemplo no Visual Studio 2005.

1) Selecionar File New Project Windows Application, chame a aplicação de AppCamadas.

2) Clicar com o botão direito em Appcamadas no Solution Explorer, selecionar Add Class. Chame a classe de Livro, ela será a nossa camada de negócios. Entre com o código abaixo:

    class Livro
{
private string _titulo;
public string Titulo
{
get { return _titulo; }
set { _titulo = value; }
}

private string _autor;
public string Autor
{
get { return _autor; }
set { _autor = value; }
}

private DateTime _dtEmprestimo;
public DateTime DtEmprestimo
{
get { return _dtEmprestimo; }
set { _dtEmprestimo = value; }
}

public bool Emprestado
{
get { return DtEmprestimo != DateTime.MaxValue; }
}

public Livro() { }
public Livro(string titulo, string autor, DateTime dtEmprest)
{
Titulo = titulo;
Autor = autor;
DtEmprestimo = dtEmprest;
}
}

Note que estamos usando propriedades para controlar o acesso aos membros. Isto permite encapsular uma regra de negócio: livros não emprestados são indicados por uma data de empréstimo igual a DateTime.MaxValue.

3) Build / Build Solution (para a IDE conhecer a classe e suas propriedades)

4) Clicar o botão direito em Form1.cs no Solution Explorer, selecionar Rename, alterar o nome para frmConsulta, confirmar. Esta é a nossa camada de apresentação.

5) Selecionar aba frmConsulta.cs [Design]. Selecionar o form. Alterar a gosto Text, Size, StartPosition.

6) Arrastar do toolbox um DataGridView. Mudar o tamanho para ocupar todo o form. Com o DataGrivView selecionado no form, mudar as propriedades

  • Name: dgvLicros
  • Anchor: Top, Bottom, Left, Right (faz resize automático do grid quando muda tamanho do form)
  • Read Only: True
  • Row Select Mode: FullRowSelect

7) Clicar na seta tinha no alto à direita do grid (smarttag).


Limpar Enable Adding e Enable Deleting. SelecionarChoose Data Source, Add Project DataSource, Object, Next, escolher Livro, Next e Finish.

Neste ponto é que é feita a mágica: o grid foi configurado para apresentar os membros e propriedades públicos da nossa classe. Um objeto BindingSource (criado automaticamente pela IDE) fará a ponte entre o componente de apresentação e a fonte dos dados.

8) Clicar novamente na seta tinha no alto à direita do grid, selecionar Edit Columns. Mover Emprestado para o inicio da lista e remover DtEmprestimo.

9) Clicar com o botão direito em Appcamadas no Solution Explorer, selecionar Add Class. Chamar a nova classe de AcessoBD, esta será a nossa camada de dados. Entre com o código abaixo:

using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.OleDb;

namespace AppCamadas
{
class AcessoBD
{
private const string StrCnx =
@"Provider=Microsoft.Jet.Oledb.4.0;" +
@"Data Source=Livros.mdb;";

public static List GetLivros()
{
List lstLivros = new List();
OleDbConnection cnn = new OleDbConnection(StrCnx);
OleDbCommand cmd = new OleDbCommand
("SELECT * FROM LIVROS", cnn);
try
{
cnn.Open();
OleDbDataReader dr = cmd.ExecuteReader();
DateTime dtEmprest;
while (dr.Read())
{
if (dr["Emprestimo"].Equals(System.DBNull.Value))
dtEmprest = DateTime.MaxValue;
else
dtEmprest = Convert.ToDateTime(dr["Emprestimo"]);
lstLivros.Add (new Livro (dr["Titulo"].ToString(),
dr["Autor"].ToString(),
dtEmprest));
}
cnn.Close();
}
catch
{
// tratamento de erros fica como exercício ao leitor
}
return lstLivros;
}
}
}

Este código é bastante simplista. Os dados extraídos da base de dados são colocados em uma lista de objetos de negócio. O BoundingSource usado na camada de apresentação suporta vários tipos de origem para os dados, graças ao recurso de generics do C# criamos de forma fácil uma lista de livros.

10) Build / Build Solution (opcional, só para ver que não fizemos nada de errado até agora)

11) Selecionar a aba frmConsulta.cs [Design]. Selecionar o form, dar um duplo clique no form (para criar um tratamento para o evento Load). Adicionar a linha abaixo.

            dgvLivros.DataSource = AcessoBD.GetLivros();

12) Digitar F5 (Start) e ver o show!

Embora esta técnica requeira um pouco mais de digitação que uma ligação direta do datagrid à base de dados, ela organiza melhor o código e nós dá uma grande liberdade. Se, por exemplo, quisermos mover a base de dados do Access para o SQL Server, basta alterar a camada de dados, sem mexer nas demais.

O projeto completo, incluindo a base de dados, pode ser baixado daqui.

Um comentário:

Ricardo SW disse...

Ótimo tutorial, me ajudou muito a entender o conceito do desenvolvimento em camadas.