Guia de introdução
Aplicação de técnicas básicas e conceitos
Trabalhar com classes locais
Ler dados do banco de dados
Trabalhar com objetos de dados estruturados
Trabalhar com tabelas internas complexas
Implementar atualizações do banco de dados utilizando business objects
Descrição do modelo de programação de aplicativos ABAP RESTful

Utilizar estruturas de controle no ABAP

Objectives

After completing this lesson, you will be able to:
  • Implementar ramificação condicional.
  • Tratar exceções.
  • Implementar iterações.

Ramificação condicional

Uma ramificação condicional é uma estrutura de controle que permite que você torne a execução do código dependente de condições lógicas.

A ramificação condicional mais comum consiste em um par de palavras-chave IF e ENDIF. O bloco de código entre IF e ENDIF só é executado se a condição após IF for cumprida.

Você pode adicionar mais blocos de código ampliando a estrutura IF … ENDIF com até uma palavra-chave ELSE e um número arbitrário de palavras-chave ELSEIF. Ao adicionar a palavra-chave ELSE, você garante que sempre é executado exatamente um dos blocos de código. Se ELSE estiver em falta, pode acontecer que nenhum dos blocos de código seja executado.

O bloco de código a ser executado é determinado da seguinte forma:

  • Primeiro, a condição IF é avaliada. Se estiver preenchido, o bloco de código relacionado é executado e o programa continua após ENDIF.
  • Somente se a condição IF não for cumprida, a condição após o primeiro ELSEIF será avaliada. Se estiver preenchido, o bloco de código relacionado é executado e o programa continua após ENDIF.
  • Isso é feito consecutivamente para todas as condições ELSEIF. Se nenhuma das condições for cumprida e a estrutura contiver ELSE, o bloco de código após ELSE é executado. Caso contrário, não é executado nenhum dos blocos de código.

Dica

Ao contrário de muitas outras linguagens de programação, o ABAP requer um delimitador (.) após cada uma das condições lógicas e mesmo após a palavra-chave ELSE.

As condições lógicas são uma combinação de comparações, operações lógicas, expressões e funções que o sistema de tempo de execução avalia para decidir se a condição é verdadeira ou falsa.

O caso de uso mais comum para condições lógicas é após as palavras-chave IF ou ELSEIF em um IF ... ENDIF. estrutura.

O primeiro exemplo é uma comparação simples: a condição é verdadeira se os dois objetos de dados x e y tiverem o mesmo valor.

O segundo exemplo é um pouco mais sofisticado: Ou o valor de x é maior ou igual a y e menor que o dobro do valor de y ou é menor ou igual a y e maior que o dobro do valor de y.

O terceiro exemplo usa a função aritmética abs( ) e a expressão lógica BETWEEN <expression1> AND <expression2>. A condição é verdadeira se o valor absoluto de x estiver entre o valor absoluto de y e o valor absoluto de duas vezes y.

Para comparações de valores simples, você pode utilizar os operadores =, <>, >, <, >= e <=. Você não só pode comparar os valores de objetos de dados, mas também os valores de muitas outras expressões, como a expressão aritmética 2 * y no exemplo.

Nota

O ABAP utiliza o mesmo símbolo (=) para avaliações e para comparações de valores. A distinção é feita com base na posição.

Você pode usar os operadores AND e OR para combinar expressões lógicas e o operador NOT para negar uma expressão. Sem parênteses, NÃO liga mais forte do que AND e AND mais forte do que OR.

O ABAP conhece algumas expressões lógicas especiais:

  • <objeto de dados> IS INITIAL é verdadeiro se <objeto de dados> contiver o respectivo valor inicial específico de tipo
  • <objeto de dados> NÃO É INICIAL é verdadeiro se <objeto de dados> contiver um valor diferente do valor inicial específico de tipo
  • <objeto de dados> ENTRE <expressão1> E <expressão2>

Algumas funções ABAP especiais são funções de predicado. Isso significa que elas próprias são condições lógicas. Contém( ) é uma função que compara valores em forma de caractere e line_exists( ) executa uma verificação de existência para uma linha em uma tabela interna.

Uma segunda técnica para ramificação condicional é o CASE … WHEN .. Estrutura de controle ENDCASE.

Ramificação condicional com CASE .. ENDCASE é um caso especial da ramificação mais geral com IF … ENDIF. Você pode usar CASE em situações em que a ramificação depende do valor de um único objeto de dados, que você compara consecutivamente com um conjunto de valores possíveis, usando uma comparação igual a cada vez.

No exemplo, o valor do número do objeto de dados é comparado com os valores 1 e 2. Se o valor for igual a 1, <code_block_1> for executado e se o valor euqals 2, <code_blocl_2> for executado. Para qualquer outro valor, é executado o bloco de código após WHEN OTHERS.

Qualquer ramificação condicional com CASE … ENDCASE também pode ser implementada com uma estrutura IF … ENDIF. Isso é ilustrado com o exemplo à direita.

Dica

Você deve usar CASE … ENDCASE ao lidar com o caso especial para aumentar a legibilidade do seu código.

Experimente: ramificação condicional

  1. Como no primeiro exercício deste curso, crie uma nova classe global que implemente a interface IF_OO_ADT_CLASSRUN.
  2. Copie o seguinte snippet de código para a parte de implementação do método if_oo_adt_classrun~main( ):
    Code Snippet
    1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
    * Declarations ********************************************************************** CONSTANTS c_number TYPE i VALUE 0. * CONSTANTS c_number TYPE i VALUE 1. * CONSTANTS c_number TYPE i VALUE 2. * CONSTANTS c_number TYPE i VALUE -1. * CONSTANTS c_number TYPE i VALUE -2. * Example 1: Simple IF ... ENDIF. ********************************************************************** out->write( `--------------------------------` ). out->write( `Example 1: Simple IF ... ENDIF.` ). out->write( `-------------------------------` ). IF c_number = 0. out->write( `The value of C_NUMBER equals zero` ). ELSE. out->write( `The value of C_NUMBER is NOT zero` ). ENDIF. * Example 2: Optional Branches ELSEIF and ELSE ********************************************************************** out->write( `--------------------------------------------` ). out->write( `Example 2: Optional Branches ELSEIF and ELSE` ). out->write( `--------------------------------------------` ). IF c_number = 0. out->write( `The value of C_NUMBER equals zero` ). ELSEIF c_number > 0. out->write( `The value of C_NUMBER is greater than zero` ). ELSE. out->write( `The value of C_NUMBER is less than zero` ). ENDIF. * Example 3: CASE ... ENDCASE ********************************************************************** out->write( `---------------------------` ). out->write( `Example 3: CASE ... ENDCASE` ). out->write( `---------------------------` ). CASE c_number. WHEN 0. out->write( `The value of C_NUMBER equals zero` ). WHEN 1. out->write( `The value of C_NUMBER equals one` ). WHEN 2. out->write( `The value of C_NUMBER equals two` ). WHEN OTHERS. out->write( `The value of C_NUMBER equals non of the above` ). ENDCASE.
  3. Pressione CTRL + F3 para ativar a classe e F9 para executá-la como um aplicativo de console.
  4. Analise a saída do console. Jogue com o código-fonte para se familiarizar com os conceitos; Não comente diferentes declarações da constante c_number com valores diferentes para ver quais ramificações do código são executadas.

Tratamento de exceções

Exceções

No ABAP, uma exceção é uma situação de erro durante a execução de um programa ABAP. Uma exceção é criada pelo código que detecta a situação de erro.

Dependendo de quem aciona a exceção, distinguimos entre exceções do sistema e exceções de aplicação.

Sem outras medidas, as exceções resultam em erros em tempo de execução. Um erro em tempo de execução cancela o programa e é documentado por padrão em um dump breve.

Você pode evitar o erro em tempo de execução se a exceção em questão for catchable. Uma exceção interceptável pode ser tratada no programa utilizando as instruções TRY … CATCH … ENDTRY.

Todas as exceções de aplicação e muitas exceções do sistema são catchable. Mais tarde, neste curso, você aprenderá a criar exceções de aplicativo. Neste ponto, vamos nos concentrar no tratamento de exceções de sistema catchable.

O vídeo a seguir mostra alguns exemplos de erros em tempo de execução.

Tratamento de exceções

Para evitar que um programa seja cancelado devido a uma exceção interceptável, você deve cercar o código de onde a exceção tem origem com as instruções TRY e ENDTRY. Ao fazer isso, o código se torna parte do bloco TRY da estrutura TRY … ENDTRY.

Antes da instrução ENDTRY, você deve adicionar uma instrução CATCH seguida pelo ID da exceção que deseja tratar. Opcionalmente, você pode adicionar mais de uma instrução CATCH para tratar várias exceções diferentes. Cada instrução CATCH deve ser seguida por código para tratar essa exceção. Este código é chamado de bloco CATCH.

Quando a execução do programa atinge a instrução TRY, ela continua com o código no bloco TRY. Três coisas podem acontecer:

  1. Se não for criada nenhuma exceção durante o bloco TRY, os blocos CATCH são ignorados. A execução continua após a instrução ENDTRY.
  2. Se for criada uma exceção durante o bloco TRY, para o qual existe um CATCH correspondente, a execução do bloco TRY é cancelada e o bloco CATCH para esta exceção é executado. Em seguida, a execução continua após a instrução ENDTRY.
  3. Se for criada uma exceção durante o bloco TRY para o qual não existe CATCH correspondente, o programa é cancelado com um erro em tempo de execução.

Agora que você aprendeu sobre exceções, vamos ver como lidar com elas.

Testar: tratamento de exceções

  1. Como no primeiro exercício deste curso, crie uma nova classe global que implemente a interface IF_OO_ADT_CLASSRUN.
  2. Copie o seguinte snippet de código para a parte de implementação do método if_oo_adt_classrun~main( ):
    Code Snippet
    1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
    * Declarations ********************************************************************** DATA result TYPE i. DATA numbers TYPE TABLE OF i. * Preparation ********************************************************************** APPEND 123 TO numbers. * Example 1: Conversion Error (no Number) ********************************************************************** CONSTANTS c_text TYPE string VALUE 'ABC'. * CONSTANTS c_text TYPE string VALUE '123'. out->write( `---------------------------` ). out->write( `Example 1: Conversion Error` ). out->write( `---------------------------` ). TRY. result = c_text. out->write( |Converted content is { result }| ). CATCH cx_sy_conversion_no_number. out->write( |Error: { c_text } is not a number!| ). ENDTRY. * Example 2: Division by Zero ********************************************************************** CONSTANTS c_number TYPE i VALUE 0. * CONSTANTS c_number TYPE i VALUE 7. out->write( `---------------------------` ). out->write( `Example 2: Division by Zero` ). out->write( `---------------------------` ). TRY. result = 100 / c_number. out->write( |100 divided by { c_number } equals { result }| ). CATCH cx_sy_zerodivide. out->write( `Error: Division by zero is not defined!` ). ENDTRY. * Example 3: Itab Error (Line Not Found) ********************************************************************** CONSTANTS c_index TYPE i VALUE 2. * CONSTANTS c_index TYPE i VALUE 1. out->write( `-------------------------` ). out->write( `Example 3: Line Not Found` ). out->write( `-------------------------` ). TRY. result = numbers[ c_index ]. out->write( |Content of row { c_index } equals { result }| ). CATCH cx_sy_itab_line_not_found. out->write( `Error: Itab has less than { c_index } rows!` ). ENDTRY. * Example 4: Combination of Different Exceptions ********************************************************************** * CONSTANTS c_char TYPE c LENGTH 1 VALUE 'X'. * CONSTANTS c_char TYPE c length 1 value '0'. CONSTANTS c_char TYPE c LENGTH 1 VALUE '1'. * CONSTANTS c_char TYPE c length 1 value '2'. out->write( `----------------------` ). out->write( `Example 4: Combination` ). out->write( `----------------------` ). TRY. result = numbers[ 2 / c_char ]. out->write( |Result: { result } | ). CATCH cx_sy_zerodivide. out->write( `Error: Division by zero is not defined` ). CATCH cx_sy_conversion_no_number. out->write( |Error: { c_char } is not a number! | ). CATCH cx_sy_itab_line_not_found. out->write( |Error: Itab contains less than { 2 / c_char } rows| ). ENDTRY.
  3. Pressione CTRL + F3 para ativar a classe e F9 para executá-la como um aplicativo de console.
  4. Analise a saída do console. Jogue com o código-fonte para se familiarizar com o conceito:
    • Comente o tratamento de exceções para que o sistema gere um erro em tempo de execução.
    • Modifique os valores das constantes c_number, c_text, c_index e c_charde modo que não sejam criadas exceções.

Iterações

As iterações são estruturas de controle que definem um bloco de código que é executado várias vezes.

A forma mais simples de iteração consiste em um bloco de código cercado por um par de instruções DO e ENDDO. Sem outras medidas, isso estabelece um loop infinito que deve ser evitado por uma das seguintes possibilidades:

Número especificado de iterações

Ao ampliar a instrução DO com uma expressão de número inteiro seguida pela palavra-chave TIMES, você pode indicar explicitamente a frequência com que o bloco de código deve ser iterado. A expressão inteira pode ser tão simples quanto literal numérica, mas também os cálculos aritméticos são uma opção. Se o valor da expressão for igual a 0, o bloco de código entre DO e ENDDO não é executado e o programa continua imediatamente com o código após ENDDO.

Cancelar com base em uma condição lógica

Você pode cancelar uma iteração a qualquer momento utilizando a instrução EXIT. Em seguida, o programa continua com o código após ENDDO. Esteja ciente de que fora das iterações EXIT tem um efeito diferente. Aí, ele cancela o processamento do bloco de processamento atual, por exemplo, o método atual.

Normalmente, EXIT é rodeado por IF e ENDIF para encerrar a iteração dependendo de uma condição de cancelamento. Esteja ciente de que essas iterações podem se transformar em loops infinitos, se a condição de cancelamento nunca se tornar verdadeira.

É claro que é possível combinar as duas técnicas, ou seja, especificar explicitamente o número de iterações e depois deixar a iteração com EXIT. Assim, o número de iterações se torna um número máximo que pode não ser atingido no momento da execução.

Com base em uma tabela interna

Um terceiro tipo de iteração é a estrutura LOOP … ENDLOOP que é utilizada para ler consecutivamente as linhas de uma tabela interna. Aqui, o número de iterações é determinado pelo número de linhas na tabela interna.

No bloco de código entre DO e ENDDO, você pode implementar acessos de leitura ao objeto de dados integrado ABAP sy-index. Esta variável de número inteiro serve como um contador de iteração, ou seja, o tempo de execução ABAP aumenta em um no início de cada nova iteração.

Em contradição com o que você pode estar acostumado de outras linguagens de programação, sy-index começa com o valor 1 durante a primeira iteração.

A variável integrada ABAP sy-tabix pode cumprir um objetivo semelhante para iterações com LOOP. Mas considere que, estritamente falando, sy-tabix não é realmente um contador, mas identifica a posição da linha da tabela que é processada na iteração atual. Posteriormente, veremos a diferença quando nem todas as linhas de uma tabela interna forem processadas em uma estrutura LOOP … ENDLOOP.

Experimente: iterações

  1. Como no primeiro exercício deste curso, crie uma nova classe global que implemente a interface IF_OO_ADT_CLASSRUN.
  2. Copie o seguinte snippet de código para a parte de implementação do método if_oo_adt_classrun~main( ):
    Code Snippet
    12345678910111213141516171819202122232425262728293031323334353637383940414243
    * Declarations ********************************************************************** CONSTANTS c_number TYPE i VALUE 3. * CONSTANTS c_number TYPE i VALUE 5. * CONSTANTS c_number TYPE i VALUE 10. DATA number TYPE i. * Example 1: DO ... ENDDO with TIMES ********************************************************************** out->write( `----------------------------------` ). out->write( `Example 1: DO ... ENDDO with TIMES` ). out->write( `----------------------------------` ). DO c_number TIMES. out->write( `Hello World` ). ENDDO. * Example 2: DO ... ENDDO with Abort Condition ********************************************************************** out->write( `-------------------------------` ). out->write( `Example 2: With Abort Condition` ). out->write( `-------------------------------` ). number = c_number * c_number. " count backwards from number to c_number. DO. out->write( |{ sy-index }: Value of number: { number }| ). number = number - 1. "abort condition IF number <= c_number. EXIT. ENDIF. ENDDO.
  3. Pressione CTRL + F3 para ativar a classe e F9 para executá-la como um aplicativo de console.
  4. Analise a saída do console. Jogue com o código-fonte para se familiarizar com os conceitos; Não comente diferentes declarações da constante c_number para ver como os diferentes valores afetam o resultado.