Obsolete language elements to hunt
What you'll learn
Hunt the obsolete constructs — MOVE, MOVE-CORRESPONDING, header lines, FORM/PERFORM, TABLES, DESCRIBE, double-negative CHECK, CONCATENATE — and swap each for its modern, inlinable equivalent.
- MOVE → b = a; MOVE-CORRESPONDING → CORRESPONDING #( ).
- LOOP AT itab. (header line) → LOOP AT itab ASSIGNING FIELD-SYMBOL(<fs>).
- OCCURS/header lines → typed tables; FORM/PERFORM → methods; drop TABLES outside dynpros.
Your logic is sound — most of modernizing ABAP is learning the modern spelling of things you already do well, not relearning the craft. It is largely a search-and-replace of constructs that are obsolete (or outright forbidden in classes and in Restricted ABAP) for their modern forms. MOVE a TO b becomes the assignment operator b = a; MOVE-CORRESPONDING becomes the constructor CORRESPONDING #( ); and a bare LOOP AT itab. with an implicit header line becomes LOOP AT itab ASSIGNING FIELD-SYMBOL(<fs>), because header lines are obsolete and illegal in classes.
Structural relics go too: OCCURS n WITH HEADER LINE becomes a typed DATA itab TYPE STANDARD TABLE OF ty WITH EMPTY KEY; FORM/PERFORM procedures become class methods; and the TABLES statement (outside dynpros) becomes an explicit local DATA declaration. These are not cosmetic — procedural forms and header lines are genuine Clean Core smells that block a package from going to ABAP Cloud.
Finally, prefer the expressive built-ins: DESCRIBE TABLE itab LINES n becomes n = lines( itab ); the double-negative CHECK NOT .. IS INITIAL becomes a positive IF .. IS NOT INITIAL; and CONCATENATE gives way to string templates. Each swap is shorter, inlinable, and easier to read at the call site.
Key points
- MOVE → b = a; MOVE-CORRESPONDING → CORRESPONDING #( ).
- LOOP AT itab. (header line) → LOOP AT itab ASSIGNING FIELD-SYMBOL(<fs>).
- OCCURS/header lines → typed tables; FORM/PERFORM → methods; drop TABLES outside dynpros.
- DESCRIBE TABLE ... LINES → lines( ); CHECK NOT .. IS INITIAL → IF .. IS NOT INITIAL.
- CONCATENATE → string templates.
Examples
Implicit header line plus DESCRIBE TABLE — obsolete, and the header line will not compile in a class.
ABAPloop at itab.
write itab-matnr.
endloop.
describe table itab lines lv_n.An explicit field symbol replaces the header line; lines( ) replaces DESCRIBE and is inlinable.
ABAPloop at itab assigning field-symbol(<row>).
out->write( <row>-matnr ).
endloop.
data(lv_n) = lines( itab ).A double negative plus CONCATENATE — both have clearer modern forms.
ABAPcheck not lv_name is initial.
concatenate lv_first lv_last into lv_full
separated by space.A positive condition and an inline template read directly.
ABAPif lv_name is not initial.
data(lv_full) = |{ lv_first } { lv_last }|.
endif.Source notes: clean-core-curriculum §3.1
Ask Claude
Build a prompt from this lesson + your question and open a fresh Claude chat with it pre-filled — handy for adapting a before/after pattern to your own object.