Modularization
ABAP Developmentintermediate

Modularization Part 3: FORM vs Method vs Function Module

Key takeaway

Choose the right unit: compare FORM routines, function modules and methods by scope, interface, reuse, remote capability, exceptions and testability — with a decision table for classic projects.

Explanation

📌 KEY POINTS
✅ Method (in a class) — default choice for all new logic.

✅ Function module — when you need RFC/BAPI, update task, or an SAP framework requires it.

✅ FORM — only when maintaining existing code or where frameworks call FORMs (SAPscript, old exits).

💡 Function modules can call methods: keep the FM thin and the logic in a class.

━━━━━━━━━━━━━━━━━━━━
▶ WHERE WE ARE

Parts 1–2 introduced units and FORMs. This part compares them so you choose deliberately.

━━━━━━━━━━━━━━━━━━━━
▶ 1. COMPARISON

  • Scope: FORM — inside one program; FM — system-wide via its function group; method — local class (one program) or global class (system-wide).
  • Interface: FORM — positional USING/CHANGING/TABLES; FM — named IMPORTING/EXPORTING/CHANGING/TABLES/EXCEPTIONS, checked at runtime; method — named IMPORTING/EXPORTING/CHANGING/RETURNING/RAISING, checked by the syntax check.
  • Remote: only FMs can be RFC-enabled (BAPIs are RFC FMs).
  • Update task: only FMs (update modules).
  • Exceptions: FORM — none (flags/messages); FM — classic EXCEPTIONS with sy-subrc (or class-based); method — class-based exceptions.
  • Expressions: only methods with RETURNING can be used inline: IF lcl_x=>is_full( ls ).
  • Testability: methods are best (ABAP Unit, test doubles).
  • State: FMs share the global data of their function group (state between calls); classes hold state in instances.

━━━━━━━━━━━━━━━━━━━━
▶ 2. DECISION TABLE

  • New business logic → method (global class if reused).
  • Called from another system (RFC) → RFC function module wrapping a class.
  • Asynchronous posting at commit → update function module (Part 5).
  • Framework requires FM/FORM (customer exit, SAPscript PERFORM) → implement it, delegate to a class.
  • Maintaining legacy → keep the style consistent but delegate new logic to methods.

━━━━━━━━━━━━━━━━━━━━
▶ 3. CALLING SYNTAX SIDE BY SIDE

PERFORM calc USING a CHANGING b.

CALL FUNCTION 'Z_CALC' EXPORTING iv_a = a IMPORTING ev_b = b EXCEPTIONS not_found = 1 OTHERS = 2.

b = zcl_calc=>calc( a ).

━━━━━━━━━━━━━━━━━━━━
▶ STEP BY STEP

Run the code example: the same "free seats" logic as FORM, function module (create Z_FLIGHT_FREE_SEATS in a function group) and method, and see which one can be used in an expression.

✅ CHECKPOINT: you pick the unit that fits the technical requirement and keep the logic in classes.

Code example

ABAP Code
REPORT zmod_part3. DATA: gs_flight TYPE sflight,      gv_free   TYPE i. CLASS lcl_seats DEFINITION.  PUBLIC SECTION.    CLASS-METHODS free_seats IMPORTING is_flight     TYPE sflight                             RETURNING VALUE(rv_free) TYPE i.ENDCLASS.CLASS lcl_seats IMPLEMENTATION.  METHOD free_seats.    rv_free = is_flight-seatsmax - is_flight-seatsocc.  ENDMETHOD.ENDCLASS. START-OF-SELECTION.  SELECT SINGLE * FROM sflight INTO gs_flight WHERE carrid = 'LH'. * ===== 1. FORM: positional, program-local =====  PERFORM free_seats USING gs_flight CHANGING gv_free. * ===== 2. Function module: named parameters, classic exceptions =====  CALL FUNCTION 'Z_FLIGHT_FREE_SEATS'          " SE37, function group ZFLIGHT    EXPORTING      is_flight      = gs_flight    IMPORTING      ev_free        = gv_free    EXCEPTIONS      invalid_flight = 1      OTHERS         = 2.  IF sy-subrc <> 0.    WRITE: / 'FM returned exception', sy-subrc.  ENDIF. * ===== 3. Method: syntax-checked interface, usable in expressions =====  IF lcl_seats=>free_seats( gs_flight ) = 0.    WRITE: / 'flight is full'.  ENDIF. FORM free_seats USING us_flight TYPE sflight CHANGING cv_free TYPE i.  cv_free = lcl_seats=>free_seats( us_flight ).       " delegateENDFORM. * ===== Function module source (SE37) =====* FUNCTION z_flight_free_seats.* *"  IMPORTING VALUE(IS_FLIGHT) TYPE SFLIGHT* *"  EXPORTING VALUE(EV_FREE) TYPE I* *"  EXCEPTIONS INVALID_FLIGHT*   IF is_flight-seatsmax = 0.*     RAISE invalid_flight.*   ENDIF.*   ev_free = is_flight-seatsmax - is_flight-seatsocc.   " or call a global class* ENDFUNCTION.

Real project scenario

A project created a new function group for every small piece of logic, including internal calculations never called remotely. Function groups accumulated shared global data, and one FM unexpectedly used values left from a previous call in the same session.
The architecture team defined a rule: logic lives in global classes; function modules only where RFC, update task or framework requirements exist, and those FMs just call class methods. New developments became easier to test, and the state bugs disappeared.

Common mistakes

  • New FORMs in new development.
  • Function modules for purely internal logic.
  • Relying on function group globals as hidden state.
  • Business logic directly inside RFC FMs.
  • Ignoring sy-subrc after CALL FUNCTION with EXCEPTIONS.

Best practices

  • Methods by default.
  • FMs for RFC, update task and framework needs — thin wrappers.
  • FORMs only in legacy/framework contexts.
  • Always handle FM exceptions.
  • Keep function group global data minimal.

Interview angle

Questions: "FORM vs function module vs method?", "When do you still need a function module?", "Why are methods preferred?"
Strong answer: methods have syntax-checked named interfaces, class-based exceptions, RETURNING for expressions and are testable; FMs are system-wide, can be RFC-enabled (BAPIs) and used as update modules, and share function group globals; FORMs are program-local and obsolete for new code; keep logic in classes and FMs/FORMs as thin wrappers where required.

Practice this lesson

Quick check

1. Business logic must be callable by an external system via RFC. What is the recommended design?

2. Which requirement still needs a function module rather than a class method?

3. Which requires a function module?

Interview questions

1. You need logic that a report uses, that an external system calls via RFC, and that runs in the update task. Would you use a FORM, a method or a function module?

Answer it in your own words first, then compare.

2. When should you use a subroutine (FORM), a function module, and a method?

Answer it in your own words first, then compare.

Practice more with Interview AI →

Reference-verified: the steps are checked against official SAP documentation and tutorials, and object and field names in the sample code are checked for consistency. The code has not been compiled or run on an SAP system by ERPClimb. Syntax marked release-dependent varies by SAP release, so check it in your own system.

More lessons in this topic

Interview questions on this topic

Related SAP topics