IQX ABAP standards / conventions / best practice guide

Naming guidelines

At IQX, we provide solutions to numerous clients. Chances are that every one of these clients have their own ABAP naming standards / conventions. When we work on a client site (or system), we will conform to the provided guidelines.

In the absence of client guidelines or in the development of IQX packaged Solutions, we do not follow an exhaustive list of guidelines / standards - we believe it is more important to make sure that the names of all development objects are descriptive and appropriate, and conforms to the general guidelines provided by SAP. For this reason, we do not enforce particular standards for the naming of Dictionary objects like Data Elements, Domains, etc.

There are however a few standards or conventions we feel, when applied correctly, will increase readability and understanding when reading our code - these are as follows (where in every example below, XXX will be replaced with a meaningful name/description, and where a ‘Z’ is shown a ‘Y’ can be used instead):

Object / Namespace

IQX namespaceCustomer namespace (Z or Y)

Structure (SE11 or defined in code)

/IQX/XXX_ST

ZXXX_ST

Table Type (SE11 or defined in code)

/IQX/XXX_TT

ZXXX_TT

Database Tables (SE11)

/IQX/XXX

ZXXX

View  (SE11)

/IQX/V_XXX

ZV_XXX or ZVXXX

Class

/IQX/CL_XXX

ZCL_XXX

OData Model Provider Class

/IQX/CL_XXX_MPC

ZCL_XXX_MPC

OData Data Provider Class

/IQX/CL_XXX_DPC

ZCL_XXX_DPC

OData Model

/IQX/XXX_MDL

ZXXX_MDL

OData Service

/IQX/XXX_SRV

ZXXX_SRV


For every client project we will create a Development Package with the following naming convention - ZIQX_YYY_<Project>, where YYY represents a 3-character IQX client ID.


In our ABAP code, we will name our variables as follows, where xxx will be replaced with a meaningful name:

Global variables

Globally visible in Class, Function Group, Report / Program / Module Pool, etc.

Simple variable

gv_xxx

Structure

gs_xxx

Internal table

gt_xxx

Reference Object (reference to a Class or Interface)

go_xxx

Local variables

Variable that has limited scope inside a Function Module, FORM routine, Class method, etc.

Simple variable

lv_xxx

Structure

ls_xxx

Internal table

lt_xxx

Reference Object (reference to a Class or Interface)

lo_xxx

Parameters - importing

USING parameters in a FORM routine, IMPORTING parameters in Function Modules, Class methods, etc.

Simple variable

iv_xxx

Structure

is_xxx

Internal table

it_xxx

Reference Object (reference to a Class or Interface)

io_xxx

Parameters - exporting

EXPORTING parameters in Function Modules, Class methods, etc.

Simple variable

ev_xxx

Structure

es_xxx

Internal table

et_xxx

Reference Object (reference to a Class or Interface)

eo_xxx

Parameters - changing

CHANGING parameters in a FORM routine.

Simple variable

cv_xxx

Structure

cs_xxx

Internal table

ct_xxx

Reference Object (reference to a Class or Interface)

co_xxx

Parameters - returning

RETURNING parameters in Class methods (Functional methods).

Simple variable

rv_xxx

Structure

rs_xxx

Internal table

rt_xxx

Reference Object (reference to a Class or Interface)

ro_xxx

Development guidelines

There are a number of guidelines we feel improve efficiency, productivity and/or the ability to read, understand and maintain ABAP code. These are:

GuidelineJustification
Internal tables
Where possible, use FIELD-SYMBOLS (LOOP AT - ASSIGNING) instead of work areas (LOOP AT - INTO) when looping over, and READ - ASSIGNING instead of READ - INTO when reading the contents of a table.

There are no disadvantages in using a field-symbol instead of a work area. The benefits are:

  • efficiency - no internal transfer of data in memory (especially evident with large data sets/records)
  • no need to modify the table from the work area - field-symbol provides direct access to the data in the table.

Note: in very specific instances where you want to loop through a table and NOT change the contents of the table, but you do want to modify some of the table fields temporarily, you may want to consider using LOOP - INTO instead of FIELD-SYMBOLS as the latter option will change the contents of the table.

Use BINARY SEARCH where possible when searching internal tables in ABAP.

Remember: sort your table before the search.

Efficiency - search is vastly more efficient, with exponential improvements the larger the table gets.

When using FOR ALL ENTRIES to compare against an internal table in a SELECT statement, ensure that you have checked that the internal table is not empty before executing the SELECT. Checking SY-SUBRC = 0 (for a prior SELECT that fills the comparison table) or checking the contents (# of rows) of the internal table should suffice.

Furthermore, please ensure that you delete duplicate entries in the 'comparison' table as this might result in an inefficient search.

Remember:

You may have to code two versions of the SELECT, inside an IF/ELSE construct - one where the internal table used for comparison is empty (without the FOR ALL ENTRIES addition) and another where the internal table does contain records (with the FOR ALL ENTRIES addition).

Note: Consider using a Range (TYPE RANGES OF) with an IN clause in your SELECT, instead of using FOR ALL ENTRIES. This reduces the need to check for an empty table, but there are size limitations to consider for the Range object. This may work initially (especially as DEV/QAS only has limited data in most instances) and only later become apparent (potentially only in PRD) as the datasets grow over time.

Efficiency - if the internal table is empty then the entire database table will be searched - the FOR ALL ENTRIES addition will not provide any benefit / filtering at all. From the SAP help website:

"If the internal table itab is empty, the entire WHERE condition is ignored. This means that none of the rows in the database table are skipped...."

When working with nested tables, use of the parallel cursor technique is recommended.

See example / explanation at:

https://wiki.scn.sap.com/wiki/display/Snippets/ABAP+Code+for+Parallel+Cursor+-+Loop+Processing

Remember: sort both the tables in the same (at least primary) sort order before the looping / search commences.

Efficiency - significant reduction in reading times of the 2nd (nested) table. Especially important if the nested table has a large number of rows.

ABAP syntax / compatability - as a general rule, when developing FAB / OneList Adapters / CAPEX or other packaged solutions, assume that not all clients will have the latest ABAP syntax available.

Please do not use the latest ABAP functionality/keywords as it will cause syntax errors during deployment, leading to immediate loss of confidence in the product by the client Basis / IT team(s).

When developing directly on the client system (Z) this restriction does not apply.

To avoid syntax errors during deployment of FAB / OneList Adapters / CAPEX or other packaged solutions
Authorisations

Apply authorisations before extracting data where (possibly) large data sets may be extracted for reporting, monitoring apps, search helps, etc.

For example, in a monitoring app, let's say that we want to only present instances to the user pertaining to the Company Codes that a user is allowed to see.

Suggested steps:

  1. Ensure all the objects that have to be checked against are recorded in the /IQX/FORMHD_INST (instance header) table, using the search fields provided. In this example, store the Company Code in one of the search fields when saving the instance.
    Note: If the number of objects to be checked exceeds the number of search fields (5) then consider adding an Append structure for the remaining objects to be checked.
  2. Repeat the following steps for each object to be checked:
    1. Determine a suitable Authorisation Object to check against. For this example, we need to find a suitable Authorisation Object for Company Codes.
    2. Use the Function Module SUSR_USER_AUTH_FOR_OBJ_GET to determine the list of allowed Company Codes for the user in question, and add the allowed Company Codes to a RANGES object.
  3. Execute a SELECT statement (selecting from the instance header table), using the RANGES object to only read the records that match the allowed Company Codes in the RANGES object (comparing against the Search Field populated on save). The SELECT statement may have to cater for a number of RANGES objects (as required) against more than one search field in the instance header table, depending on how many authorisations objects have to be checked against.



When working with reports, monitoring apps and any situation where a large data set needs to be extracted, we want to prevent the scenario where we retrieve all data (ignoring authorisations) and then applying the authorisations after the fact. This approach will be inefficient, as data will be extracted that may never be presented to the users, since they may not be authorised for large sections of that data set.

The same concept may be applied where we only want to present the relevant (allowed) values to a user in a Search Help.