Buscar

Interface. mas agora o assunto é código!

nome

Ivo Nascimento

Colunista ainda sem descrição. Caro colunista, por favor envie-nos sua descrição.

    Tudo bom gente. Eu gostaria de agradecer a todo mundo que leu e também aos que comentaram meus artigos anteriores. Brigadão. Ta Valendo!
    Nos outros dois artigos eu vim dando uma introdução de formas de trabalho com interface que para mim têm funcionado durante estes últimos anos e procurei me manter na superfície do assunto (se é que me entendem).
    Agora eu começo a adentrar um pouco mais em modelos de código. Isso mesmo, digo modelos porque podem ser reaproveitados mesmo.
    Toda aplicação que conheço que tem por intuito ser funcional, preocupa-se com não só a sua funcionalidade para o usuário, mas também com a do programador, tentando evitar que ambos fiquem sofrendo ao trabalharem.
    Eu também me preocupo e por isso utilizo as seguintes "regras":

    1º - Sempre que acesso dados(Paradox ou PostgreSQL) utilizo query ou descendentes da mesma. No primeiro caso para evitar de forma clássica qualquer tipo de dado Piradox decorrente de uma operação errada que eu esqueci de tratar ou mesmo evitar corromper índices e no segundo por que é assim e pronto(e isso é muito bom).

    2º - Faço a interface saber o que pode e o que não pode ser feito com relação aos dados.(Se Ta editando não pode apagar. Se ta inserindo não pode apagar. Se ta editando não pode Inserir. Se ta fazendo qualquer destas coisas não pode imprimir algo re ferente àquela entidade de dados, etc)

    3º - Procuro manter não só a manipulação de dados como também os algorítimos específicos e genéricos reservados em um único local do aplicativo(isso as vezes complica mais o desenvolvimento, mas facilita em muito a manutenção) utilizando-me de uma unit e/ou uma dll(Quem usa também kylix e programa se preparando para as conversões utilizando a CLX deve procurar trabalhar mais com a unit . Sim, sabemos que existem os .so no kylix que fazem papel de dlls e quem trabalha no Linux sabe que dá pra usar o wine também).

    4º - Aplico o estilo do melhor código escrito de que tenho conhecimento: os das units do Delphi(gosto de, quando tenho um tempinho ler as uses da vida — windows, math, DBGrid, system).

    5º - Procuro sempre escrever um algorítimo deixando-o tão abstrato quanto possível para poder aplicar em outras situações e isso implica não referenciar instancias diretamente e usar RTTI, não fazer referencia a variáveis globais de outras units(assim posso usar a mesma unit em vários programas e tudo bem, sem adaptações e sem sofrimento) e me utilizar de declarações com out,var e const.

    6º - Procuro fazer com que as procedures e function manipulem algorítimos específicos dividindo o algoritmo principal em partes funcionais que podem também ser reaproveitadas.

    7º - Sabe aquela propriedade tag que todos os objetos descendentes de Tcomponent têm e que a gente costuma deixar abandonada, pois é. Eu uso.

    8º - Uso, mas sem exercitar a preguiça, o tratamento de exceções com blocos try...except/finally. Na maioria dos casos dá pra escapar dele.

    9º - Faço uso da especialização de componentes já existentes. Ex.: Criar um componentes descendente do Edit para entrada de semente numero ao invés de excrever sempre if not key in() then.

    10º - Utilizo-me do expediente de ligar pra minha namorada pra perguntar pra ela se é melhor escrever um case ou vários if e coisas assim. Brincadeiras a parte, toda vez que eu pergunto pra alguém se tal coisa fica melhor assim ou assado aparece na minha cabeça enquanto a pessoa discorre do problema um insight que se aplica melhor ao código do que "aquele troço que fazia aquilo lá que serve praquele coiso" que eu tinha escrito. Experimenta e você vai ver como funciona.
    OK. Vamos pegar o caso simples, mas clássico dos botões de inserção de dados que criamos no artigo anterior dentro daquele template de formulário que fizemos.
    Tínhamos os botões Incluir, editar, gravar, apagar, cancelar, imprimir.
    Vamos pensar nesses "caras".
    Quando eu clicar em inserir, provavelmente não vou querer que o código escrito no botão apagar possa ser executado(causando uma exceção). Tampouco vou querer imprimir um registro que ainda não gravei.
    O mesmo ocorre com o botão editar.
    Quando eu clicar em imprimir espero que o registro esteja gravado são e salvo e quando clicar em apagar espero poder apagar alguma coisa baseado numa referencia que exista no banco de dados, além, e claro, dá perguntinha: "Deseja realmente excluir esta informação Y?".
    Vamos adicionar aqui a ação de fechar o formulário que esta sendo utilizado. Seria meio triste tentar ficar lembrando se aquelas informações que digitei foram ou não gravadas antes de fechar o formulário(isso chama-se usabilidade/conforto para o usuário).
    Quando a gente começa a pensar no problema surgem muitas possibilidades de soluções, mas basicamente se resumem a ficar testando se for uma table if Table1.State = dsEdit then ... ou fazer a interface trabalhar.
    Uma das possibilidades é a seguinte:

Procedure Btns(op:boolean=true);

Begin
Incluir.enabled := not op;
Editar.enabled := not op;
Gravar.enabled : = op;
Apagar.enabled : = not op;
Cancelar.enabled : = not op;
Fechar.enabled := not op;
Imprimir.enabled:= not op;
End;

Mas esse código me trazia a necessidade de:

a)Copiar e colar código entre formulários ou declarar em todos os formulários o formulário a qual ele pertencia;
b) Lembrar o nome padrão dos botões e ter de chama-los sempre do mesmo nome em todos lugares;
c) Não era genérico. Só dava pra usar pra essa finalidade e pronto. Se eu quissese controlar o acesso a outros botões do formulário eu tinha que escrever algo parecido demais com isso e eu não sou muito fã de repetir codificação e depois, se precisar, ter de sair caçando suas referências com ctrl+F.

Então eu passei a escreve-lo assim.
Em uma unit à parte que chamo de Interface_Tools(gostaria de observar que neste ponto não vou criar um objeto seguindo todas as regras explicitas para POO devido a este ser um artigo ainda introdutório e pertencente a uma seqüência, posteriormente irei levar o código a seguir para dentro de um objeto, assim sendo, esta é uma unit simples e pura)unit Interface_Tools;

interface
uses Forms, controls;

type

//aqui defino que trabalharei com no máximo 30 componentes por vez.
Btns = set of 1..30;

procedure SetBtnAcess(Formulario: TForm ;Op:boolean; BtnsRef:Btns);

implementation

procedure SetBtnAcess(Formulario: TForm ;Op:boolean; BtnsRef:Btns);

var i:byte;

begin

for i:= 0 to Formulario.ComponentCount -1 do begin

if (Formulario.Components[i] is TwinControl) then

if (Formulario.Components[i] as TwinControl).Tag in BtnsRef then

(Formulario.Components[i] as TwinControl).Enabled := op;

end;
end;
end.

Declare esta unit no formulário utilizando ALT+F11 para este fim.
No código anterior a chamada à função que desabilitava os botões era simplesmente algo como:

procedure TForm1.btnmodificarClick(Sender: TObject);
begin
Btns(true);
// para habilitar alguns e desabilitar outros ao mesmo tempo.
end;

Mas tinha todos poréns que descrevi anteriormente.

Agora a chamada recebe mais parâmetros só que pode ser utilizada sem maiores problemas para qualquer conjunto de botões, ou melhor dizendo, qualquer objeto que em sua Hiearaquia de classes tenha TwinControl(Quase tudo que usamos em interface com usuários).

procedure TForm1.btnnovoClick(Sender: TObject);

begin
// os números 2 5 6 e 7 reference à numeração que inseri nas tags dos botões ou qualquer componente visual que desejo manipular.
SetBtnAcess(form1,false,[2,5,6,7]);
//Btns(true);

end;

   
Dessa forma eu pude criar um código que foi escrito somente uma vez e pode ser utilizado em todos os aplicativos que escrevo. Com pouca modificação este código pode ficar puro OO e quando digo isso me refiro a encapsulamento de variáveis, procedimentos e funções. Geração de instância(se for desejável).

Explicações:

    Ao utilizar os operadores is e as trabalhei com RTTI baseando-me na premissa de que componentes Delphi conhecem sua classe progenitora.

    Utilizei TwinControl par poder manipular exclusivamente a propriedade enabled que era o que interessava neste exemplo e poderia ter utilizado a mesma idéia principal para trabalhar operações em lote sobre tables por exemplo. Se fosse o caso poderia ser testada apenas uma classe Como If (...is Tedit) then (... as Tdit).text. O is me poupou do código entre um try except.

    A utilização de set(conjuntos ordinais de dados) é amplamente utilizada no Delphi em suas classes internas e constituem uma ótima forma de organizar informações e deixar o código tão legível quanto um bom romance. Basta utiliza-los com racionalidade suficiente que podem até servir como forma de acesso a informações de alguma forma persistentes na aplicação e pesquisadas de algum SGDBR, substituindo assim expressões longas como

    If (DataModule. Table1.field[‘Campo’].asinteger = 10) or (DataModule. Table1.field[‘Campo’].asinteger = 15) or (DataModule. Table1.field[‘Campo’].asinteger = 20) then

Por

If (DataModule. Table1.field[‘Campo’].asinteger = 10) in SET101520 then...

    Conforme pode-se observar, uma classe unicamente para esta função parece um desperdício de tempo e, de qualquer forma não consegui escapar de ter de declarar na uses algum outro tipo de dado(pense assim: "Como posso reduzir o tamanho dos executáveis de meus aplicativos?" ao invés de deixa-los inchados. A internet esta ai né. Oito Mb é muito pra ficar atualizando um desktop remotament em cada modificação...). Logo, esta classe que criei, para poder se justificar, deve conter muito mais operações como esta e fazer com que eu saiba exatamente como e onde modificar meu código, evitando CRTL+F.
    Este é um exemplo simples de uso de RTTI e para criar códigos enxutos.
    Este modelo é extensível também, se a gente viajar(como gosto de dizer), num modelo de controle de acesso de ações nos formulários.
    Vocês conhecem a TactionList, pois é, as ações também tem a sagrada propriedade Tag.
    Todo tipo de operações, acessos e propriedades podem ser controladas por uma idéia aprimorada deste código.

    Novamente obrigado pessoal.
    No próximo artigo falarei mais sobre Interface, adentrando cada vez mais em algoritmos nos quais vejo algum tipo de utilidade pública, a série continua e o foco no próximo é a primeira regra da lista que apresentei aqui sendo criada se trabalhando com Dlls.

    Até mais.

Publicidade

Vote no artigo




Quantidade de votos: 1 voto
Aceitação: 80%


Detalhes do artigo

Categoria: Outros
Adicionado dia: 22/07/04
Por: Ivo Nascimento
Visualizado: 20354 vezes

Planeta Delphi - Tudo sobre programação Delphi Planeta Delphi - www.planetadelphi.com.br - Todos os direitos reservados | Copyright 2001-2009