Nesse artigo falarei mais um pouco sobre "Tratamento de Exceções".
Caso você não tenha lido o artigo anterior, peço que não continue esse artigo a menos que esteja bem inteirado sobre o tema. Se preferir, clique aqui para ver o artigo anterior.
Veremos abaixo mais exemplos de Try, Except e Finally aninhados e, também
apresentaremos um meio de gerar exceções através do Raise.
Para iniciar, vamos relembrar como tratar exceções com as cláusulas
Try, Except e Finally num determinado trecho do código.
Nunca construir tratamento de exceções dessa forma:
Try
...
Except
...
Finally
...
End;
A forma correta de tratar exceções usando Try, Except e Finally
é:
Try
Try
...
Except
...
End;
Finally
...
End;
Também podemos opcionalmente construir:
Try
Try
...
Except
...
End;
Finally
Try
...
Except
...
End;
...
End;
A seguir, apresento a lista das exceções que descrevem os tipos
básicos - há centenas de classes da exceção:
Classe - Descrição
Exception - Exceção genérica, usada
apenas como ancestral de todas as outras exceções;
EAbort - Exceção silenciosa, pode ser gerada
pelo procedimento Abort e não mostra nenhuma mensagem;
EAccessViolation - Acesso inválido à memória,
geralmente ocorre com objetos não inicializados;
EConvertError - Erro de conversão de tipos de dados;
EDivByZero - Divisão de inteiro por zero;
EInOutError - Erro de Entrada ou Saída reportado pelo sistema operacional;
EIntOverFlow - Resultado de um cálculo inteiro excedeu o limite;
EInvalidCast - TypeCast inválido com o operador as;
EInvalidOp - Operação inválida com número de ponto
flutuante;
EOutOfMemory - Memória insuficiente;
EOverflow - Resultado de um cálculo com número real excedeu o
limite;
ERangeError - Valor excede o limite do tipo inteiro ao qual foi atribuída;
EUnderflow - Resultado de um cálculo com número real é menor
que a faixa válida;
EVariantError - Erro em operação com variant;
EZeroDivide - Divisão de real por zero;
EDatabaseError - Erro genérico de banco de dados, geralmente não é usado
diretamente;
EDBEngineError - Erro da BDE, descende de EDatabaseError e traz dados que podem
identificar o erro;
Exemplos
1 - Nesse Exemplo, temos uma ocorrência normal da Aplicação
utilizando Try, Finally -> Try, Except . O código
na cláusula
Try é executado por completo e em seguida, o código da cláusula
Finally é executado entrando primeiro na cláusula Try que está dentro
de Finally. Como não é gerada nenhuma exceção
dentro desse Try, o código é executado por completo
indo em seguida para a última linha do Finally.

Figura 1
2 - Nesse Exemplo, temos uma ocorrência normal da Aplicação
utilizando Try -> Try, Except, Finally -> Try, Except. O
código
na cláusula Try -> Try é executado por completo
e em seguida, o código da cláusula Finally é executado
entrando primeiro na cláusula Try que está dentro
de Finally. Como não é gerada
nenhuma exceção dentro desse Try o código é executado
por completo, indo em seguida para a última linha do Finally.

Figura 2
3 - Nesse Exemplo temos uma ocorrência de uma divisão por zero
na Aplicação, utilizando Try -> Try, Except, Finally
-> Try,
Except. O código na cláusula Try -> Try é executado
até a linha "resultado := dividendo div divisor;". Como
nessa linha ocorre a exceção "EDivByZero" o
código
da cláusula Except é executado, verificando
o tipo de exceção
que foi gerado. Repare que nesse exemplo o Except possui apenas
3 tentativas (on EDivByZero do, on EAccessViolation do e else).
A tentativa válida
que será executada neste caso é on EDivByZero do e
após
isso o finally é chamado,
executando o código da mesma forma como mostramos nos exemplos anteriores.

Figura 3
4 - Nesse Exemplo, temos a ocorrência de um objeto que não criado,
ou instancializado se preferir, ser utilizado para atribuição
de valor em Try -> Try, Except, Finally -> Try, Except.
O código na cláusula Try -> Try é executado
até a linha "MinhaStringList.Text
:= '1';". Como o objeto MinhaStringList não
foi criado ("MinhaStringList := TStringList.Create;"),
essa linha gera a exceção "EAccessViolation",
então, o código da clásula Except é executado
verificando o tipo de exceção que foi gerado, executando a linha on
EAccessViolation do e após isso o finally é chamado
executando o código da cláusula Try, que por sua
vez também gera uma exceção. A exceção ocorre
porque tentamos destruir um objeto que não foi Criado, linha "MinhaStringList.Destroy;".
Assim o código em Except é executado e após
isso o restante do código do finally.

Figura 4
5 - Nesse Exemplo, temos uma ocorrência parcialmente normal da Aplicação,
utilizando Try -> Try, Except, Finally -> Try, Except.
O código na cláusula Try -> Try é executado
por completo e em seguida, o código da clásula Finally é executado,
entrando primeiro na clásula Try que está dentro
de Finally. Quando a linha "MinhaStringList.Destroy;" é executada,
ocorre uma exceção porque tentamos destruir um objeto que já havia
sido destruído, na linha "MinhaStringList.Destroy;" em Try
-> Try. Assim o código em Except é executado
e após isso o restante do código do finally.

Figura 5
6 - Nesse Exemplo, temos uma ocorrência parcialmente normal da Aplicação,
utilizando Try, Finally -> Try, Except. O código
na cláusula Try é executado por completo e
em seguida, o código da cláusula Finally é executado,
entrando primeiro na cláusula Try que
está dentro de Finally. Quando a linha "MinhaStringList.Destroy;" é executada,
ocorre uma exceção porque tentamos destruir um objeto que já havia
sido destruído,
na linha "MinhaStringList.Destroy;" em Try.
Além disso estamos forçando a finalização da Aplicação
com "Application.Terminate;".
Assim, o código
em Except é executado e o Raise permite
que a Exceção seja exibida ao usuário, então, a
Aplicação nem chega a executar restante do código
em finally.

Figura 6
7 - Nesse Exemplo, temos uma ocorrência de uma divisão por
zero na Aplicação, utilizando Try -> Try, Except,
Finally. O código na cláusula Try -> Try é executado
até a linha "resultado := dividendo div divisor;".
Como nessa linha ocorre a exceção "EDivByZero",
o código da clásula Except é executado,
mas dessa vez, sem verificar o tipo de exceção que foi gerado,
porque diferente do exemplo Número 3, que possuía
3 tentativas (on EDivByZero do, on EAccessViolation
do e else), o exemplo 7 mostra um tratamento genérico, na
linha ("on E : Exception do"). Dessa forma, a Aplicação
entende que qualquer exceção ocorrida deve ser tratada pelo código
dentro de "on E : Exception do". Essa idéia
pode ser aplicada a outros tipos de Exceções, bastando apenas
você definir um tratamento genérico a todos os problemas que possam
ocorrer.

Figura 7
Existem muitas formas de trabalhar com Tratamento de Exceções
de forma com que a aplicação fique mais robusta. Um outro exemplo é a
possibilidade de criarmos nossa própria exceção. Para isso,
na seção Type, digite:
type
EUsuarioInvalido = class (Exception);
E no evento OnClick do botão faça:

Figura 8
Em execução, você verá:

Figura 9
Exceções e o Debbuger
Enquanto você estiver usando o Delphi para testar sua aplicação,
verá que antes das mensagens de tratamento de exceções
serem exibidas, uma notificação de Exceção da IDE é exibida
para você (passando a impressão de que o tratamento de exceção
não funcionou), então, pressionando a tecla F9 é possível
dar continuidade a aplicação.
Mas as vezes isso se torna um incômodo
para testar nossa aplicação. No meu caso, acabei testando fora
do Delphi, rodando o executável.
Para testar a aplicação sem que a notifcação
de Exceção da IDE do Delphi apareça, faça o seguinte:
Delphi 2006: No menu Tools, Options, Debugger Options, Borland
Debuggers, Language Exceptions, desmarque a opção “Notify
on language exceptions”.
Delphi 7 ou Anterior: No menu Tools, Debugger Options, Language
Exceptions, desmarque a opção “Stop on Delphi
Exceptions”
Dessa forma, as mensagens de exceção do depurador não
serão mostradas!
Beleza galera, no próximo artigo irei passar mais alguns exemplos e
apresentar outros tipos de exceções. Espero que isso possa lhes
ajudar e também espero que vocês possam contribuir com comentários
referentes a experiências obtidas com o uso do tratamento de exceções.
Se tiverem dúvidas, é só entrar em contato!
Clique aqui para fazer o download do exemplo
João
Marcos
Contato: jsakalauska@gmail.com
|