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.
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.
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.
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.
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.
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.
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.