SnapDataSet

Ligando seus objetos a componentes data-aware de forma RAD

Como já mencionei em outros artigos, quando desenvolvemos em OO, colocando nossa regra de negócio em classes temos a preocupação de como exibi-los de forma eficiente ao usuário, sem misturar lógica de negócio com camada de apresentação (Formulários, Grids, Edits, etc). Pensando nisso grandes mestres criaram alguns padrões de projeto para auxiliar nisso, como MVC (model-view-controller), MVP (model-view-presenter), MGM (model-GUI-mediator).

Implementar por completo cada padrão desse confesso que é uma tarefa árdua, porém muito recompensadora.

Ao considerarmos que se utilizássemos descendentes de TDataSet (TQuery, TIBQuery, etc) essa ligação já está pronta pelos componentes data-aware pensamos porque não podemos fazer o mesmo com nossos objetos?.

Não seria bom poder ligar um TDBEdit à uma propriedade "Nome" de uma classe qualquer ?

Estaríamos aproveitando o melhor dos dois mundos. No OO teríamos toda sua vantagem (reutilização, encapsulamento, etc) e no RAD poderíamos construir interfaces para os usuários de forma natural e rápida.

Com toda certeza Cosimo Demichele, um italiano, que me parece muito prático, criou o SnapDataSet. Esse pacote faz isso para nós! Ele atua como um mediador entre nossas classes e os componentes data-aware.

Se até hoje sua equipe de desenvolvimento pensou em utilizar OO, mas não pode por falta de um suporte RAD ao desenvolvimento de interfaces de usuário, essa é a hora de dar um passo além!

SnapDataSet

Ele pode ser baixado por aqui. É gratuito e vem acompanho com seus fontes. Após devido download pode ser instalado como qualquer outro pacote. Após sua instalação, dois novos componentes são criados em uma guia chamada Snap, veja Figura 1.

SnapDataSet
Figura 1. Pacote depois de instalado.

TSnapVirtualDataset

Este componente permite conectar qualquer fonte de dados ao componentes data-aware. Isso é feito através dos seguintes eventos:

OnGetDataCount permite especificar a quantidade de registros no dataset
OnGetDataValue permite que o dataset leia o valor de um TField o registro ativo
OnGetDataBlobValue como o anterior, porém especializado para Blobs
OnSetDataValue atualiza o valor de uma propriedade com o valor de um componente data-aware
OnSetDataValueBlob como o anterior, porém especializado para Blobs

Os demais dispensam explicações. Ocorrem em operações de adição de registros, exclusão, alteração e confirmação de registros. São eles:

  • OnAddData
  • OnCancelData
  • OnPostData
  • OnDeleteData

Mesmo se sua fonte de dados estiver implementada em um array ou um TList, suas informações poderão ser acessadas através de componentes data-aware.

TSnapObjectDataset

É nesse que vamos focalizar. Ele permite que propriedades de uma classes possam ser ligadas aos controles data-aware que conhecemos. Internamente ele cria um DataSet e o preenche, com seus devidos TFields, baseado em uma classe. Isso pode ser feito em tempo de execução ou durante projeto, visto que oferece um editor de próprio para realizar essa criação.

A única exigência para as classes que desejam se utilizam dos recursos do TSnapObjectDataset, é que suas propriedades devem estar publicadas, ou seja, na seção published da classe. Na Figura 2 vemos como ele mapeia os tipos primitivos para tipos de TField.

Mapeamento de tipos, realizado pelo TSnapObjectDataset
Figura 2. Mapeamento de tipos, realizado pelo TSnapObjectDataset.

Um outro detalhe importantíssimo é que o TSnapObjectDataset oferece suporte para relacionamentos do tipo Mestre-Detalhe.

Demonstração

Vamos fazer um pequeno exemplo para demonstrar o poder desse componente. Inicie um novo projeto no delphi, e em uma unit defina uma classe, TContato, e a implemente conforme Listagem 1.

Listagem 1. Classes para demonstração
TContato = class(TCollectionItem)

  private

    _email:string;

    _nome:string;

    procedure SetNome(val : string);

    procedure SetEmail(val : string);

    function GetNome : string;

    function GetEmail : string;

  published

    property Nome :  string read GetNome write SetNome;

    property Email :  string read GetEmail write SetEmail;

  end;

Construa o formulário principal da aplicação conforme Figura 3.

Formulário principal
Figura 3. Formulário principal.

Ligue o TDataSource inserido ao componente TSnapObjectDataset. É preciso agora adicionar o campos em nosso dataset. Para isso dê um clique duplo sobre o TSnapObjectDataset e seu Field Editor irá aparecer

Na lista Unit é listada as units que fazer parte do projeto e na lista Class as classes encontradas na unit escolhida. Após escolhida a classe, sua propriedade publicadas são exibidas. Devemos então selecionar as propriedades que desejamos que conste no Dataset, e clicar no OK.

Feito isso ligamos a propridade Dataset dos componentes data-aware para nosso Dataset. Com isso podemos até adicionar as colunas do DBGrid. Vamos carregar nosso exemplo com alguns objetos iniciais. Para isso crie um campo privado _listaContatos do tipo TCollection e um método chamado CarregaContatos.

Na Listagem 2 vemos a implementação do CarregaDados.

Listagem 2. Carregando objetos de demonstração.
procedure TPrincF.CarregaContatos;

var

 obj : TContato;

begin

  _listaContatos := TCollection.Create(TContato);

  obj:= _listaContatos.Add as TContato;

  obj.Nome := 'Paulo';

  obj.Email := 'pauloquicoli@gmail.com';

 

  obj:= _listaContatos.Add as TContato;

  obj.Nome := 'Carla';

  obj.Email := 'carla@gmail.com';

 

  obj:= _listaContatos.Add as TContato;

  obj.Nome := 'Livia';

  obj.Email := 'livia@gmail.com';

 

  ObjectDataset.ObjectInstance := _listaContatos;

end;

Implementado o método, no evento onshow do formulário principal vamos chama-lo e abrir o dataset, conforme Listagem 3.

Listagem 3. Método OnShow.
procedure TPrincF.FormShow(Sender: TObject);

begin

  CarregaContatos;

  ObjectDataset.Open;

end;

Agora é só executar o aplicativo e ver que nossos objetos são acessados por componentes data-aware.

Conclusão

Apresentei uma alternativa para quem deseja começar com OO e ser prático nas interfaces com usuário.