Yep, we already spilled the beans in our last blog which introduced the language element
While writing code in ABAP, we often would like to declare immutable variables instead of mutable variables to avoid mutable state, like overwritten results, any unwanted changes, or even security threads. The concept of immutable variables can also be referred to as static single assignment and has been wished for from the SAP Community here. Now, the keyword
To get a feeling when to use
The ABAP Programming Guidelines also offer a good and bad example to point out the efficient use of the declaration operator
Connecting this use case to the one from the blog about the keyword
Remember the quarterly orders of all customers? If not, no worries, this example is covered wholly. Below, you find the basic construct for the use case involving three methods representing the three examples.
For the first example, we get an inquiry to list all purchase orders made in the fourth quarter of the year 2021 sorted from newest date to oldest date. The result will be used for further processing, like determining customer benefits. The internal table is constructed in the method
In total, one inline declaration with
The result of the quarterly purchase orders example shows all purchases orders in the period from October to December 2021 from the newest date to the oldest date.
Orders of all customers in Quarter 4 2021:
For the second example, we'll switch to database access. The internal table, constructed in the former example, is now a database table (exemplified here as
This example demonstrates the use of the declaration operator
The result of the amount of customer orders example shows all customer IDs and the amount of purchase orders.
Customers and their amount of ordered items:
For the third example, you want to know the time and date when you last assigned the result set of the query from the previous example to the internal table
In this example, the inline declaration operator
The result of the last update example shows the time according to ISO 8601 and the date when the result set of the query of example two was last assigned to the internal table
Last change: 20220825 12:09:12 AM
Why is it
There was already lots of discussion going on about the naming of the keyword
In the beginning of the discussion regarding the static single assignment and the naming of the inline declaration operator,
Therefore, an immutable variable isn't a constant but a write-protected variable that is handled similar to other write-protected variables, like input parameters passed by reference or key fields of internal tables.
Like all other data declarations in ABAP, both constants and immutable variables are statically visible behind their declaration only, but dynamically available in the whole program. Let's look at an example:
The example shows some infamous ABAP behavior. Right at the beginning, two fields are assigned dynamically to two field symbols. The dynamic assignment is possible even though these fields are only declared at the bottom of the example:
0
222
The fundamental technical difference is that the values of constants are stored in the PXA and immutable variables are stored like other variables in the stack memory. Summarized, all differences are important for the naming of the inline declaration operator. The name
Looking at the list below, the most important take-aways for the declaration operator
The following two links refer to the ABAP Keyword Documentation:
You should now know how to use the new declaration operator
STEP for ABAP internal tables (SAP BTP ABAP Environment 2202). Nonetheless, if you haven't heard of it yet... Here's another new ABAP language element: It's FINAL! Available with ABAP Release 7.89, SAP BTP ABAP Environment 2208.Basics
While writing code in ABAP, we often would like to declare immutable variables instead of mutable variables to avoid mutable state, like overwritten results, any unwanted changes, or even security threads. The concept of immutable variables can also be referred to as static single assignment and has been wished for from the SAP Community here. Now, the keyword
FINAL is introduced as the declaration operator of a declaration expression FINAL(var) to declare an immutable variable var. The inline declaration with FINAL (for immutable variables) works similar to the inline declaration with DATA (for mutable variables). Assigning a value to an immutable variable is possible at exactly one write position in the current context. The value cannot be changed at other write positions. If you try other positions for a write access of an immutable variable, either a syntax error (if detected by the compiler) or the uncatchable exception MOVE_TO_LIT_NOTALLOWED_NODATA (if detected at runtime) will be raised. Want a quick overview? Scroll down or click here.ABAP Programming Guidelines
To get a feeling when to use
FINAL and when not, the ABAP Programming Guidelines offer guidance for you. The rule for immutable variables states:Whenever you want a variable to be filled at exactly one write position and to be read only at all other positions, use an immutable variable.
The ABAP Programming Guidelines also offer a good and bad example to point out the efficient use of the declaration operator
FINAL. Since we've already covered the basics, let's get straight to some examples and find out when to use an immutable variable.Use Case
Connecting this use case to the one from the blog about the keyword
STEP, we're back to purchase orders. For the use case of the previous blog, we imagined to work with customer data and purchase order data as one part of our daily work. Preparing for the tasks concerning our work, we constructed an internal table which represented a joined table of customer and purchase data. For this use case, we'll work with an internal table as well as with a database table. Even though the following examples might not necessarily be realistic, they emphasize the use of immutable variables in ABAP.Quarterly purchase orders
Remember the quarterly orders of all customers? If not, no worries, this example is covered wholly. Below, you find the basic construct for the use case involving three methods representing the three examples.
CLASS purchase_orders DEFINITION.
PUBLIC SECTION.
TYPES:
BEGIN OF customer_purchase,
cust_id TYPE c LENGTH 8,
cust_name TYPE string,
item_id TYPE c LENGTH 9,
purch_date TYPE datn,
proc_date TYPE datn,
END OF customer_purchase,
customer_purchases TYPE STANDARD TABLE OF customer_purchase
WITH EMPTY KEY.
METHODS quarterly_purchase_order.
METHODS customer_purchase_count.
METHODS last_change.
ENDCLASS.
CLASS purchase_orders IMPLEMENTATION.
"...
ENDCLASS.
START-OF-SELECTION.
DATA(inquiry) = NEW purchase_orders( ).
inquiry->quarterly_purchase_order( ).
inquiry->customer_purchase_count( ).
inquiry->last_change( ).
cl_demo_output=>display( ).For the first example, we get an inquiry to list all purchase orders made in the fourth quarter of the year 2021 sorted from newest date to oldest date. The result will be used for further processing, like determining customer benefits. The internal table is constructed in the method
quarterly_purchase_order and the orders table is filled according to the inquiry.CLASS purchase_orders IMPLEMENTATION.
"...
METHOD quarterly_purchase_order.
TYPES:
BEGIN OF order,
item_id TYPE c LENGTH 9,
purch_date TYPE datn,
proc_date TYPE datn,
END OF order.
DATA orders TYPE TABLE OF order.
DATA(customer_purchases) = VALUE customer_purchases(
( cust_id = '00000001' cust_name = `Customer A` item_id = '781029348'
purch_date = `20211108` proc_date = `20211109` )
( cust_id = '00000001' cust_name = `Customer A` item_id = '781028275'
purch_date = `20211117` proc_date = `20211118` )
( cust_id = '00000001' cust_name = `Customer A` item_id = '781029350'
purch_date = `20211203` proc_date = `20211206` )
( cust_id = '00000002' cust_name = `Customer B` item_id = '781029348'
purch_date = `20211207` proc_date = `20211208` )
( cust_id = '00000003' cust_name = `Customer C` item_id = '781029353'
purch_date = `20211215` proc_date = `20211216` )
( cust_id = '00000004' cust_name = `Customer D` item_id = '781029321'
purch_date = `20211215` proc_date = `20211216` )
( cust_id = '00000005' cust_name = `Customer E` item_id = '781029342'
purch_date = `20211216` proc_date = `20211217` ) ).
LOOP AT customer_purchases REFERENCE INTO FINAL(customer_purchase) STEP -1
WHERE purch_date <= `20211231` AND purch_date >= `20211001`.
orders = VALUE #( BASE orders
( item_id = customer_purchase->item_id
purch_date = customer_purchase->purch_date
proc_date = customer_purchase->proc_date ) ).
FINAL(quarter) = `Quarter 4 2021`.
ENDLOOP.
cl_demo_output=>write( |Orders of all customers in { quarter }:| ).
cl_demo_output=>write( orders ).
ENDMETHOD.
"...
ENDCLASS.In total, one inline declaration with
DATA and two inline declarations with FINAL were applied. The reasons might be obvious:DATA(customer_purchases): The declaration operatorFINALcould be used too but we expect that values might be inserted later on. You could argue to declare immutable variables as long as you really need mutable variables; in this example, we can be sure that the values of the internal table will change and thus we save the time of changing the variable later on.FINAL(customer_purchase): The first appearance of the declaration operatorFINALis inside aLOOP ATstatement afterINTO. UsingFINALinside a loop, a value is assigned to the variablevarmultiple times. This also shows that at runtime, multiple write accesses can be executed.FINAL(quarter): The second appearance of the declaration operatorFINALis for declaring a text string literal. Usually, strings are expressed as immutable: In ABAP, both mutable and immutable declarations are possible.
The result of the quarterly purchase orders example shows all purchases orders in the period from October to December 2021 from the newest date to the oldest date.
Orders of all customers in Quarter 4 2021:
| ITEM_ID | PURCH_DATE | PROC_DATE |
| 781029342 | 2021-12-16 | 2021-12-17 |
| 781029321 | 2021-12-15 | 2021-12-16 |
| 781029353 | 2021-12-15 | 2021-12-16 |
| 781029348 | 2021-12-07 | 2021-12-08 |
| 781029350 | 2021-12-03 | 2021-12-06 |
| 781028275 | 2021-11-17 | 2021-11-18 |
| 781029348 | 2021-11-08 | 2021-11-09 |
Amount of customer orders
For the second example, we'll switch to database access. The internal table, constructed in the former example, is now a database table (exemplified here as
db_customer_purchases). The inquiry is to count all purchase orders made by each customer and to store the entries in an internal table.CLASS purchase_orders IMPLEMENTATION.
"...
METHOD customer_purchase_count.
SELECT cust_id, COUNT(*) AS count
FROM db_customer_purchases
GROUP BY cust_id
ORDER BY cust_id
INTO TABLE @FINAL(customer_count).
cl_demo_output=>write( customer_count ).
ENDMETHOD.
"...
ENDCLASS.This example demonstrates the use of the declaration operator
FINAL when assigning the data of the result set to an internal table.The result of the amount of customer orders example shows all customer IDs and the amount of purchase orders.
Customers and their amount of ordered items:
| CUST_ID | COUNT |
| 00000001 | 3 |
| 00000002 | 1 |
| 00000003 | 1 |
| 00000004 | 1 |
| 00000005 | 1 |
Last update
For the third example, you want to know the time and date when you last assigned the result set of the query from the previous example to the internal table
customer_count.CLASS purchase_orders IMPLEMENTATION.
"...
METHOD last_change.
FINAL(time) = COND string(
LET t = '130000' IN
WHEN sy-timlo < t AND sy-timlo > '010000' THEN
|{ sy-timlo TIME = ISO } AM|
WHEN sy-timlo > t AND sy-timlo < '010000' THEN
|{ CONV t( sy-timlo - 12 * 3600 ) TIME = ISO } PM|
WHEN sy-timlo = '120000' THEN
`High Noon`
ELSE
`Error` ).
cl_demo_output=>write( |Last change: { sy-datlo } { time }| ).
ENDMETHOD.
ENDCLASS.In this example, the inline declaration operator
FINAL declares the variable time. The value of time is constructed with the conditional operator COND of a conditional expression. The example is based on an example of the ABAP Keyword Documentation. Using FINAL in this context emphasizes that expressions can be defined as values of immutable variables.The result of the last update example shows the time according to ISO 8601 and the date when the result set of the query of example two was last assigned to the internal table
customer_count.Last change: 20220825 12:09:12 AM
Why is it FINAL and not CONSTANT, CONST, or IMMUTABLE?
There was already lots of discussion going on about the naming of the keyword
FINAL in this blog. So, perhaps for some of you this might be the most anticipated section.In the beginning of the discussion regarding the static single assignment and the naming of the inline declaration operator,
CONST was favored over other names. Reasons being, for example, that there was already the statement CONSTANTS for declaring a constant data object or a constant and that there was already the addition FINAL for classes and methods. When getting to the details of the different names, there is, however, a difference between a data object declared as a constant and a variable declared as final:- Constant: Defined with the
CONSTANTSdeclaration statement and only one start value can be assigned with theVALUEaddition at compile time. When the program is executed, the value of a constant is stored unchangeable in the PXA. - Final: Defined at one write position, but multiple write accesses can be executed at runtime at this position. At runtime, the value of an immutable variable is not stored in the PXA.
Therefore, an immutable variable isn't a constant but a write-protected variable that is handled similar to other write-protected variables, like input parameters passed by reference or key fields of internal tables.
Fun fact
Like all other data declarations in ABAP, both constants and immutable variables are statically visible behind their declaration only, but dynamically available in the whole program. Let's look at an example:
METHOD fun_fact.
"Fun fact (the infamous ABAP behavior)
ASSIGN ('NUMBER1') TO FIELD-SYMBOL(<fs1>).
ASSIGN ('NUMBER2') TO FIELD-SYMBOL(<fs2>).
cl_demo_output=>new(
)->write( <fs1>
)->write( <fs2> )->display( ).
FINAL(number1) = 111.
CONSTANTS number2 TYPE i VALUE 222.
ENDMETHOD.The example shows some infamous ABAP behavior. Right at the beginning, two fields are assigned dynamically to two field symbols. The dynamic assignment is possible even though these fields are only declared at the bottom of the example:
number1 with the declaration operator FINAL and number2 with the statement CONSTANTS. What happens now is that both fields can be read (but not written) and accessed by using the field symbols before their declaration; the value of FINAL is set at the position of the FINAL operator, while the value of CONSTANTS is already stored in the PXA from the beginning. Thus, the result looks like the following:0
222
Summary
The fundamental technical difference is that the values of constants are stored in the PXA and immutable variables are stored like other variables in the stack memory. Summarized, all differences are important for the naming of the inline declaration operator. The name
CONST is out of discussion at this point for the reasons above and because it's more similar to CONSTANTS than to FINAL and some programming languages use CONST as a type qualifier. Overall, the name of the inline declaration operator should be short and known. In Java, for example, FINAL is used as a modifier for immutable variables. This is why IMMUTABLE is also out of discussion. Considering the definitions and other programming languages, the naming of FINAL is the logical consequence. However, if you still have any doubts about the naming, the comment section is always open for you.Quick Check
Looking at the list below, the most important take-aways for the declaration operator
FINAL are listed.- The declaration operator
FINALcan be used at the same positions as the declaration operatorDATAwith the only exception that the statementOPEN CURSORcannot be used to declare an immutable cursor. - Immutable variables are write-protected variables that can be assigned a value at one write position only, but there for multiple times.
- Immutable variables can make programs more robust and therefore, use
FINALas the first choice from now on.
The following two links refer to the ABAP Keyword Documentation:
Further information
You should now know how to use the new declaration operator
FINAL in your projects. Use FINAL for declaring immutable variables. The examples given in this blog are intended for demonstration purposes only. Did you notice another new language element and are you excited to use the new declaration operator FINAL? Write your thoughts in the comment section. Don’t miss out on new language elements and follow my profile (lenapadeken) for similar blog posts.