Thursday, January 21, 2010

Modelo-Visão-Controlador

Nessa arquitetura, cada funcionalidade de um sistema é dividida em três elementos:
  • Visão - Representa a interface gráfica da funcionalidade. Não tem código é apenas uma máscara.
  • Controlador - Faz a ponte entre a interface gráfica e a lógica de negócio
  • Modelo - São as classes usadas para descrever a lógica de negócio ( classes do problema ( DP ) e classes de persistência (DAO) ) ou ainda podem ser classes da camada de serviço
O MVC (model-view-controller) ou modelo-visão-controlador é um dos design patterns mais variados que existem pois existem vários tipo de implementações e derivações. No exemplo utilizado aqui, o controlador acessa a visão através de uma interface apenas e a visão se comunica apenas através de eventos que são capturados pelo controlador.

No exemplo abaixo, o controlador pode controlar os componentes gráficos que compõe a visão
( textBox, combobox, grids, etc. ) mas não acessa estes controles diretamente de JanCadastroCliente mas apenas pela interface ICadastroClienteView. Dessa forma, o controlador não precisa conhecer a tecnologia específica (web, winforms, mobile, etc.) que este está controlando. Além disso, o controlador pode ser checado por testes unitários.

Com isso o controlador pode controlar a visão quando:
  • ler/escrever dados nos componentes
  • habilitar/desabilitar componentes
  • mostrar/esconder componentes
  • outras operações que forem necessárias
Por outro lado, quando o usuário dispara um evento como pressionar um botão no formulário, a JanCadastroCliente deve executar um método do controlador que trata daquele evento.
O tráfego de dados entre o Formulário ou WebForm e o controlador é feito via Data Transfer Objects (DTO) o que evita que objetos de negócio sejam levados diretamente para a interface e causar problemas ja que a sessão desses objetos já estaria fechada.


ICadastroClienteView

public interface ICadastroClienteView
{
long IdClient { get; set; }
string NomeCliente { get; set; }
int CodDocumentoCliente { get; }
IList Documentos { set; }
event EventHandler NovoCliente;
event EventHandler InclusaoCliente;
event EventHandler ConsultaCliente;
}

JanCadastroCliente (Winforms)
public class JanCadastroCliente : System.Windows.Forms.Form, ICadastroClienteView
{
: : : : : // código do formulário

// Formulário deve possuir uma referência para o seu controlador correspondente
private ControladorCadastroCliente controlador = new ControladorCadastroCliente(this);

// Le ou mostra o Id do Cliente num label
public long IdCliente
{
get { return Int64.Parse(this.lbIdCliente.Text); }
set { this.lbIdCliente.Text = Int64.Parse(this.lbIdCliente.Text); }
}

// Le ou mostra o nome do cliente num textbox
public string NomeCliente // Le/escreve dados no textBox
{
get { return this.txtNomeCliente.Text; }
set { this.txtNomeCliente.Text = value; }
}

// Le ou mostra os documentos de um cliente
public IList Documentos
{
set { this.cmbbxDocumentos.DataSource = value; }
get { return this.cmbbxDocumentos.DataSource; }
}

// Le um id de cliente num componente numeric para fins de pesquisa
public long IdClientePesquisa
{
get { return this.numIdClientePesquisa.Value; }
}

public JanCadastroCliente()
{
}

public void JanCadastroCliente_btNovoCliente(Object sender,EventArgs e)
{
if (this.NovoCliente != null) { this.NovoCliente(sender,e); }
}

public void JanCadastroCliente_btInclusaoCliente(Object sender,EventArgs e)
{
if (this.InclusaoCliente != null) { this.InclusaoCliente(sender,e); }
}

public void JanCadastroCliente_btConsultaCliente(Object sender,EventArgs e)
{
if (this.ConsultaCliente != null) { this.ConsultaCliente(sender,e); }
}

}

WebCadastroCliente (Webforms)
public class WebCadastroCliente: System.Windows.Forms.Form, ICadastroClienteView
{
: : : : : // código do formulário

// Formulário deve possuir uma referência para o seu controlador correspondente
private ControladorCadastroCliente controlador;

protected void Page_Load(object sender, System.EventArgs e)
{
controlador = new ControladorCadastroCliente(this);
}

// Le ou mostra o Id do Cliente num label
public long IdCliente
{
get { return Int64.Parse(this.lbIdCliente.Text); }
set { this.lbIdCliente.Text = Int64.Parse(this.lbIdCliente.Text); }
}

// Le ou mostra o nome do cliente num textbox
public string NomeCliente // Le/escreve dados no textBox
{
get { return this.txtNomeCliente.Text; }
set { this.txtNomeCliente.Text = value; }
}

// Le ou mostra os documentos de um cliente
public IList Documentos
{
set { this.cmbbxDocumentos.DataSource = value; }
get { return this.cmbbxDocumentos.DataSource; }
}

// Le um id de cliente num componente numeric para fins de pesquisa
public long IdClientePesquisa
{
get { return this.numIdClientePesquisa.Value; }
}

public void WebCadastroCliente_btNovoCliente(Object sender,EventArgs e)
{
if (this.NovoCliente != null) { this.NovoCliente(sender,e); }
}

public void WebCadastroCliente_btInclusaoCliente(Object sender,EventArgs e)
{
if (this.InclusaoCliente != null) { this.InclusaoCliente(sender,e); }
}

public void WebCadastroCliente_btConsultaCliente(Object sender,EventArgs e)
{
if (this.ConsultaCliente != null) { this.ConsultaCliente(sender,e); }
}

}

ControladorCadastroCliente
public class ControladorCadastroCliente
{
private ICadastroClienteView _view;
private ServicoCadastroCliente _servicoCadastroCliente;

public ControladorCadastroCliente(ICadastroClienteView view)
{
this._view = view;
this._view.NovoCliente += new EventHandler(LimparCliente);
this._view.InclusaoCliente += new EventHandler(IncluirCliente);
this._view.ConsultaCliente += new EventHandler(ConsultarCliente);
this._servicoCadastroCliente = new ServicoCadastroCliente();
}

public void LimparCliente(Object sender, EventArgs e)
{
this.IdCliente = 0;
this.NomeCliente = string.Empty;
this.Documentos = new List();
}

public void IncluirCliente(Object sender, EventArgs e)
{
long idCliente = this._servicoCadastroCliente.Incluir(
this._view.NomeCliente,
this._view.Documentos);
this._view.IdCliente = idCliente;
}

public void ConsultarCliente(Object sender, EventArgs e)
{
ClienteDTO dto = this._servicoCadastroCliente( this.IdClientePesquisa );
this._view.IdCliente = dto.Id;
this._view.NomeCliente = dto.Nome;
this._view.Documentos = dto.Documentos;
}

}

DocumentoDTO
public class DocumentoDTO
{
public int CodDocumento { get; set; }
public string Descricao { get; set; }
// É a forma como o DTO vai aparecer no combobox ou listbox, etc.
// Mostra apenas a descricao
public override string ToString()
{
return descricao;
}
}