Aplicações Robustas IV: Propagando de Exceções
Esse artigo é continuação do post “Aplicações Robustas III”
Propagando exceções:
Construindo um exemplo:
Inicie uma nova aplicação no Delphi:
No D7 - Menu, File ►New ► Application.
No BDS - Menu, File ►New ► VCL Forms Application – Delphi for Win 32 (“Alt, n, r”).
Adicione uma nova Unit: Nela vamos copdificar uma função.
No D7 - Menu, File ►New ► Unit.
No BDS - Menu, File ►New ► Unit – Delphi for Win 32 (“Alt, n, t”).
unit ZnFunctionPropagExcept;
interface
uses DbClient, Db, Classes, SysUtils, Dialogs;
type
ZnException = class(Exception);
function SetDados(Lista: TStringList;
Cds: TClientDataSet; AField: TField): String;
procedure ForcaExcecao(const Value: string);
implementation
procedure ForcaExcecao(const Value: string);
begin
(* força uma exceção. Basta que um dos elementos da lista seja a palavra
exceção. *)
if AnsiUpperCase(Value) = AnsiUpperCase('exceção') then
raise ZnException.Create('ZnException: Buuuuuuuhhhhhhhh!!!!!!');
end;
function SetDados(Lista: TStringList;
Cds: TClientDataSet; AField: TField): String;
var
I: Integer;
begin
try
if Lista.Count <= 0 then
raise Exception.Create('Nenhum elemento na lista.');
for I := 0 to Lista.Count - 1 do
begin
ForcaExcecao(Lista[i]);
if not Cds.Locate(AField.FieldName, Lista[i], []) then
begin
Cds.Append;
AField.AsString := Lista[i];
Cds.Post;
end;
end;
except
(*essa exceção não vou propagar*)
on E: ZnException do
MessageDlg(E.Message, mtInformation, [mbOK], 0);
(*Propagando a exceçaõ genérica*)
on E: Exception do raise;
end;
Result := Cds.XMLData;// retorna os dados no formato Xml numa string.
end;
end.

Na seção “type” declaramos uma exceção “ZnException” aqual usaremos no nosso tratamento. Os dois modulos cdificados nesta Unit são: A função “SetDados” que recupera os dados de uma lista e atribui a um dataset, retorna um string que usaremos como log do que foi adicionado no dataset. O procedimento “ForcaExcecao”, como o próprio nome já indica força um exceção, algo que é impressindível para o nosso exemplo. Após codificar esta Unit, passe para a implentação do form1 na unit “ZnPropagExceptForm”.
No Form1 adicione os seguintes componentes: Um Edit (TEdit), um Button (TButton), um Label (Tlabe) e um ListBox (TListBox), da palheta Standard; Dois DbGrids (TDbGrid), da palheta Data Control; Dois DataSource(TDataSource), Dois ClientDataSet(TClientDataSet) Data access. Configure as propriedades dos componentes segundo listado abaixo:
Form1: TZnPropagExceptFrm
Name = ZnPropagExceptFrm
ClientHeight = 395
ClientWidth = 578
Caption = 'Propagando Exceções'
Label1: TLabel
Left = 16
Top = 8
Width = 31
Height = 13
Caption = 'Digite o Dado'
ListBox1: TListBox
Name = LstDados
Left = 16
Top = 56
Width = 121
Height = 329
Button1 : TButton
Name = BtnAddElemento
Left = 143
Top = 27
Width = 90
Height = 25
Caption = 'Add Elemento'
Edit1: TEdit
Name = EdtDados
Left = 16
Top = 29
Width = 121
Height = 21
ClientDataSet1: TClientDataSet
Name = cdsLog
ClientDataSet2: TClientDataSet
Name = cdsDados
DataSource1: TDataSource
Name = dsDados
DataSet = cdsDados
DataSource: TDataSource
Name = dsLog
DataSet = cdsLog
DbGrid1: TDBGrid
Name = GrdLog
Left = 248
Top = 216
Width = 322
Height = 169
DataSource = dsLog
DbGrid2: TDBGrid
Name = GrdDados
Left = 247
Top = 29
Width = 322
Height = 181
DataSource = dsDados
Button2: TButton
Name = BtnTransDados
Left = 143
Top = 70
Width = 90
Height = 25
A seção type da unit1 deverá estar assim
type
TZnPropagExceptFrm = class(TForm)
LstDados: TListBox;
BtnAddElemento: TButton;
EdtDados: TEdit;
Label1: TLabel;
dsDados: TDataSource;
cdsLog: TClientDataSet;
GrdLog: TDBGrid;
GrdDados: TDBGrid;
cdsDados: TClientDataSet;
dsLog: TDataSource;
BtnTransDados: TButton;
private
{ Private declarations }
public
{ Public declarations }
end;
Campos persistentes:
Vamos adicionar um campo persistente em cada um dos ClientDataSets. O Nome do Campo vai ser “ZnTexto”, o tipo string, e tamanho 200 (quantidade de caracteres). Click com o botão direito do mouse sobre o ClientDataSet, escolha aopção, “Fields Editor”.

Agora botão direito no Field Editor, escolha a opção, “New Field”.

Cofigure conforme a figura abaixo e click “Ok”:

Pronto vc acabou de criar um campo persistente num dataset. Repita a mesma operação para o outro ClientDataSet.

Codificando o evento OnClick do botão “BtnAddElemento”, “BtnAddElementoClick”:
procedure TZnPropagExceptFrm.BtnAddElementoClick(Sender: TObject);
begin
(* Atribuido a lista o valor digitado no Edtdados *)
LstDados.Items.Add(EdtDados.Text);
EdtDados.Clear; // Limpa o Edit
EdtDados.SetFocus;// seta o foco para ele
end;
É chegado o momento de usarmos a Unit contendo os módulos que programamos onde está o tratamento de exceção. Faça use unit, ou seja no Menu, File ►Use Unit (Alt, f, u), ou Alt + F11.

Codificando o evento OnClick do botão “BtnTransDado”, “BtnTransDadosClick”:
procedure TZnPropagExceptFrm.BtnTransDadosClick(Sender: TObject);
var
Lst: TStringList;
begin
Lst := TStringList.Create;
(*Bloco protegido*)
try
try
Lst.Assign(LstDados.Items);
cdsLog.XMLData := SetDados(Lst, cdsDados, cdsDadosZnTexto);
except
(*Capturando a exceção propagada pela rotina "SetDados"*)
on Zn: Exception do
begin
Self.Caption := Zn.Message + '/'+ Zn.ClassName;
MessageBox(0, 'Exceção propagada capturada!!!!',
'Estação Zn', MB_ICONASTERISK or MB_OK);
end;
end;
finally
Lst.Free;
end;
end;
No D7:
No menu Tools ► Debuggrer Options ► Aba “Language Exceptions”, desmarque a check “Stop on Delphi Exception” (Dica do Felipe)
No BDS:
No menu Tools ►Options ...Selecione, na treeview a esquerda, Borland Debugger, sub item, language Exceptions, e desmarque a check “Notify on Language Exceptions”. Veja na figura abaixo:


Prosseguindo com o nosso exemplo, vamos acrescentar um botão que irá abrir os ClientDataSets. Ficando ao critério do usuário forçar a exceção “EDatabaseError” ou não. Configure o novo botão da seguinte forma: Name = btnOpenCds; Caption = “Ativar Cds”; Top = 108; left =143; Width = 90.
procedure TZnPropagExceptFrm.BtnOpenCdsClick(Sender: TObject);
begin
(*O Método "CreateDataSet nos permite trabalhar com o ClienteDataSet
desconectado do banco de dados. "*)
cdsLog.CreateDataSet;
cdsDados.CreateDataSet;
end;
Vamos executar nosso segundo teste. Pressione F9, ative os datasets clickando no novo botão. Adicione alguns elementos. Lembre-se, se vc não adicionar a palavra “Exceção”, nenhuma exceção será levantada. Portanto, para testar o caso da exceção que não é propagada, adicione a palavra “exceçao”. E Clicke sobre o botão “Transfere Dados”.

Verifique o codigo da função “SetDados”, veja que o que diferenciou um caso do outro foi a utilização da paralra reservada “raise” na estutura “on ..do” (que verificava se a exceção era do tipo “ZnException”). Quando vc trata uma exceção, a estrutura “try ... except” provê para vc um manipulador de exceções. Esse manipulador gerencia também o “tempo de existência” dessa exceção. Antes do final da estrutura a exceção “morre”, é desalocada. Assim sendo, se vc deseja que ela seja atribuida, passada, ao próximo manipulador, vc tem que usar a palavra reservadda “raise”.
Note Ainda que, assim que vc clickar no ok da mensagem da exceção, o processo continuará a execução após a estrutura “try ... except” da função “SetDados” e efetuará o log dos elementos transferidos para o “cdsDados”.

Artigo completo (View Full Post)










