Abstração de Acesso a Dados e Orientação a Objetos – Parte 05

Introdução

No post anterior (Abstração de Acesso a Dados e Orientação a Objetos – Parte 04), foram implementadas algumas opções de exportação de tabelas, para os objetos ZDBFFILE e ZMEMFILE. Enquanto isso, foi implementado na classe ZISAMFILE a importação dos formatos SDF e CSV. Agora, para compatibilizar alguns recursos do AdvPL já existentes com estas classes, vamos partir para as novas classes ZTOPFILE e ZQUERYFILE.

Classe ZQUERYFILE

Quando queremos um result-set de uma Query em AdvPL, usamos a função TCGenQry() em conjunto com a função DBUseArea(), para abrir um cursor READ ONLY e FORWARD ONLY usando um ALIAS em AdvPL.

Embora todas as funções ISAM possam ser usadas em uma WorkArea aberta sob um ALIAS, para um cursor ou result-set de Query, aplicam-se apenas as seguintes funções:

  • DbSkip() — Avança um registro no cursor. Podemos especificar um número de registros positivo para avançar, mas nunca negativo. Lembre-se, cursor FORWARD ONLY.
  • DBGoTOP() — Se você ainda está no primeiro registro da Query, a função é ignorada. Se você já leu um ou mais registros, ou mesmo todos os registros da Query, como não tem como “voltar” registros, a função fecha e abre a query novamente no Banco de Dados, recuperando um novo result set. Logo, se no intervalo de tempo entre a primeira abertura do cursor e o DBGoTOP(), registros foram acrescentados ou tiveram algum campo alterado, a quantidade de registros retornada pela Query pode ser diferente.
  • TCSetField() — Se no banco de dados existem um campo “D” Data em AdvPL, ele é gravado e retornado pela Query como um campo “C” Caractere de 8 posições. Usando a função TCSetField() podemos informar ao Protheus que esta coluna deve ser retornada no campo do ALIAS j;a convertida para Data. O mesmo se aplica a precisão de campos numéricos, e a campos do tipo “L” lógico — que no Banco de Dados são gravados com um caractere “T” indicando verdadeiro ou “F” indicando falso.
  • DbCloseArea() — Fecha o alias da Query
  • FieldGet() — Recupera o valor de um campo da query pelo número do campo
  • DbSTruct() — Retorna o array com a definição dos campos retornados na Query.
  • FieldPos() — Retorna a posição de um campo na estrutura a partir do nome.

Quaisquer outras instruções são ignoradas, ou retornam algum tipo de erro. DBRLOCK() sempre retorna .F., pois um alias de Query é READ ONLY — Somente leitura. Nao é possível setar filtros, nem para registros deletados. O filtro de registros deletados deve ser uma condição escrita de forma literal na Query, usando o campo de controle D_E_L_E_T_ .

A ideia da classe ZQUERYFILE é encapsular o alias retornado da Query, e implementar as mesmas funcionalidades que um objeto de acesso a dados da ZLIB foram concebidos — como por exemplo o ZDBFFILE e o ZMEMFILE.

Desta forma, uma rotina escrita para trabalhar com um tipo de arquivo que herda desta classe ou que possui os métodos mínimos de navegação necessários possa utilizá-la também, onde colocamos um overhead mínimo apenas criando métodos para encapsular os acessos aos dados.

Classe ZTOPFILE

O DBAccess permite eu criar um arquivo em um banco relacional (SQL) homologado, e emular um acesso ISAM neste arquivo, como se ele fosse um arquivo DBF. Toda essa infra-estrutura já está pronta e operacional dentro do Protheus Server. O objetivo desta classe é fazer o mesmo encapsulamento de acesso feito pela ZQUERYFILE, porém implementando todas as funcionalidades disponíveis, como filtros e índices, além da navegação entre registros pela ordem de um índice.

Dentro da classe — que vai herdar a ZISAMFILE — implementamos os métodos para usar os recursos nativos, e alguns adicionais para permitir o uso de recursos implementados na ZLIB, como por exemplo o índice em memória do AdvPL — ZMEMINDEX.

Uso após a implementação

Alguns métodos das classes ZISAMFILE já foram concebidos para trabalhar nativamente com um objeto de dados, ou o ALIAS de uma WorkArea. A ideia de utilização do modelo de abstração é permitir flexibilizar a manutenção e persistência de dados — permanente ou temporária — usando instruções de alto nível, dentro de fronteiras e comportamentos pré-definidos para viabilizar escalabilidade, desempenho e resiliência para a aplicação.

Idéias e mais idéias

Quer ver uma coisa deveras interessante que pode ser feita com, esta infraestrutura ? Então, imagine um operador de sistema realizando por exemplo uma inclusão de dados com muitas informações, em um terminal com conexão síncrona, como o SmartClient. Em determinado momento, algo horrível aconteceu com a rede entre a estação (SmartClient) e o Servidor (Protheus Server) que ela estava conectada. Vamos ao pior cenário, houve um problema de Hardware (no servidor, na rede, na própria estação — acabou a luz. e o terminal em uso não têm No-Break. Adeus operação, dados já digitados, foi pro beleléu.

Bem, usando um cache — por exemplo o ZMEMCACHED — a aplicação poderia gravar no cache, em intervalos de tempo pré-definidos ou mesmo a cada informação significativa digitada, um registro com os dados já preenchidos até aquele momento, atrelado ao usuário que está realizando a operação ou a operação em si. No término da operação, esta informação é removida do cache. Caso o processo seja interrompido, no momento que o usuário fizer o login, ou quando ele entrar na rotina novamente na rotina, o programa verifica se tem alguma informação no cache daquele usuário, e em caso afirmativo, permita a informação ser recuperada, e o usuário conseguiria continuar a operação do ponto onde foi feito o último salvamento.

Para isso ser feito de forma simples, a operação deve ser capaz de serializar — representar em um formato armazenável e recuperável — o seu estado no momento, para tornar fácil a operação de salvamento e recuperação de estado. Para isso, poderemos usar — assim que estiver pronta — a classe ZSTREAM.

Com ela, a ideia é ser possível inclusive salvar não apenas valores, mas um objeto. Isso mesmo, pegar as propriedades de um objeto automaticamente e salvar o estado do objeto em um cache, no disco ou onde você quiser. Porém, para restaurar o estado do objeto, você deverá recria-lo, e fazer os métodos Save e Load nele, para ser possível ajustar as propriedades necessárias, lembrando que CodeBlock não dá para ser salvo e restaurado, o bloco de código pode depender de variáveis do ambiente e referências de onde ele foi criado.

Neste cenário, o mundo ideal seria criar uma classe apenas para ser um agrupador de propriedades e ser o container de contexto de dados de uma operação. Neste caso, poderíamos construir um método NEW() na estrutura, retornando self e populando as propriedades com seus valores default. e os métodos SAVE e LOAD para salvar ou recuperar o estado atual a partir de uma Binary String — ou Stream.

Conclusão

Quando começamos a encapsular recursos, realmente conseguimos reaproveitar muito código. Os exemplos dos posts anteriores de CRUD em AdvPL — usando SmartClient e AdvPL ASP — foram úteis para mostrar o que pode ser feito usando instruções básicas da linguagem AdvPL. Agora, com o agrupamento de algumas funcionalidades em um Framework (zLib), podemos reaproveitar código e implementar funcionalidades similares com menos esforço. As classes mencionadas acima ainda estão em desenvolvimento, e serão acompanhadas de novos posts assim que estiverem “prontas” para uso !!!

Agradeço novamente a audiência e lhes desejo TERABYTES DE SUCESSO !!!

 

 

2 comentários sobre “Abstração de Acesso a Dados e Orientação a Objetos – Parte 05

Deixe uma resposta para Júlio Wittwer Cancelar resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair /  Alterar )

Foto do Google

Você está comentando utilizando sua conta Google. Sair /  Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair /  Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair /  Alterar )

Conectando a %s