Microsoft.com Brasil Home | Mapa do Site
HyperLink
 
Procurar no Microsoft.com por:
 
  Home | Developer Center | Biblioteca | Downloads | Como Comprar | Assinaturas MSDN




Pesquisa rápida

 
 
  
Home MS Brasil
Compre
Downloads
Suporte
Fale conosco

 Tecnologias :: Visual FoxPro
 
  
Desenvolvimento de aplicações multi-camadas com VFP e VB


Por Jorge A. Espinosa, artigo originalmente publicado na revista UTMag/RapoZine.


Neste artigo poderemos ver como, utilizando as ferramentas que temos a nosso alcançe, poderemos fazer uso da tecnologia COM para encarar um desenvolvimento em n camadas e usufruir das verdadeiras vantagens da reutilização de código que nos permite a implementação da referida arquitetura. Desenvolveremos um sistema de teste no qual construiremos as camadas intermediárias e, sem necessidade trocar nenhum componente, faremos a mesma interface de usuário utilizando Visual Fox Pro e Visual Basic para depois tratar a origem de dados e ver a facilidade de alterar (neste caso pode ser outros como SQL Server, Oracle, etc) de uma origem de dados VFP para um BD do Access.

Como chegamos hoje a esta Tecnologia

Para compreender melhor onde estamos hoje ou que tecnologia estamos utilizando, devemos dar uma rápida olhada para trás e ver um pouco de história sobre o desenvolvimento de aplicações com base de dados

Quatro arquiteturas distintas de desenvolvimento se passaram até chegarmos hoje a conceber o denominado desenvolvimento em n camadas, mencionamos na primeira instância a primeira forma de escrever nossos programas que tivemos ao sentarmos pela primeira vez em frente a um PC (vocês lembram do FoxDOS ou Clipper ?), bom, aí temos a arquitetura de uma camada ou "Single-Tier", logo chegaram os servidores, começamos a trabalhar em 2 camadas ou Client/Server, Há alguns anos atrás, começamos a ouvir alguma coisa sobre desenvolvimento em 3 camadas (Three-Tier development), sobre isso, em particular, vamos entrar um pouco em detalhe, porque nos vai ser útil para entender a nova arquitetura

A idéia de desenvolvimento em 3 camadas consistia em utilizar um método de desenvolvimento para nossos sistemas que nos permitia separá-los em camadas distintas. As camadas recomendadas eram: A interface com o usuário, as regras de negócio e a base de dados, a idéia desta arquitetura estava baseada principalmente na capacidade de escabilidade que esta nos oferece, por exemplo, se temos desenvolvida uma aplicação baseada em uma fonte de dados em VFP e se no desenvolvimento desta, aplicamos apropriadamente as regras de criação de três camadas, quando quisermos que a mesma funcione, por exemplo com SQL Server, não deveríamos alterar mais do que a base de dados, a camada cliente ficaria intacta e, a camada de regras de negócios sofreria, talvez, uma alteração muito superficial. A figura abaixo nos mostra o conceito do funcionamento desta arquitetura.



Como podemos ver, esta arquitetura nos permite fazer que tanto a interface de usuário, as regras de negócios e a base de dados se converteram em entidades separadas umas das outras, o importante é manter bem definidas as interfaces e o que cada uma delas fazem para se comunicar com a outra.

Atualmente já nos encontramos falando em desenvolver aplicações em n camadas, a que temos de mais comum é a de quatro camadas, a camada adicionada é a que separa definitivamente as regras de negócio da de acesso a dados.

Esta arquitetura nos dá a vantagem de isolar definitivamente nossa lógica de negócios de tudo que tenha a ver com a origem de dados, já que desde o manejo da conexão até a execução de uma consulta manipulará a camada de acesso a dados. Deste modo, ante a qualquer eventual alteração, só se deverá tocar no módulo específico, assim como o momento de planejar a escabilidade de nosso sistema, se tivermos respeitado as regras básicas de projeto não deveríamos nos deparar com grandes modificações.



A importância desta arquitetura

Existem muitas razões para utilizar o desenvolvimento de aplicações em arquitetura de n camadas.

Abstração total sobre a origem dos dados As diferentes camadas se especializam absolutamente na função que devem fazer (processamento nas regras de negócio ou apresentação de dados na camada cliente) sem importar qual é a origem dos dados processados.

Baixo custo de desenvolvimento e manutenção das aplicações Se bem que no momento de projetar podemos observar uma carga maior de complexidade, a utilização desta arquitetura nos dá um controle maior de cada componente, assim como também a possibilidade de uma verdadeira reutilização do código. Por exemplo: Se tivéssemos em nossas regras de negócios uma função que nos mostre um resumo de conta de nossos clientes quando um usuário de nossa aplicação Win32, quando a camada cliente chamar este módulo executará a função MostrarListaConta() para ver o detalhe em seu monitor; mas se o desenvolvedor do site web da empresa no momento de montar a página de consulta nos pede isso, lhe diremos simplesmente que carregue o componente de regras de negócios e execute MostrarListaConta() Como podemos ver este é um exemplo concreto, já que mediante a utilização desta arquitetura, o desenvolvedor de uma interface de usuário jamais chegará a manipular diretamente um dado em nosso servidor a não ser através de um componente

Padronização das regras de negócio As regras de negócio se encontram encapsuladas em um set de rotinas comuns e podem ser chamadas de diversas aplicações sem necessidade de saber como esta funciona ou foi projetada Por exemplo: Suponhamos que uma das funções encapsuladas dentro de nossas regras de negócios se utilize para devolver os dados de um cliente. Nossa função DevolveCliente() aceitará como parâmetros o código do cliente e também processará nosso ID de usuário, então, depende de quem execute esta função será os dados que receberá como resposta. Se a execução for solicitada por um usário de baixo nível o retorno seria:

? DevuelveCliente("00002")

resultado :

Rodriguez, Alberto
Antibares 3372 6to C
Buenos Aires


Se for um usuário com um nível mais elevado poderia receber o seguinte:

? DevuelveCliente("00002")

resultado :

Rodriguez, Alberto
Antibares 3372 6to C
Buenos Aires
Saldo Conta : 120.00
Conta Inativa


Melhor qualidade nas aplicações Como as aplicações são construídas em unidades separadas, estas podem ser testadas independentemente e com muito mais precisão, isto permite obter um produto bem mais sólido

Reutilização de código A concepção natural de um sistema desenvolvido nesta arquitetura promove a reutilização de seus componentes em várias partes do próprio desenvolvimento e de futuros sistemas

Escabilidade Utilizando serviços como MTS muitos objetos podem escalar e ser distribuidos em um ambiente transacional de alta segurança

Os componentes

Antes de entrar em um desenvolvimento de um componente, primeiro devemos ter um conhecimento claro do que é isso.

Um componente é um objeto que pode instanciar, e como todo objeto, deve cumprir com as condições básicas do objeto (Abstração, Encapsulamento, Herança e Polimorfismo), deve ter muito bem definidos propriedades, métodos e eventos que vão expor e é muito importante destacar que estes devem funcionar livre de estado.

Bom, depois disto, deixamos um pouco de lado a teoria e ................. ao código!!

Para começar, planejei o desenvolvimento de um pequeno sistema que através de componentes acessa dados de um cliente e mostra os dados de sua conta tal como havíamos projetado anteriormente

Para seguir em frente este teste precisamos de uma tabela denominada CLIENTE com a seguinte estrutura:
CampoTipoTamanho
IdCliente C 5
ApNombre C 50
limCredito N 5


e outra denominada EstadoCuenta com os seguintes campos:

CampoTipoTamanho
IdCliente C 5
SaldoCuenta N 5


Com esta estrutura de dados vamos criar um componente que, mediante o envio por nossa parte de código de cliente, processe os dados necessários para nos retornar o nome do cliente e mostrar-nos o estado de sua conta

Vamos ter dois componentes, um chamado CapaNegocios que terá as regras de negócios e será a interface de comunicação entre a camada cliente e a de dados. O segundo componente, chamado CapaDatos terá a capacidade de conectar-se a origem de dados e dará o retorno a CapaNegocios

Teremos ainda nossa interface cliente, que constará simplesmente de dois formulários, um com a lista de clientes e outro que, ao escolher o cliente da lista nos mostrará o estado da conta do mesmo. Esta camada cliente desenvolveremos em Visual Fox Pro e também em Visual Basic, para deste modo ter um claro exemplo de como um componente desenvolvido em VFP pode ser reutilizado a partir de qualquer linguagem de desenvolvimento.

Ainda no exemplo, vamos consultar duas origens de dados diferentes, uma será uma base nativa em VFP e outra em Access.

Estão ................... ao código

Nossa interface de usuário desenvolvida em VFP será a seguinte: Criamos um projeto chamado CapasEnVFP

Adicionamos um formulário chamado Clientes, com as seguintes propriedades:

PropriedadeValor
Autocenter .T.
Caption Clientes
Height 325
Width 530


Este formulário conta ainda com um método chamado processa, que contém o seguinte código:

PARAMETERS Lista

Lista.movefirst

DO WHILE ! Lista.eof()
Thisform.list1.AddItem(lista.fields("idcliente").value +SPACE(5)+ ;
lista.fields("apnombre").value, VAL(lista.fields("idcliente").value))
Lista.movenext
Enddo


Este método, mediante a recepção de um RecordSet de ADO como parâmetro, chama a lista que contém o formulário. O formulário em questão tem 3 objetos, um ListBox e dois CommandButtons

Propriedades do ListBox

PropriedadeValor
Height200
Left50
NameList1
Top35
Width430


Propriedades do Botão 1

PropriedadeValor
CaptionCarga Lista
Height40
Left50
NameCommand1
Top265
Width160


Evento clik deste botão contém o seguinte código:

oCapaNegocios=CREATEOBJECT("capanegocios.capanegocios")
miRecordset = oCapaNegocios.ListaClientes()
thisform.procesa( miRecordset )
Thisform.Refresh


Propriedades do Botão 2

PropriedadeValor
CaptionVer Estado Cta.
Height40
Left324
NameCommand2
Top265
Width160


Evento clik deste botão contém o seguinte código:

miCliente = PADL(thisform.list1.ListIndex, 5, "0")
DO FORM MuestraEstado WITH miCliente


Exemplo como deveria ficar o formulário Clientes



Agora adicionaremos o segundo formulário chamado MuestraEstado para mostrar o estado da conta do cliente selecionado na lista:

Este formulário contém 7 objetos, 4 labels e 3 textbox. As propriedades do formulário são as seguintes:

PropriedadeValor
CaptionEstado de Cuenta
Height230
Left285
Top180
Width470
WindowType1 - Modal


O evento INIT deste formulário conterá o seguinte código:

PARAMETERS Cliente

oCliente = CREATEOBJECT("capanegocios.capanegocios")
miRecord = oCliente.ConsultaEstadoCuenta( Cliente )

Thisform.text1.Value = miRecord.fields("idcliente").value
Thisform.text2.Value = miRecord.fields("apnombre").value
Thisform.text3.Value = miRecord.fields("saldocuenta").value

IF miRecord.fields("saldocuenta").value < miRecord.fields("limcredito").value
Thisform.label4.Caption = "Cuenta Habilitada !"
else
Thisform.label4.Caption = "Cuenta Inhabilitada !"
Endif

** Este indica o nivel de cliente que está usando o sistema
ClienteNivel = 100
IF ClienteNivel < 50
Thisform.text3.Visible = .f.
Thisform.label4.Visible = .f.
ELSE
Thisform.text3.Visible = .t.
Thisform.label4.Visible = .t.
Endif
Thisform.Refresh


Propriedades de LABEL1

PropriedadeValor
Autosize.T.
CaptionCódigo Cliente :
Left36
NameLabel1
Top36


Propriedades de LABEL2

PropriedadeValor
Autosize.T.
CaptionDenominación :
Left36
NameLabel2
Top72


Propriedades de LABEL3

PropriedadeValor
Autosize.T.
CaptionSaldo Cuenta :
Left36
NameLabel3
Top108


Propriedades de LABEL4

PropriedadeValor
Autosize.T.
BackStyle0 - Transparent
CaptionEstado de Cuenta
FontSize25
Height41
Left96
NameLabel4
Top168
Width251


Os 3 Textbox do formulários terão a propriedade Enabled = .f. . O formulário deverá estar da seguinte forma:



Isso é o bastante para a camada cliente, agora passaremos ao objeto de regras de negócios

Criaremos um projeto chamado CapaNegocios ao qual adicionaremos um arquivo PRG com o seguinte código

DEFINE CLASS CapaNegocios as Session OlePublic

Procedure ListaClientes() as ADODB.Recordset

oCapaDatos = CREATEOBJECT("capadatos.capadatos")
oCapaDatos.Conectar()

miListaClientes = oCapaDatos.CargaLista()

RETURN MiListaClientes

EndProc

Procedure ConsultaEstadoCuenta( miCliente as String ) as adodb.Recordset

oCapaDatos = CREATEOBJECT("capadatos.capadatos")
oCapaDatos.Conectar()

miRecord = oCapaDatos.EstadoCuenta( miCliente )

RETURN miRecord
EndProc
EndDefine


Como observamos no código, este componente executará dois procedimentos, o primeiro com nome Listaclientes, é o que nos devolve um RecordSet de ADO com a lista de clientes, através do chamado a CargaLista da camada de Acesso a dados o qual será processado pelo método processa do formulário Clientes para carregar o ListBox com a lista de clientes.

O segundo procedimento se denomina ConsultaEstadoCuenta que executa o método EstadoCuenta da camada de dados, devolvendo um registro com os dados referentes ao código da conta que enviou a chamada da função. Uma vez criado este código em um PRG gravamos com o nome de CapaNegocios.prg e procedemos a criação do componente .DLL conforme a figura.



Vamos agora ao componente de acesso a dados.

Criamos um projeto chamado CapaDatos ao qual adicionaremos um arquivo .PRG com o seguinte código:

DEFINE CLASS CapaDatos as Session OlePublic

PROTECTED miConeccion
miConeccion = ""

Procedure Conectar

oConeccion = CREATEOBJECT("adodb.connection")
oConeccion.Open("Provider=VFPOLEDB.1;Data Source="+;
D:\Universal Thread\Ejemplo\Ejemplo.dbc;Password='';Collating Sequence=MACHINE")

This.miConeccion = oConeccion

EndProc

Procedure CargaLista() as ADODB.Recordset

oRecordset=CREATEOBJECT("adodb.recordset")
oRecordset.Open("SELECT idCliente, Apnombre;
from Cliente", This.miConeccion)

RETURN oRecordset

EndProc

Procedure EstadoCuenta( miCliente as String ) as ADODB.Recordset

oRecordCta=CREATEOBJECT("adodb.recordset")
oRecordCta.Open("SELECT Cliente.idcliente, Cliente.apnombre,;
Cliente.limcredito, EstadoCuenta.saldocuenta;
from Cliente, EstadoCuenta;
Where Cliente.idCliente = '"+micliente+"';
and Cliente.idCliente = EstadoCuenta.idCliente",;
This.miConeccion)

RETURN oRecordCta

EndProc
ENDDEFINE


Feito isso gravamos o arquivo com o nome CapaDatos.prg e procederemos a criação do componente .DLL conforme mostra a figura:



Agora, tranquilamente podemos pegar o projeto CapasEnVFP e executá-lo. Damos um click sobre o botão "Cargar Lista", escolhemos um cliente e clicamos o botão "Ver Estado Cta." e deverá dar o resultado similar ao que vemos abaixo:

Figura do sistema em funcionamento:



O uso de nosso componente em Visual Basic

Agora vamos ver que fácil é criar uma interface de cliente desde qualquer outra linguagem de programação para acessar nossa origem de dados mediante o uso de nossos componentes criados em VFP. Para isso, vamos criar um projeto em Visual Basic (muito fácil) que faça o mesmo que nosso projeto CapasEnVFP criado em VFP

Vamos lá !!!

Abrimos o Visual Basic e na tela New Project selecionamos a opção Standard EXE que chamaremos CapasConVFP tal como mostra a figura:



E ao formulário que aparece alí adicionamos 3 objetos, 2 botões de comando e um list box.

Ao Formulário daremos as seguintes propriedades

PropriedadeValor
NameClientes
CaptionClientes
Height5535
Left1890
ScaleMode1 - Twip
Top1500
Width6840


E adicionamos o seguinte código:

Na sessão General -> Declarations

Public oNegocio As capanegocios.capanegocios

Para o ListBox as seguintes propriedades:

PropriedadeValor
NameList1
Height3570
Left360
Top240
Width6015


As propriedades do Command 1 serão as seguintes:

PropriedadeValor
NameCommand1
CaptionCargar Lista
Height495
Left600
Top4200
Width2055


E adicionamos o seguinte código:

Private Sub Command1_Click()

Set oNegocio = New capanegocios.capanegocios
Call Cargalista

End Sub


Para o Command 2 as propriedades são:

PropriedadeValor
NameCommand2
CaptionConsultar Estado
Height495
Left3960
Top4200
Width2055


E adicionamos o seguinte código:

Private Sub Command2_Click()
MuestraEstado.Show
End Sub


Logo adicionamos um procedimento chamado CargaLista da seguinte maneira:

Private Sub Cargalista()
Set ListaClientes = oNegocio.ListaClientes
ListaClientes.MoveFirst
While Not ListaClientes.EOF

List1.AddItem ListaClientes!IdCliente & " " & ListaClientes!Apnombre
ListaClientes.MoveNext
Wend
End Sub


O formulário ficará da seguinte maneira:



A seguir procedemos a criação do segundo formulário para mostrar o estado das contas. O formulário terá 7 controles, 4 labels e 3 TextBox com as seguintes propriedades

Para o Formulário :

PropriedadeValor
NameMuestraEstado
CaptionEstado de Cuenta
Height4380
Left3810
ScaleMode1 - Twip
Top3390
Width7230


E adicionamos o seguinte código:

Na sesão General -> Declarations

Public oNegocio As capanegocios.capanegocios

No evento Load o seguinte código:

Private Sub Form_Load()
Dim sCod As String

sCod = Mid(Clientes.List1.Text, 1, 5)
Set oNegocio = New capanegocios.capanegocios
Set miCuenta = oNegocio.ConsultaEstadoCuenta(sCod)

MuestraEstado.Text1.Text = miCuenta!IdCliente
MuestraEstado.Text2.Text = miCuenta!Apnombre
MuestraEstado.Text3.Text = miCuenta!SaldoCuenta

If miCuenta!SaldoCuenta > miCuenta!limcredito Then
MuestraEstado.Label4.Caption = "Cuenta Inhabilitada !"
Else
MuestraEstado.Label4.Caption = "Cuenta Habilitada !"
End If

End Sub


As propriedades para o Label 1 serão:

PropriedadeValor
NameLabel1
CaptionCódigo de Cliente :
Height255
Left240
Top650
Width1815


Para o Label 2 serão:

PropriedadeValor
NameLabel2
CaptionDenominación :
Height255
Left240
Top1350
Width1815


Para o Label 3 serão:

PropriedadeValor
NameLabel3
CaptionSaldo Cuenta :
Height255
Left240
Top2050
Width1815


Para o Label 4 serão:

PropriedadeValor
NameLabel4
CaptionEstado de Cuenta :
Height735
Left1680
Top2880
Width5175


Para o TextBox 1 :

PropriedadeValor
NameText1
Height375
Left2280
Top600
Width1815


Para o TextBox 2 :

PropriedadeValor
NameText2
Height375
Left2280
Top1300
Width4695


Para o TextBox 3 :

PropriedadeValor
NameText3
Height375
Left2280
Top375
Width2280


O formulário deverá estar da seguinte maneira:



Executamos a aplicação e se tudo funcionar corretamente teremos o seguinte resultado:



Como podemos observar, assim facilmente teremos uma aplicação Front-end feita em Visual Basic, acessando uma origem de dados absolutamente abstrata e através de nossos componentes criados em Visual Fox Pro.

Comprovamos a abstração da origem de dados ??????

Criemos uma BD em Access que tenha 2 tabelas com a mesma estrutura que mostra o BD de Fox e nomeamos de Access.mdb, digitamos alguns dados para testar e logo faremos o seguinte:

Pegamos o projeto VFP chamado CapaDatos, e no procedimento conectar trocamos a linha que contém:

oConeccion.Open("Provider=VFPOLEDB.1;Data Source="+;
D:\Universal Thread\Ejemplo\Ejemplo.dbc;Password='';Collating Sequence=MACHINE")


Pela seguinte:

oConeccion.Open("Provider=Microsoft.Jet.OLEDB.4.0;Data Source="+;
D:\Universal Thread\Ejemplo\Access.mdb;Persist Security Info=False")


Recompilamos a .DLL executemos os projetos e .......... que me contam ????

Até a próxima e espero que isto lhes tenha sido de muita utilidade.

Jorge A. Espinosa, Buenos Aires (Capital Federal), Argentina, é Analista Programador y MCP. Dedicado ao desenvolvimento de sistemas desktop desde o ano de 1987; sempre baseado em xBase e em Visual Fox Pro desde a versão 3.0. Hoje Gerente de sistema da Drogaria Sporiti SACIFA www.drogueria-saporiti.com.ar.

topo


   Última Atualização: 3 de Setembro de 2002
© 2003 Microsoft Corporation. Todos os direitos reservados. Nota Legal.