Fórum Classes em Delphi #377438
12/05/2010
0
unit uValidar;
interface
uses
Windows, SysUtils, Forms, Classes, Controls;
type
TValidar = class
private
FGravar: Boolean;
function getGravar:Boolean;
public
function Data(Data: String; ShowMsg: Boolean; Menssagem: String; Componente: TObject = nil): Boolean;
function CampoObrigatorio(Campo: String; ShowMsg: Boolean; Menssagem: String; Componente: TObject = nil): Boolean;
property Gravar: Boolean read getGravar;
constructor Create;
end;
implementation
{ TValidar }
// *****************************************************************************
// Função para validaçáo de campo obrigatório
// *****************************************************************************
function TValidar.CampoObrigatorio(Campo: String; ShowMsg: Boolean;
Menssagem: String; Componente: TObject): Boolean;
begin
if Campo = '' then
begin
FGravar:= false;
Result := false;
if (Componente is TWinControl) then
TWinControl(Componente).SetFocus;
if ShowMsg then
Application.MessageBox(Pchar(Menssagem), 'Atenção',MB_ICONINFORMATION + MB_OK);
end
else
Result:=True;
end;
// *****************************************************************************
// Constructor para inicialização da variável FGravar
// *****************************************************************************
constructor TValidar.Create;
begin
FGravar := True;
end;
// *****************************************************************************
// Função para validaçáo de datas
// *****************************************************************************
function TValidar.Data(Data: String; ShowMsg: Boolean; Menssagem: String; Componente: TObject = nil): Boolean;
var
Aux: TDateTime;
begin
if (TryStrToDate(Data,Aux))then
begin
Result := True
end
else
begin
Result := False;
FGravar := False;
if (Componente is TWinControl) then
TWinControl(Componente).SetFocus;
if ShowMsg = True then
Application.MessageBox(Pchar(Menssagem), 'Atenção',MB_ICONINFORMATION + MB_OK);
end;
end;
// *****************************************************************************
// Função para ler a variável FGravar
// *****************************************************************************
function TValidar.getGravar: Boolean;
begin
Result := FGravar;
end;
end.
------------------------------------------------------------------------------------------------------------------------------
Abaixo a utilização:
procedure TForm1.Button1Click(Sender: TObject);
var
Validar : TValidar;
begin
Validar := TValidar.Create();
Validar.Data(Edit1.Text,true,'Data Inválida',Form1.Edit1);
if Validar.Gravar then
ShowMessage('Gravar')
else
ShowMessage('Não Gravar');
FreeAndNil(Validar);
end;
Desde já, muito Obrigado!
Walter Desidera
Curtir tópico
+ 0Post mais votado
12/05/2010
Eu fiz algumas melhorias que podem ser válidas, vc disse que ainda está começando...darei algumas dicas de melhorias..
Por exemplo....Eu percebi q essa classe TValidar, poder ter métodos estáticos...ou seja...vc não precisa instanciar a classe para ter acesso aos métodos....
Eu fiz algumas melhorias....
A classe ficaria assim...
Type TValidar = classpublic Class function Data(Data: String; ShowMsg: Boolean; Menssagem: String; Componente: TObject = nil): Boolean;//Método estático. Class function CampoObrigatorio(Campo: String; ShowMsg: Boolean; Menssagem: String; Componente: TObject = nil): Boolean;//Método estático. constructor Create; end;
a implementação da classe ficaria assim..
{ TValidar }
// *****************************************************************************// Função para validaçáo de campo obrigatório// *****************************************************************************
Class function TValidar.CampoObrigatorio(Campo: String; ShowMsg: Boolean; Menssagem: String; Componente: TObject): Boolean;
begin
if Campo = '' then
begin
Result := false;
if (Componente is TWinControl) then
TWinControl(Componente).SetFocus;
if ShowMsg then
Application.MessageBox(Pchar(Menssagem), 'Atenção',MB_ICONINFORMATION + MB_OK);
end
else
Result:=True;
end;
// *****************************************************************************// Constructor para inicialização da variável FGravar// *****************************************************************************
constructor TValidar.Create;
begin
Inherited Create(); //Chama o método Create da super Classe, no caso, TObject.//FGravar := True;
end;
// *****************************************************************************// Função para validaçáo de datas// *****************************************************************************
Class function TValidar.Data(Data: String; ShowMsg: Boolean; Menssagem: String; Componente: TObject = nil): Boolean;
varAux: TDateTime;
begin
if (TryStrToDate(Data,Aux))then
begin
Result := True
end
else
begin
Result := False;
if (Componente is TWinControl) then
TWinControl(Componente).SetFocus;
if ShowMsg = True then
Application.MessageBox(Pchar(Menssagem), 'Atenção',MB_ICONINFORMATION + MB_OK);
end;
end;
E um exemplo de uso...seria assim..
procedure TForm1.Button1Click(Sender: TObject);
begin
if TValidar.Data(Edit1.Text,true,'Data Inválida',Form1.Edit1) then //Como disse, não precisa instanciar a classe, basta chamar o NomeDaClasse.NomeMétodo.
ShowMessage('Gravar')
else
ShowMessage('Não Gravar');
end;
end.
Mts vezes usar métodos estáticos tbm resolvem nossos problemas....
Espero ter ajudado....flw
Raimundo Melo
Gostei + 2
Mais Posts
12/05/2010
Marco Salles
são vários pontos que apesar da simplicidade da classe pode ser atacado para futuras referencias
por exemplo
vc passa um Componente , para que ele receba o foco
function TValidar.CampoObrigatorio(Campo: String; ShowMsg: Boolean; Menssagem: String; Componente: TObject): Boolean;
e na implementação do método vc usa o operador Is e seguidamente vc usa o Operador as
A pergunta que lhe faço é ... Pq ao inves de usar o Componente: TObject pq não vc define
Componente: TWincontrol . Assim vc não precisa fazer esta conversão
Uma outra duvida que eu tenho é vc definir uma propriedade cujo controle depende de outros métodos
Por exemplo , algumem que utiliza a sua classe executar
procedure TForm1.Button1Click(Sender: TObject);
var
validar:TValidar;
begin
validar:=TValidar.Create;
try
if validar.Gravar then
Showmessage('Grava ou Não ???')
else
Showmessage('Pq não Grava');
finally
validar.Free;
end;
end;
meio sem sentido isto, mas é o que vc fez...
Gostei + 1
13/05/2010
Walter Desidera
pouco do seu tempo para me ajudar... Ainda estou começando... Bem vocês me
deram boas idéias para melhorar a minha classe... Mais a idéia que eu tinha
para esta classe é um pouco diferente da de vocês...
Bem seria assim:
Uma classe que fornece métodos para validação em uma tela de cadastro por
exemplo:
Crio uma instancia e chamo um método qualquer dela, por exemplo:
Validar.Data(Edit1.Text,true,'Data Inválida',Form1.Edit1);
Esta função devolve um booleano para uma propriedade Gravar, em seguida no
final do código eu apenas testo se essa variável continua True e só assim
efetuo as alterações no banco. Sendo que a property Gravar é Read Only, só os
métodos internos da classe podem alterar e usar este valor...
Programei desta forma porque não queria ficar fazendo if's na implementação dos
métodos; ficando desta forma:
procedure TForm1.Button1Click(Sender: TObject); var Validar : TValidar; begin Validar := TValidar.Create();
Com métodos estáticos eu tenho que testar com if's se deu certo ou não, com a
property eu não preciso porque ela q verifica se eu posso ou não gravar
as alterações, já que esse valor é retornado a ela quando a função é chamada.
Desse modo posso validar vários campos de uma vez...
Validar.Data(Edit1.Text,true,'Data de Nascimento Inválida',Form1.Edit1); </span>
Validar.Data(Edit2.Text,true,'Data de Cadastro Inválida',Form1.Edit2);
Validar.Data(Edit3.Text,true,'Data LALALA Inválida',Form1.Edit3);
Validar.Data(Edit4.Text,true,'Data BLABLABLA Inválida',Form1.Edit4);
Validar.Data(Edit5.Text,true,'Data TATATA Inválida',Form1.Edit5);</span>
if Validar.Gravar then
ShowMessage('Gravar')
Aqui usei um exemplo de um método simples, não vou chamar nenhuma menssagem aqui,
seria por exemplo um inherited de uma operação de post, caso a
property gravar ainda fosse verdadeira...
FreeAndNil(Validar);
end;
Marco você está certo, usar TObject foi um erro, na verdade eu realmente devo
usar TWinControl direto no lugar...
Mais um erro que eu cometi... não crie uma função para abortar caso a property
Gravar seja False, em cada método deveria ter colocado o seguinte código no
inicio:
if Gravar = False then exit else //Código a Validar
Assim se uma validação desse errado eu já nem verificaria os outros campos,
evitando várias mensagens uma atrás da outra...
Bem a principio eu realmente queria simplificar ao máximo o uso da classe, por
isso a property gravar também é opcional, é só é usada quando valido vários
campo de uma só vez.. O componente passado como parâmetro também, porque eu
posso validar um valor do banco ou variável que não esteja associada a um
componente...
Bom pessoal, muito obrigado pela ajuda, gostaria de saber se esta minha idéia foi
mal formulada, mais como eu disse anteriormente estou aprendendo... Qualquer
ajuda é muito bem vinda ;)
Gostei + 0
13/05/2010
Marco Salles
Vamos concatenas as Idéas..
Entendi sua intenção..
Esta função devolve um booleano para uma propriedade Gravar, em seguida no final do código eu apenas testo se essa variável continua True e só assim efetuo as alterações no banco. Sendo que a property Gravar é Read Only, só os métodos internos da classe podem alterar e usar este valor...
Mas é muito estranho esta property estar aclopada a outros métodos , além do mais seu raciocineo esta
Errado .. Tente acompanhar
Com métodos estáticos eu tenho que testar com if's se deu certo ou não, com a property eu não preciso porque ela q verifica se eu posso ou não gravar as alterações, já que esse valor é retornado a ela quando a função é chamada. Desse modo posso validar vários campos de uma vez...
Validar.Data(Edit1.Text,true,'Data de Nascimento Inválida',Form1.Edit1); //1
Validar.Data(Edit2.Text,true,'Data de Cadastro Inválida',Form1.Edit2); //2
Validar.Data(Edit3.Text,true,'Data LALALA Inválida',Form1.Edit3); //3
Validar.Data(Edit4.Text,true,'Data BLABLABLA Inválida',Form1.Edit4); //4
Validar.Data(Edit5.Text,true,'Data TATATA Inválida',Form1.Edit5); //45
if Validar.Gravar then
ShowMessage('Gravar')
Suponha que os passos //1 , //2 , //3 , //4 sejam todos Falsos.. Porém o passo //5 Esta tudo Certo
O que que vai acontecer ??? a Propery vai ser True e Vc estar Gravando ... Entende Isto ???
Mesmo que vc Utilize Exit , vc não impede o Compilador de executar as Instruçoes Seguintes
E qual a saida ????
Bem , eu sugiro uma mais orientada a objetos do que este aclopamanento que vc esta fazendo
A Idéia e que ao inves de function estes métodos sejam Procedures e que ao Inves de Retornar
Um boolean , devolvam uma Exceção Não Tratada .. Vc mesmo na sua classe Pode definir uma Exceção
Especifica.. < Ai é uma outra dica Boa e fica o codigobem mais legivel
Ai Vc Varia
try
Validar.Data(Edit1.Text,true,'Data de Nascimento Inválida',Form1.Edit1); //1
Validar.Data(Edit2.Text,true,'Data de Cadastro Inválida',Form1.Edit2); //2
Validar.Data(Edit3.Text,true,'Data LALALA Inválida',Form1.Edit3); //3
Validar.Data(Edit4.Text,true,'Data BLABLABLA Inválida',Form1.Edit4); //4
Validar.Data(Edit5.Text,true,'Data TATATA Inválida',Form1.Edit5); //45
ShowMessage('Gravar')
except
On e:SUAEXCECAO do
begin
ShowMessage('Não foi possivel Gravar')
end;
No fim , gosto muito do método de classes aonde não precisa instanciar a classe , conforme ja foi comentado antes
Gostei + 0
13/05/2010
Walter Desidera
Neste caso minhas funções não retornam uma Boolean e sim
Procedures com uma Exception (vou pesquisar como fazer isso para tentar fazer
um teste aqui...que eu me lembre era algo como "Raise")
Em suma eu estaria levantando uma Exception caso uma das validações não fosse verdadeira,
caso ela fosse gerada anularia as verificações seguintes definidas dentro do
bloco try...except.
Como as mensagens de erro são tratadas por procedimentos, eu
posso simplesmente não fazer nada quando a exception for levantada, usando ela
apenas para abortar a execução do bloco try...except. Quando ocorresse
qualquer erro na validação, ele nunca chegaria ao método de gravação dos dados,
correto?
EDITADO:
Dei uma olhada e vi que poderia usar uma exception silenciosa sem o Dialog do tipo EAbort:
raise EAbort.Create('Data Inválida');
Assim ainda posso usar um MessageBox normalmente que eu usava para mostrar um erro customizado ao usuário...vou fazer mais alguns testes aqui...
Gostei + 0
13/05/2010
Marco Salles
Gostei + 0
13/05/2010
Walter Desidera
Então sobre a responsabilidade única da classe, seria para simplificar o código e eliminar as dependências e acoplamentos de várias funcionalidades para uma mesma classe. Cada classe desempenha um único papel...
Mais uma coisa que estive pensando... Quando defino uma class function ou class procedure eu automaticamente reservei memória as qualquer variáveis que eu venha a usar dentro de minhas funções implementadas na classe, ou seja, automaticamente estou usando memória mesmo que eu não chame nenhuma função da classe...
Seria como uma variável global no Form principal, sempre alocada para uso mesmo que eu não esteja usando...
Se a classe não for estática, essa memória não é reservada, pois seus métodos não estão disponíveis diretamente, a memória só irá ser alocada caso eu crie um objeto desta classe...
Estou certo???
Gostei + 0
14/05/2010
Marco Salles
Entendi, seria uma exception customizada própria da classe... vou ter que dar uma olhada nisso...
Isto mesmo
Então sobre a responsabilidade única da classe, seria para simplificar o código....
Cada classe desempenha um único papel...
Isto é um conceito de POO ... Se vc sabe para que serve os bolinhos da classe e se esses bolinhos
estão saindo quimados , então vc modifica , altera , enfim da manuntenção em um lugar especidico
no programa .. E por ai vai todo o conceito de reusabilidade , manuntenção etc e coisa e tal
Mais uma coisa que estive pensando... Quando defino uma class function ou class procedure eu automaticamente reservei memória as qualquer variáveis que eu venha a usar dentro de minhas funções implementadas na classe, ou seja, automaticamente estou usando memória mesmo que eu não chame nenhuma função da classe...
Bem , não tenho conhecimento para dizer que sim nen dizer que não . As biografias que ja li a respeito de
métodos de classe não levantaram nenhuma informação de como é feito este gerenciamento de
memoria no Delphi . O que ela dizem sçao em suma que um método de classe não é especico a nenhum Objeto
da Classe e sim a propria classe ( em outras palavras são metodos Aplicados a classe e não ao Objetos da classe)
Mas não confunda com metodos Estáticos que não tem nada a ver .. Inclusive Metodos de Classe podem Sofrer
Polimorfismo. Apesar de meio abstrato o exemplo abaixo , ele demostar Isto
type
TClasseBase = class
class procedure Mensagem(); virtual;
end;
TClassFilha = class(TClasseBase)
class procedure Mensagem(); Override;
end;
class procedure TClasseBase.Mensagem;
begin
showmessage('Classe Base');
end;
{ TClassFilha }
class procedure TClassFilha.Mensagem;
begin
//inherited;
Showmessage('Classe Filha')
end;
procedure TForm1.Button1Click(Sender: TObject);
var
obj:TClasseBase;
begin
obj:=TClassFilha.Create; //POLIMORFISMO
try
obj.Mensagem;
finally
obj.Free;
end;
end;
Seria ate interresante , definir dois programas com uma certa quantidade de métodos. Um Do modo Tradicional
e outro usando o Metodo de classe , de modo que todos esses metodos em ambos os casos fossem compilados
isto é , lolinhas azuis , ou seja em algum lugar do programa referencia-sse esses métodos. Gera-sse esses dois
executaveis e verificasse o Tamanho do mesmo ... Nunca fiz isto...
Gostei + 0
14/05/2010
Walter Desidera
o tipo dos métodos, acreditava que class methods, por exemplo, não usavam
override...
Sobre a exception eu, andei dando uma pesquisada eu eu teria que criar uma nova
classe descendente da classe Exception (<a href="http://cc.embarcadero.com/item/17819" target="_blank" title="EDN">http://cc.embarcadero.com/item/17819</a>),
para poder ter total liberdade para implementar as menssagens que gostaria que
fossem apresentada, ou seja minha classe TValidar só validariao campo,
TMinhaException faria a parte de tratar a exception.
Tambem achei um jeito de minha idéia anterior funcionar corretamente:
Como minha property FGravar era responssável por verificar se tudo tinha
ocorrido corretamente e então gravaria as informações ficando assim
Validar.Data(Edit1.Text,true,'Data de Nascimento Inválida',Form1.Edit1); //False Validar.Data(Edit2.Text,true,'Data de Cadastro Inválida',Form1.Edit2); //False Validar.Data(Edit3.Text,true,'Data LALALA Inválida',Form1.Edit3); //False Validar.Data(Edit4.Text,true,'Data BLABLABLA Inválida',Form1.Edit4); //False Validar.Data(Edit5.Text,true,'Data TATATA Inválida',Form1.Edit5); //True
Não tinha preparado mais já havia solucionado o problema que você tinha me informado
adicionando o Exit sim, pois:
Caso uma função retorne false para FGravar, as outras funções não vão
ser nem testadas, não tem como porque quando uma está errada a condição
Supomos:
Validar.Data(Edit1.Text,true,'Data de Nascimento Inválida',Form1.Edit1); //False
Retorna Fgravar como False...
No próximo método...
Validar.Data(Edit2.Text,true,'Data de Cadastro Inválida',Form1.Edit2);//True
Não importa se a validação vai dar true ou false, FGravar esta como False, uma
vez False ela não pode se True novamente, só quando uma nova instancia desta
classe for criada, pois a primeira coisa em cada método é verificar se FGravar
está em True para que ele possa validar o próximo campo...
Gravar = False then // Condição falsa, não verifica mais nenhum método a seguir destrói o objeto exit else //Código a Validar
A idéia de uma exception customizada ficaria mais orientada a objeto, mais a
implementação seria mais complexa e um pouco estranha, vamos ver assim:
try
Validar.Data(Edit1.Text,true,'Data de Nascimento Inválida',Form1.Edit1); //1
Validar.Data(Edit2.Text,true,'Data de Cadastro Inválida',Form1.Edit2); //2
ShowMessage('Gravar')
except
On e:SUAEXCECAO do
begin
ShowMessage('Não foi possível Gravar')
end;
Ou:
try Validar.Data(Edit1.Text,true,'Data de Nascimento Inválida',Form1.Edit1);
Levanta minmha exception e mostra o que aconteceu e vai direto para o bloco except do try... Mostra a mensagem ("data Inválida"), focus no objeto...
Validar.Data(Edit2.Text,true,'Data de Cadastro Inválida',Form1.Edit2);//2
ShowMessage('Gravar')
except
On e:SUAEXCECAO do
Quando eu entrasse no bloco except do try, aqui não faria simplesmente nada, já
que quando a exception foi levantada ela já tratou o erro, achei que ficou mais
estranho assim...
O Try e uma exception customizada eliminam minha property FGravar, mais ele faz
o mesmo trabalho, ocorreu uma exception, a exception impede a continuidade da
validação e processo de gravação é abortado...
(Não tem nada a ver com o que eu estou fazendo aqui mais achei muito interessante http://www.delphi3000.com/articles/article_3308.asp)
Gostei + 0
14/05/2010
Marco Salles
Sobre a exception eu, andei dando uma pesquisada eu eu teria que criar uma nova classe descendente da classe Exception (http://cc.embarcadero.com/item/17819), para poder ter total liberdade para implementar as menssagens que gostaria que fossem apresentada, ou seja minha classe TValidar só validariao campo, TMinhaException faria a parte de tratar a exception.
Acho que esta complicando
Antes de proseguir com o exit e com seu raciocineo
teste este exemplo
Defina na sua Classe
type TMinhaExcecao = class(Exception);
Na sua Classe qnd for conveniente , naqueles lugares aonde vc usa a Booleana para dizer que não Pode gravar
Vc Faz
raise TMinhaExcecao.Create('MinhaExcecao');
Com isto esta exceção é levantada e capturada no Bloco Try except do Codigo Principal
procedure TForm1.Button1Click(Sender: TObject);
begin
try
raise TMinhaExcecao.Create('MinhaExcecao');
except
on e:TMinhaExcecao do
Showmessage(e.Message);
on e:exception do
Showmessage('Esta excecao não fio criada') //portanto não sera exceutada
end;
end;
Gostei + 0
14/05/2010
Walter Desidera
bem a sua idéia, vejamos:
//Defini uma nova exception
type
TMinhaExcecao = class(Exception);</span><span style="font-size: 10pt;">
class procedure TValidar.CampoObrigatorio(Campo: String; ShowMsg: Boolean;
Menssagem: String; Componente: TWinControl);
begin
if Campo = '' then
begin
//FGravar:= false;
Componente.SetFocus;
if ShowMsg then
Application.MessageBox(Pchar(Menssagem), 'Atenção',MB_ICONINFORMATION + MB_OK);
raise TMinhaExcecao.Create('Campo Obrigatório!');
<== Adicionei a exception criada aqui
end;
end;
Num Botão qualquer:
try
TValidar.CampoObrigatorio(Edit1.Text,True,'Campo Vazio!',Form1.Edit1);
//Aqui a exception foi levantada
except
on e:TMinhaExcecao do //Caindo nesse bloco
Showmessage(e.Message); //Mostrou a mensagem Campo Obrigatório!
on e:exception do
Showmessage('Esta exceção não foi criada') //portanto não sera executada
end;
Isso funciona, mesmo que eu chame a exception depois de dar focus e mostrar a minha
menssagem ainda recebo uma menssagem do raise da exception, ou seja duas
menssagens...
Ainda que eu usasse o Abort para ter apenas a minha mensagem , o bloco
try...except é meio estranho, pois quando acontecer uma exceção eu não quero
que ele faça nada...um raise aconteceu ele captura e cai no except
dai no except não faço nada, pq já foi tratado anteriormente no meu método...
Se eu deixa-se apenas com a exception daria certo, mais eliminaria meu
MessageBox...
Gostei + 0
14/05/2010
Marco Salles
Try
TValidar(); // e coisa e tal -->> se levantar uma exceção ela sera capturada pelo try except
TValidar(); // e coisa e tal
TValidar(); // e coisa e tal
TValidar(); // e coisa e tal
Showmessage('Gravado')
except
//Não coloque nada Aqui.. A exceção cai neste bloco que não faz nada...
end;
Gostei + 0
15/05/2010
Walter Desidera
Testei desta forma também:
class function TValidar.Data(Data: String; ShowMsg: Boolean; Menssagem: String; Componente: TWinControl = nil): Boolean; var Aux: TDateTime; begin if (TryStrToDate(Data,Aux))then begin Result := True end else begin Result := False; if Componente <> nil then Componente.SetFocus; if ShowMsg = True then Application.MessageBox(Pchar(Menssagem), 'Atenção',MB_ICONINFORMATION + MB_OK); Abort; <=== Ele cancela o processamento dos outros campos também, então não uso o Try...Except end; end; Validar.Data(Edit1.Text,true,'Data Inválida',Form1.Edit1); Aborta e não continua para o próximo Validar.Data(Edit2.Text,true,'Data Inválida',Form1.Edit2);
Se deu erro nem valida os outros, e também não recebo um erro do compilador por ter usado um raise... Agora sobre a segurança dessa implementação... Achei uma ótima idéia do try...except é um método mais seguro, um erro ocorre na validação e o processo é abortado imediatamente...
Já a procedure abort tem um código ASM...
procedure Abort; function ReturnAddr: Pointer; asm MOV EAX,[EBP + 4] end; begin raise EAbort.CreateRes(@SOperationAborted) at ReturnAddr; end; Mais isso é para quando eu tiver mais tempo livre pra entender rsrsrsrs
Gostei + 0
Clique aqui para fazer login e interagir na Comunidade :)
Inserção de url
Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.