Sei sulla pagina 1di 10

Quando eu explico tratamento de exceção na academia ABAP, o

pessoal não dá muita bola, até porque os alunos ainda estão tentando
se recuperar das aulas de polimorfismo e interface, mas entender o
funcionamento dela é vital para desenvolver boas soluções usando
orientação a objetos (não somente para aprender a escrever a palavra
exceção).

Nesse post, vou explicar dois conceitos ligado ao tratamento de


exceções baseado em classes, propagação e comando CLEANUP.

Começando Pelo Básico


Vamos entender primeiro o funcionamento básico do tratamento de
exceções baseado em classes. Quando usamos as classes de
exceção, devemos usar a estrutura de comandos TRY-CATCH-
CLEANUP.

Usarei a classe LCL_EXCEPTION_DEMO que está no include


ZABAP101_EXCEPTION_CLASSES nos programas de exemplo.

*&---------------------------------------------------------------------*
*& Include ZABAP101_EXCEPTION_CLASSES
*&---------------------------------------------------------------------*

*----------------------------------------------------------------------*
* CLASS lcl_exception_demo DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_exception_demo DEFINITION.

PUBLIC SECTION.
METHODS: dump_factory,
simple_catch,
cleanup_live RAISING cx_sy_zerodivide,
cleanup_dead RAISING cx_sy_zerodivide,
propagating RAISING cx_sy_zerodivide.

PRIVATE SECTION.
DATA: result TYPE i.

ENDCLASS. "lcl_exception_demo DEFINITION


*----------------------------------------------------------------------*
* CLASS lcl_exception_demo IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_exception_demo IMPLEMENTATION.

METHOD dump_factory.
result = 1 / 0.
ENDMETHOD. "dump_factory

METHOD simple_catch.
TRY .
result = 1 / 0.
CATCH cx_sy_zerodivide.
WRITE: / 'Executou o CATCH do método SIMPLE_CATCH.'.
ENDTRY.
ENDMETHOD. "simple_catch

METHOD cleanup_live.
TRY .
result = 1 / 0.
CLEANUP.
WRITE: / 'Executou o Cleanup do método CLEANUP_LIVE.'.
ENDTRY.
ENDMETHOD. "cleanup_live

METHOD cleanup_dead.
TRY .
result = 1 / 0.
CATCH cx_sy_zerodivide.
WRITE: / 'Executou o CATCH do método CLEANUP_DEAD'.
CLEANUP.
" o programa nunca executará o CLEANUP.
WRITE: / 'Executou o Cleanup do método CLEANUP_DEAD.'.
ENDTRY.
ENDMETHOD. "cleanup_dead
METHOD propagating.
result = 1 / 0.
ENDMETHOD. "propagating

ENDCLASS. "lcl_exception_demo IMPLEMENTATION

view rawZABAP101_EXCEPTION_CLASSES hosted with by GitHub

O primeiro programa que mostrarei é um programa cuja saída é … um


DUMP!? Sim, quando o sistema chega a alguma situação onde ele
não consegue seguir com o programa, como por exemplo uma divisão
por zero.
*&---------------------------------------------------------------------*
*& Report ZABAP101_EXCEPTION_DUMP
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*

REPORT zabap101_exception_dump.

INCLUDE zabap101_exception_classes.

DATA: r_demo TYPE REF TO lcl_exception_demo.

START-OF-SELECTION.

CREATE OBJECT r_demo.

TRY .
r_demo->dump_factory( ).
CATCH cx_sy_zerodivide.
WRITE: / 'Executou o CATCH do programa principal.'.
ENDTRY.

view rawZABAP101_EXCEPTION_DUMP hosted with by GitHub


Quando o programa tenta fazer uma divisão por zero a seguinte tela é
mostrada. Toda a pilha de execução é eliminada e toda a memória
usada pelo programa é apagada.

Mas graças ao tratamento de exceção por classes, você pode dizer


para o sistema “tente executar essa operação, e se caso aconteça
divisão por zero, execute isso”.

Nesse primeiro programa onde o DUMP é evitado, o método


SIMPLE_CATCH( ) é chamado. Na implementação do método, ele
tenta (TRY) executar uma divisão por zero, que é tratada (CATCH)
dentro do próprio método.

*&---------------------------------------------------------------------*
*& Report ZABAP101_EXCEPTION_BASIC
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*

REPORT zabap101_exception_basic.

INCLUDE zabap101_exception_classes.

DATA: r_demo TYPE REF TO lcl_exception_demo.

START-OF-SELECTION.

CREATE OBJECT r_demo.

TRY .
r_demo->simple_catch( ).
CATCH cx_sy_zerodivide.
WRITE: / 'Executou o CATCH do programa principal.'.
ENDTRY.

view rawZABAP101_EXCEPTION_BASIC hosted with by GitHub

Repare que a a exceção é tratada dentro do próprio método, portanto


a mensagem “Executou o CATCH do método SIMPLE_CATCH.” é
impressa no lugar do DUMP. A saída do programa acima é mostrada

abaixo:
Propagação de Exceção
Conheço muitas equipes onde esse conceito é muito bem difundido,
ou seja, uma pessoa decide não ser responsável pelo erro que
cometeu e decide passar o erro para outra pessoa corrigir. Pois é, no
ABAP temos algo parecido. Veja esse programa:

*&---------------------------------------------------------------------*
*& Report ZABAP101_EXCEPTION_PROP
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*

REPORT ZABAP101_EXCEPTION_PROP.

INCLUDE zabap101_exception_classes.

DATA: r_demo TYPE REF TO lcl_exception_demo.

START-OF-SELECTION.

CREATE OBJECT r_demo.

TRY .
r_demo->propagating( ).
CATCH cx_sy_zerodivide.
WRITE: / 'Executou o CATCH do programa principal.'.
ENDTRY.

view rawZABAP101_EXCEPTION_PROP hosted with by GitHub

Quando o método PROPAGATING( ) é chamado, uma divisão por


zero é executada. Observe que esta divisão não está sendo tratada
com o TRY-CATCH e veja a saída do programa:
O segredo está na declaração do método: “METHODS propagating
RAISING cx_sy_zerodivide.” Existe uma instrução RAISING que diz
exatamente o que algumas pessoas que conheço fazem, “olha, pode
ser que uma divisão por zero aconteça e se isso acontecer você
[quem está chamando o método] deverá tratar essa exceção”.

Sendo assim, a exceção precisou ser tratada na chamada do método


e não mais dentro do método.

Qual forma usar, a do primeiro programa ou essa? Depende. Se você


quer passar a responsabilidade do tratamento para quem chama o
método então o segundo programa deve ser usado. Mas se o erro é
algo interno do método e precisa ser tratado de maneira transparente
do usuário, então você deverá tratar a exceção dentro do próprio
método, assim como fora feito no primeiro programa.

O que acontece se não tratarmos a exceção na chamada do método?


Experimente…

CLEANUP não é WHEN OTHERS do


Tratamento de Exceções
Essa é a primeira conclusão que os meus alunos chegam quando
olham para definição do comando no Help do ABAP.

Não, o CLEANUP não é uma espécie de WHEN OTHERS do TRY-


CATCH. Para ilustrar o uso do CLEANUP, veja o programa abaixo:

*&---------------------------------------------------------------------*
*& Report ZABAP101_EXCEPTION_CLEAN
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*

REPORT ZABAP101_EXCEPTION_CLEAN.

INCLUDE zabap101_exception_classes.

DATA: r_demo TYPE REF TO lcl_exception_demo.

START-OF-SELECTION.

CREATE OBJECT r_demo.

TRY .
r_demo->cleanup_live( ).
CATCH cx_sy_zerodivide.
WRITE: / 'Executou o CATCH do programa principal.'.
ENDTRY.

view rawZABAP101_EXCEPTION_CLEAN hosted with by GitHub

O objetivo do CLEANUP é para a limpeza de variáveis (memória)


quando acontece uma exceção que será propagada. Seria o
equivalente ao “quero limpar a bagunça antes de passar a exceção
para ser tratada por quem chamou o método”.

Pela saída do
programa, você consegue entender a sequência de execução do
programa. Ocorre a exceção, o CLEANUP é executado e então o
CATCH no programa principal.
CLEANUP Morto
O CLEANUP somente é usado para “limpar a bagunça” quando a
exceção está sendo propagada. No programa abaixo, o CLEANUP
nunca será chamado.

*&---------------------------------------------------------------------*
*& Report ZABAP101_EXCEPTION_FAKE_CLEAN
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*

REPORT ZABAP101_EXCEPTION_FAKE_CLEAN.

INCLUDE zabap101_exception_classes.

DATA: r_demo TYPE REF TO lcl_exception_demo.

START-OF-SELECTION.

CREATE OBJECT r_demo.

TRY .
r_demo->cleanup_dead( ).
CATCH cx_sy_zerodivide.
WRITE: / 'Executou o CATCH do programa principal.'.
ENDTRY.

view rawZABAP101_EXCEPTION_FAKE_CLEAN hosted with by GitHub

Na saída do programa vemos claramente que o sistema não executou


o CLEANUP, pois a divisão por zero é tratada dentro do próprio
método.
Conclusão
Os conceitos de tratamento de exceção por classes não fica somente
nisso, mas nesse post quis apenas expor os conceitos de propagação
e CLEANUP. Para o uso correto de classes de exceções, é necessário
entender encadeamento de exceções, hierarquia de exceções e textos
da exceção. Isso será explorado em futuros posts.

Aprenda a usar corretamente as classes de exceções e você


entregará programas muito elegantes e de fácil manutenção

Potrebbero piacerti anche