Now accepting guest editorial from SAP, Oracle, Workday and ServiceNow practitioners.Pitch a guide
The Sign-Off Table

Lesson 2 of 6

Inline declarations and string templates

11 min

Listen to this lesson

0:00 / 11:45

Inline declarations remove the block of DATA statements at the top of every classic method. You declare a variable where it first receives a value, and its type comes from that value. String templates replace CONCATENATE and WRITE ... TO for building text. Together they change how almost every line of ABAP looks, so this lesson covers them first, including the traps that catch classic developers.

Inline declarations

WhereClassicModern
AssignmentDATA lv_deposit TYPE p LENGTH 15 DECIMALS 2.
lv_deposit = lv_qty * lv_rate.
DATA(deposit) = quantity * rate.
Method resultDATA lo_calc TYPE REF TO zcl_cmc_core_deposit.
CREATE OBJECT lo_calc.
DATA(calc) = NEW zcl_cmc_core_deposit( ).
Loop work areaDATA ls_agr LIKE LINE OF lt_agr.
LOOP AT lt_agr INTO ls_agr.
LOOP AT agreements INTO DATA(agr).
Field symbolFIELD-SYMBOLS <ls_agr> LIKE LINE OF lt_agr.
LOOP AT lt_agr ASSIGNING <ls_agr>.
LOOP AT agreements ASSIGNING FIELD-SYMBOL(<agr>).
SQL targetSELECT ... INTO TABLE lt_agr.SELECT ... INTO TABLE @DATA(agreements).
Read once, never changeNot possibleFINAL(customer) = agr-customer.

Inline declarations at the common write positions. Code is shown with a line break where the classic form needs two statements.

FINAL( ) declares an immutable variable: it can be written at exactly one position, and any other write is a syntax error or a runtime error. SAP introduced it in ABAP release 7.89 (SAP BTP ABAP environment 2208), which corresponds to ABAP Platform 2022 on premise (7.57); check your release. Kenji's team uses FINAL by default and DATA only when the value really changes, which makes the variables that change stand out.

Typing traps

The type of an inline variable is derived from the right-hand side. That is precise, and it surprises people:

  • DATA(count) = 0. gives type i. A later count = count + 0.5 truncates silently.
  • DATA(code) = 'X'. gives type c length 1. Assigning 'OPEN' later stores 'O'.
  • DATA(name) = `Great Lakes`. with backquotes gives type string; with single quotes, a fixed-length c field.
  • DATA(deposit) = quantity * rate. takes the calculation type of the expression, which may not be the packed type your table field uses. When the type matters, use CONV or declare explicitly.
Kenji's rule for inline declarations: FINAL by default, DATA when the value changes, explicit types when the right side does not make them obvious.
The Sign-Off Table · thesignofftable.com/academy/sap-abp-206

Inline declarations also work in method calls with EXPORTING/IMPORTING parameters: calc->get_rate( EXPORTING product = item-product IMPORTING rate = DATA(rate) ). For functional methods, prefer returning values, so the call itself is the right-hand side: DATA(rate) = calc->get_rate( item-product ). Clean ABAP recommends returning one value rather than many exporting parameters, which also makes the code easier to test: the test simply asserts the returned value.

Scope: inline is not local to the block

A variable declared inline in a LOOP or IF is visible in the whole method from the point of declaration, not only inside the block. Declaring DATA(agr) in two loops in the same method is a syntax error. The second loop simply reuses agr, or better, the method is split. Long methods with many inline variables are a sign that the method does too much.

String templates

A string template sits between vertical bars and embeds expressions in curly braces: |Deposit { deposit } USD for { customer }|. Inside the braces you can put any expression, including method calls, and format it with options.

NeedTemplateResult (Contoso data)
Simple text|Agreement { agr_id } is { status }|Agreement 100045 is OPEN
Strip leading zeros|{ customer ALPHA = OUT }|17100001 (stored as 0017100001)
Add leading zeros|{ customer ALPHA = IN }|0017100001
User date format|{ valid_to DATE = USER }|Date in the user's format
Number format|{ deposit NUMBER = USER }|540.00 in the user's decimal notation
Fixed width|{ product WIDTH = 12 }|CMC-ALT-100 padded to 12 characters
Concatenatetext = text && | { product }|.Appends the product

Common string template options. Check the formatting options in the keyword documentation for your release.

  1. FindCONCATENATE 'Deposit' lv_amount 'USD' INTO lv_text SEPARATED BY space
  2. Noticelv_amount is packed; CONCATENATE needs character-like operands, so the old code first moved it with WRITE ... TO
  3. Writetext = |Deposit { amount } USD|.
  4. CheckDecimal separator and format: add NUMBER = USER if users see the text
  5. TestUnit test asserts the exact text for 540.00
How Kenji refactors one CONCATENATE statement into a string template.
The Sign-Off Table · thesignofftable.com/academy/sap-abp-206

What goes wrong in testing

  • Format drift. WRITE ... TO applied user formatting; a plain template does not. A text that showed 540,00 for a German-format user now shows 540.00. Unit tests with fixed expected strings catch this.
  • Leading zeros. A refactored message prints 0017100001 where the old code printed 17100001. Add ALPHA = OUT.
  • Truncation. A DATA(code) = 'X' later assigned a longer value cuts it off without an error.
  • Shadowed names. Inline variables named like old globals (lv_ prefixes) make reviews harder; Clean ABAP recommends dropping Hungarian prefixes in new code.
A test that pins the exact text comes first; then the refactoring cannot change formatting unnoticed.
The Sign-Off Table · thesignofftable.com/academy/sap-abp-206

What would you do?

Ana, the accounts payable clerk, reports that a refunded deposit message now shows the customer as 0017100001. Kenji had refactored the message from WRITE ... TO into a string template. What is the fix?

Key points
  • Declare variables where they get their first value; use FINAL( ) when the value never changes.
  • Inline types come from the right-hand side: watch literals and calculation types.
  • Inline variables are visible in the whole method after their declaration.
  • String templates replace CONCATENATE and WRITE ... TO; add ALPHA, DATE and NUMBER options where formatting matters.

Check your understanding · not graded

Lesson check

  1. 1. What type does DATA(count) = 0. give count?

  2. 2. What does FINAL( ) declare?

  3. 3. Which template prints customer 0017100001 as 17100001?

  4. 4. Kenji declares DATA(agr) in two loops in one method. What happens?

  5. 5. Why might a refactored text show 540.00 where users saw 540,00?