Перейти до вмісту

Керування потоком програми

Потоком ABAP-програми керують три речі: керівні структури (IF, CASE, цикли), виклики процедур (методи, функціональні модулі, підпрограми) і робота з винятками (TRY/CATCH, RAISE). На цій сторінці зібрано основні конструкції і їхні сучасні operand-аналоги (COND, SWITCH).

Умови будуються з порівнянь або предикатів, зʼєднуються операторами NOT, AND, OR. Для AND і OR можна явно дужкувати.

IF num = 1. ENDIF.
IF num = 1 AND flag = 'X'. ENDIF.
IF ( num = 1 AND flag = 'X' ) OR num = 99. ENDIF.
IF num BETWEEN 1 AND 3. ENDIF.
IF num IS INITIAL. ENDIF.
IF dref IS BOUND. ENDIF. " data reference валідна
IF <fs> IS ASSIGNED. ENDIF. " field symbol присвоєний
IF oref IS INSTANCE OF zcl_child. ENDIF. " тип обʼєкта
IF line_exists( itab[ key = val ] ). ENDIF.
IF contains( val = txt pcre = `\d+` ). ENDIF.

Оператори порівняння мають і символьні, і буквені форми: =/EQ, <>/NE, </LT, >/GT, <=/LE, >=/GE. Сучасний код пише символами.

Предикативний виклик методу

Section titled “Предикативний виклик методу”

Функціональний метод у логічному виразі — порівнюється з initial value свого типу:

IF some_method( ). " true, якщо результат != initial
IF some_method( ) IS NOT INITIAL. " еквівалент — але довший

xsdbool( ... ) повертає abap_bool (X/' ') від логічного виразу — зручно для присвоєння:

DATA(is_empty) = xsdbool( itab IS INITIAL ).

boolc( ... ) повертає string (X/' ') — небезпечний у порівняннях, бо повертає literal ' ' замість initial. У новому коді бери xsdbool.

Перевірка послідовно зверху вниз; виконується перший блок, умова якого істинна. Якщо жодна — ELSE (опційний).

IF sy-subrc = 0.
" знайдено
ELSEIF sy-subrc = 4.
" не знайдено
ELSE.
" інше
ENDIF.

Вкладеність можлива, але при 4+ рівнях — час виносити у метод.

Коли потрібен результат залежно від умови (а не виконання блоку):

DATA(greeting) = COND #(
WHEN sy-uzeit < '120000' THEN `Добрий ранок`
WHEN sy-uzeit < '180000' THEN `Добрий день`
ELSE `Добрий вечір` ).

# — тип виводиться з контексту (тут — string). Всі гілки після THEN мають бути приведеними до цільового типу.

Дискретне порівняння значення з набором варіантів. WHEN приймає кілька значень через OR:

CASE status.
WHEN 'N'. handle_new( ).
WHEN 'A' OR 'P'. handle_active_or_pending( ).
WHEN OTHERS. handle_unknown( ).
ENDCASE.

Спеціальна форма для перевірки типу object reference (RTTI):

DATA(descr) = cl_abap_typedescr=>describe_by_data( obj ).
CASE TYPE OF descr.
WHEN TYPE cl_abap_elemdescr. " елементарний
WHEN TYPE cl_abap_structdescr. " структура
WHEN TYPE cl_abap_tabledescr. " таблиця
WHEN OTHERS.
ENDCASE.

Аналог COND для дискретних випадків:

DATA(label) = SWITCH #( status
WHEN 'N' THEN `Новий`
WHEN 'A' THEN `Активний`
WHEN 'C' THEN `Закритий`
ELSE `Невідомий` ).

Виконується заданий раз або нескінченно (до EXIT). У тілі доступне sy-index з номером ітерації (починається з 1):

DO 5 TIMES.
out->write( sy-index ). " 1..5
ENDDO.
DO. " нескінченний — потрібен явний EXIT
IF some_condition. EXIT. ENDIF.
ENDDO.

Поки умова істинна. sy-index також заповнюється:

WHILE counter < 10.
counter += 1.
ENDWHILE.
ОператорДія
EXITповний вихід з циклу, програма продовжується після ENDDO/ENDWHILE/ENDLOOP
CONTINUEпропустити залишок ітерації, перейти до наступної
CHECK log_expяк CONTINUE, але умовно: якщо вираз хибний — пропустити
DO 10 TIMES.
CHECK sy-index MOD 2 = 0. " тільки парні
IF sy-index = 8. EXIT. ENDIF.
" обробка 2, 4, 6
ENDDO.

LOOP AT itab ... ENDLOOP — окрема тема, див. Внутрішні таблиці. На відміну від DO/WHILE, заповнюється sy-tabix (індекс рядка), а не sy-index.

FOR ... IN ... — ітерація як частина constructor expression (VALUE, REDUCE). Дає можливість побудувати таблицю/значення за один вираз замість циклу з APPEND:

DATA(doubled) = VALUE int_tab( FOR n IN nums ( n * 2 ) ).
DATA(total) = REDUCE i( INIT s = 0 FOR n IN nums NEXT s = s + n ).

Сучасний ABAP: вся модуляризація — у методах класів. Синтаксис і деталі — у ООП-сторінці (TBD).

Legacy, але досі широко використовується у Standard ABAP (не в ABAP Cloud):

CALL FUNCTION 'SOME_FM'
EXPORTING
input = value1
IMPORTING
output = result
EXCEPTIONS
not_found = 4
OTHERS = 8.
IF sy-subrc <> 0.
" обробка
ENDIF.

Для class-based exceptions — у TRY/CATCH:

TRY.
CALL FUNCTION 'SOME_FM'
EXPORTING input = value1
IMPORTING output = result.
CATCH cx_some_error INTO DATA(exc).
out->write( exc->get_text( ) ).
ENDTRY.

Динамічний виклик — імʼя FM у змінній + PARAMETER-TABLE:

DATA(fm) = 'SOME_FM'.
DATA(params) = VALUE abap_func_parmbind_tab(
( name = 'INPUT' kind = abap_func_exporting value = NEW string( `val` ) )
( name = 'OUTPUT' kind = abap_func_importing value = NEW string( ) ) ).
CALL FUNCTION fm PARAMETER-TABLE params.

Застаріла конструкція з доби до ABAP Objects. У новому коді не писати; зустрічається тільки у legacy та у специфічних SAP LUW-сценаріях (PERFORM ... ON COMMIT).

Миттєво виходить з поточної процедури. Для функціональних методів (з RETURNING параметром) — можна повернути вираз одразу:

METHODS multiply IMPORTING a TYPE i b TYPE i
RETURNING VALUE(result) TYPE i.
METHOD multiply.
RETURN a * b. " еквівалент: result = a * b. RETURN.
ENDMETHOD.

Зупиняє виконання на задану кількість секунд:

WAIT UP TO 3 SECONDS.

Потрібне рідко — у продакшні майже завжди вказує на архітектурну проблему (polling, race condition). Безпечно у тестах і демо.

Охоплено окремо на сторінці винятків (TBD). Коротко:

TRY.
some_risky_op( ).
CATCH cx_sy_conversion_no_number INTO DATA(exc).
" обробка конкретного типу
CATCH cx_root INTO DATA(any_exc).
" fallback
CLEANUP.
" виконається незалежно від того, чи був виняток
ENDTRY.
" Власне породження
RAISE EXCEPTION TYPE zcx_my_error
EXPORTING textid = zcx_my_error=>bad_input.

Адаптовано з 13_Program_Flow_Logic.md (Apache 2.0). Повний перелік нюансів — в оригіналі.