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

 
BlogBlogs.Com.Br