A Progress introduziu no OpenEdge 10.1C uma nova funcionalidade que permite o tratamento estruturado de erros, de forma similar ao existente em linguagens como C# e Java. Esta forma de tratamento de erros é caracterizada pelas seguintes funcionalidades:
- todos os erros são representados como objetos (são instâncias de uma classe);
- o programador pode definir seus próprios tipos de erros (criar novas classes de erros);
- o programador pode gerar um erro explicitamente;
- o programa pode interceptar um determinado tipo de erro em um contexto;
- os erros podem ser propagados de um contexto interno para um contexto externo;
- pode ser especificado um bloco de código que executa ao final de outro bloco, independente de ter ou não ocorrido erro na execução.
No OpenEdge o tratamento estruturado de erros é realizado com os blocos CATCH / FINALLY, que devem estar associados a algum bloco com a propriedade UNDO (normalmente um bloco DO, FOR ou REPEAT).
Quando existe um bloco CATCH associado a um bloco de código, o código inicia sua execução normal. Se ocorrer algum erro durante a execução, o bloco de código é abortado, a máquina virtual do OpenEdge (AVM) gera um UNDO e o bloco CATCH é acionado. Podemos dizer que o bloco CATCH “intercepta” os erros ocorridos nos blocos aos quais estão associados. Se o bloco de código original executar sem erros, o bloco CATCH não é acionado.
Quando se utiliza o tratamento normal de erros com NO-ERROR é necessário verificar a ocorrência de erros após cada comando. O tratamento estruturado de erros facilita esta verificação, pois independentemente do comando que gerou erro no bloco de código, o bloco CATCH é executado.
O FINALLY permite associar um bloco que sempre executa ao final de um bloco de código, independente de ter ou não ocorrido algum erro. O objetivo do bloco FINALLY é liberar recursos que o programa utilizou, como procedures persistentes ou objetos alocados.
Abaixo um exemplo simples de um bloco DO com um bloco CATCH e um bloco FINALLY associados:
DO ON ERROR UNDO:
DEF VAR i AS INTEGER.
ASSIGN i = INTEGER('a').
CATCH erro AS Progress.Lang.ProError:
DISP "Esta mensagem só aparece se ocorrer um erro".
DISP erro:GetMessageNum(1).
DELETE OBJECT erro.
END CATCH.
FINALLY:
DISP "Esta mensagem sempre é exibida".
END FINALLY.
END.
Neste exemplo, ocorrerá um erro na linha do ASSIGN, pois o caracter ‘a’ não pode ser convertido para inteiro. A AVM intercepta esta condição, faz um UNDO do bloco e executa o bloco CATCH. Ao final do CATCH, o bloco FINALLY é executado. Se não houvesse uma condição de erro, o bloco CATCH seria ignorado, mas o FINALLY continuaria sendo executado.
O bloco CATCH definido no exemplo acima intercepta todos os tipos de erro. O Progress permite que o programador crie novos tipos de erros e intercepte somente um ou outro tipo. O tratamento estruturado de erros é muito mais abrangente do que o descrito neste post. O manual OpenEdge Development: Error Handling possui informações detalhadas sobre tratamento de erros na linguagem ABL / 4GL.