Best Practices & Common Pitfalls

42.1 Best practices

Design: object-oriented, small classes with single responsibility; interfaces at boundaries; dependency injection for testability.

Data access: code-to-data (CDS, SQL expressions, joins); select only needed columns; one database round trip instead of many.

Modern syntax: inline declarations, constructor expressions, string templates, table expressions, NEW, xsdbool( ) — but keep readability first.

Robustness: check sy-subrc after every statement that sets it; handle exceptions at the right level; never leave empty CATCH blocks.

Security: AUTHORITY-CHECK for every sensitive operation; escape dynamic SQL (CL_ABAP_DYN_PRG); no hard-coded users/passwords; validate file paths.

Transport hygiene: small, meaningful transports; release in dependency order; no $TMP objects in productive logic.

Texts: use text symbols and message classes (translatable), never hard-coded UI texts.

Clean core: prefer released APIs, BAdIs and RAP extensions over modifications or implicit enhancements.

Testing and quality: ABAP Unit for business logic, ATC on every transport, code reviews (abapGit/gCTS pull requests).

Documentation: ABAP Doc comments ("!) on public methods; keep the *why* in comments.

42.2 Common pitfalls

FOR ALL ENTRIES with an empty driver table Selects the entire table, huge runtime

Check IS NOT INITIAL before the SELECT SELECT inside LOOP Slow programs, many DB round trips

Join, CDS view, FOR ALL ENTRIES, or select from @itab Not checking sy-subrc

Stale work-area data used after failed READ/SELECT Check sy-subrc or use line_exists() / OPTIONAL Table expression on missing row Dump CX_SY_ITAB_LINE_NOT_FOUND

VALUE #( itab[ … ] OPTIONAL ), line_exists( ), or TRY … CATCH

Linear READ TABLE on large standard tables O(n²) nested processing

Hashed/sorted tables, secondary keys, BINARY SEARCH after SORT BINARY SEARCH on an unsorted table Rows not found randomly

SORT by the same key first, or use a sorted table AT NEW on unsorted data or wrong column order Wrong group breaks

SORT first; control field must be leftmost relevant column; or use GROUP BY

COMMIT WORK inside BAdIs, user exits, or RAP handlers Inconsistent data, dumps Let the caller/framework commit Forgetting BAPI_TRANSACTION_COMMIT BAPI "succeeds" but nothing is saved Commit after evaluating RETURN Hard-coded BREAK-POINT / BREAK user Stops in QA/production Remove; ATC blocks it Using f (float) for money p or decfloat34 Missing leading zeros (ALPHA)

SELECT finds nothing for '1000' vs '0000001000' CONVERSION_EXIT_ALPHA_INPUT or ALPHA = IN Currency amounts without currency key Wrong decimals (e.g. JPY)

Always keep the CUKY reference; use CURRENCY formatting MODIFY/UPDATE on SAP standard tables Inconsistency, lost support Use BAPIs/released APIs Dynamic SQL from user input Whitelist and CL_ABAP_DYN_PRG SELECT * on wide HANA tables High memory/CPU Explicit field lists Locks not released Users blocked (SM12)

DEQUEUE or lock scope with COMMIT WORK; release on all paths Front-end file functions in background

Use application-server files when sy-batch is set Header lines / obsolete statements Confusing code, not allowed in classes Explicit work areas, modern syntax

Inline declaration inside IF used outside Confusing scope (ABAP declarations are procedure-wide) Declare before the branch