domingo, 22 de abril de 2007

Aplicações Robustas III: Criação de Exceções

Esse artigo é continuação do post “Robustez no Delphi

Dando continuidade a seqüência de artigos sobre tratamento de exceções.....

Com base em tudo o que foi falado nos artigos anteriores sobre exceções vamos tratar agora sobre como e por que criar suas próprias exceções. Entenda que não me refiro a levantar um exceção, quando uso o termo “criar” estou falando de definir uma classe nova, derivada diretamente de Exception, ou de um de seus herdeiros.

Criando suas próprias exceções:

Imagine uma situação em que a lógica do negócio envolvida no seu programa, defina certas regras que não podem ser quebradas. Você não vai encontrar nas bibliotecas do Delphi nenhuma exceção para o caso de um cliente ser cadastrado com valor para data de nascimento maior que a data corrente, por exemplo. Portanto, quando você precisa garantir que as regras pertinentes ao negócio sejam suportadas pelo seu sistema em forma de exceções é preciso para isso definir classes, tipos, de exceções específicas para isso.

Construindo um exemplo.


Para exemplificar, vamos propor um problema para em seguida implementarmos um pequeno programa, em cima desse problema, de maneira que possamos modelar as regrar contidas no domínio do problema em questão em forma de exceções.

O problema:
O programa que vamos contruir simula um pequeno aspecto da relação de uma farmácia e seus clientes. Vejamos, para compra de qualquer remédio controlado é exigido a apresentação, por parte do cliente, de uma receita válida para o remédio específico desejado. Em nosso exemplo vamos trabalhar com os seguintes atributos da receita: Data de validade e substância (remédio). Criaremos, portanto, duas classes de exceções: EDataInvalida (caso a receita esteja vencida), ESubstanciaErrada. Vamos arbitrariamente definir que a validade de uma receita seja de 4 dias. Já temos algumas regras, agora já podemos construir nosso pequeno programa.

Inicie uma nova aplicação no Delphi
: Menu, File ►New ► Application.

No Form1 adicione os seguintes componentes: Duas ComboBox (TComboBox), um Button (TButton), três Labels (TLabel) e um ListBox (TListBox), da palheta Standard; Um DateTimePicker1 (TDateTimePicker), da palheta Win32. Configure as propriedades dos componentes segundo listado abaixo:


Form1:
Width = 470
Height = 494
Caption = 'Criando Exceções'

Label1:
Left = 12
Top = 12
Caption = 'Receita'

Label2:
Left = 300
Top = 12
Caption = 'Remédio'

Label3:
Left = 12
Top = 58
Caption = 'Data da Receita'

ComboBox1:
Name = CmbReceita
Left = 12
Top = 29
Width = 280

ComboBox2:
Name = CmbRemedio
Left = 300
Top = 29
Width = 150

Button1: TButton
Left = 373
Top = 64
Width = 75
Height = 25
Caption = 'Efetuar venda'

ListBox1:
Name = LstVendas
Left = 12
Top = 104
Width = 445
Height = 353

DateTimePicker1:
Name = DtReceita
Left = 12
Top = 75
Width = 82


A seção type da unit1 deverá estar assim

type
TForm1 = class(TForm)
CmbReceita: TComboBox;
CmbRemedio: TComboBox;
Button1: TButton;
ListBox1: TListBox;
DtReceita: TDateTimePicker;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
private
{ Private declarations }
public
{ Public declarations }
end;


Logo abaixo da palavra reservada “type” vamos codificar a definição das nossas exceções. Faça conforme exemplo abaixo:



type
EDataInvalida = class(Exception);//Exceção para data inválida
ESubstanciaErrada = class(Exception); // Exceção de substância errada

TForm1 = class(TForm)
CmbReceita: TComboBox;
CmbRemedio: TComboBox;
Button1: TButton;
LstVendas: TListBox;
DtReceita: TDateTimePicker;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
private
procedure LoadReceitas;
procedure LoadRemedios;
procedure CriticarVenda;
{ após digitar as procedures a cima pressione: “Ctrl+Shift+C”}
public
{ Public declarations }
end;


Codificaremos primeiro o preenchimento da combo com os remédios.

procedure TForm1.LoadRemedios;
begin
(* Montando a combo dos remédios *)
with CmbRemedio do
begin
Items.Add('Frontal');
Items.Add('Tefxel');
Items.Add('Lorax');
Items.Add('Haldol');
Items.Add('Urbanil');
Items.Add('Tagretol');
end;
end;


Em seguida o preenchimento da combo das receitas. Para facilitarmos nosso exemplo vamos ordenar as receitas conforme a ordem dos remédios.


procedure TForm1.LoadReceitas;
const
DescReceita = 'Receita para o remédio: %s';
var
i: Integer;
begin
for i := 0 to CmbRemedio.Items.Count - 1) do
CmbReceita.Items.Add(Format(DescReceita, [CmbRemedio.Items[i]]))

end;


Agora, a rotina que gera as exeções, “CriticarVenda”.

procedure TForm1.CriticarVenda;
begin
(* Caso nehuma opção seja selecionada levantaremos uma exceção genérica*)
if (CmbReceita.ItemIndex < 0) and (CmbRemedio.ItemIndex < 0) then
raise Exception.Create('Selecione a receita, em seguida o remédio.');

(* Caso uma opção não seja selecionada levantaremos a exceção que criamos*)
if (CmbReceita.ItemIndex <= 0) xor (CmbRemedio.ItemIndex <= 0) then
raise ESubstanciaErrada.Create('A receita não corresponde ao remédio.');

(* Caso as opção selecionada sejam diferntes *)
if not (CmbReceita.ItemIndex = CmbRemedio.ItemIndex ) then
raise ESubstanciaErrada.Create('A receita não corresponde ao remédio.');

(* definimos, hipoteticamente, prazo de validade de 6 dias para a receita. *)
if DtReceita.Date < (Date - 6) then
raise EDataInvalida.Create('Prazo de validade da receita expirou.');
end;

No evento OnCreate do From1 faremos a chamada aos procedimentos que preencherão as Combos.

procedure TForm1.FormCreate(Sender: TObject);
begin
LoadRemedios;
LoadReceitas;
DtReceita.Date := Date - 10;
end;

Para finalizar, o evento OnClick do Button1, onde construiremos o tratamento das exceções.

procedure TForm1.Button1Click(Sender: TObject);
const
MsgSucesso = 'Venda efetuada com sucesso: %s';
begin
try
CriticarVenda;
LstVendas.Items.Add(Format(MsgSucesso, [CmbRemedio.Text]));
except
on E: EDataInvalida do
LstVendas.Items.Add(E.Message);
on E: ESubstanciaErrada do
begin
LstVendas.Items.Add(E.Message);
CmbRemedio.SetFocus;
if CmbReceita.ItemIndex < 0 then
begin
MessageBox(0, 'Selecione a receita.',
'Criando Exceções - Estação ZN', MB_ICONERROR or MB_OK);
CmbReceita.SetFocus;
end;
end;

on E: Exception do
begin
MessageBox(0, PChar(E.Message),
'Criando Exceções - Estação ZN', MB_ICONERROR or MB_OK);
CmbReceita.SetFocus;
end;
end;
end;

Veja as imagens abaixo:






Nenhum comentário:

Postar um comentário