SAP: how to program and test ABAP function modules

An ABAP function module encapsulates a piece of ABAP code under a name and makes this code globally available within the SAP system. Function modules are always part of a function group. In many cases, however, it is better to use a class (ABAP Objects) instead of a function module.

First, let’s look at why modularization of programs is important. Then we’ll discuss when ABAP function modules make sense and when they don’t. Then we’ll look at the call syntax and the structure of a function module.

Why you should modularize your ABAP program code

One of the most important principles of good programming is to “never write the same code twice”. If you write the same lines of code in two places in your program, then pay close attention. Imagine at some point later you find a mistake and correct it. Now one piece of code is fixed, but the other is still wrong. Maybe you still think you know what you are doing. So now imagine someone else has to maintain your code later and this poor person does not know anything about the code duplicates. He finds a mistake, corrects it, and he has little chance of knowing that the same mistake still exists elsewhere.

It is therefore better to encapsulate this functionality, stick a name on it as a label and call this one code in both places. Now if there is an error, then there is only one instance of your code with the error. There is only one point to correct. The quality of your program code has improved.

ABAP offers various options for avoiding such code duplicates and for giving a piece of program code a name under which it can be called:

  • Form routines (these are officially obsolete)
  • Function modules (this is what this is article is about) and
  • global classes and their methods. In most cases these are the better choice. A class can have multiple methods. This is a better structure than to have a large number of function modules that have little connection with each other.

When should you use function modules?

Treat new function modules as something you need a justification for. Why do you need it in the first place? Why don’t you write a global class instead? I explicitly recommend the article Coding ABAP Like JavaOpens in a new tab. for more information about the advantages of object orientation in ABAP development.

There are however some valid reasons for coding function modules:

  • The function module already exists, it has to be adapted, but it is not feasable to port it into a class.
  • RFC (remote function call): You can call RFC-capable ABAP function modules externally (e.g. from a SAP-PI), you can also make them available as a web service. You can’t do that with classes. One client project I’m working on uses a lot of RFC. That also means a lot of function modules, even new ones. But, as I said, this is just an exception. In the standard case, new function modules should be rare.
  • Update modules: you can use function modules as update modules. That is a whole chapter of its own and would go beyond the scope of this article. The basic idea is that you can register a function module to be executed later, together with a commit command or even after a commit of the main program. Sometimes this makes sense to speed up the flow of the main program. But again: this should be a rare exception.
  • Customer exits: some customer exits require a function module with a specific signature (parameter list) as an interface. But before you follow this road, please look around to see if there are other enhancement options to solve your case, e.g. Badi.

As you are reading on, I assume that you have a valid reason for your new function module.

Calling SAP function modules

SAP comes with a large number of ready-to-use function modules. It is often worth to spend some time on research to see if there already is a module that solves your problem than to write a new one yourself.

There is a special syntax for calling a function module. SAP has created an ABAP command for this purpose: CALL FUNCTION.

As long as you don’t know the syntax of CALL FUNCTION by heart, there is help in the SAP GUI for the correct calling of a function module. Even if you know the syntax, it is often helpful to use this method, because then the names of all parameters that you need to fill, will automatically be inserted into your ABAP program.

In your SAP GUI go to Menu/Edit/Pattern:

The following dialog appears. In it you enter the name of the function module. (You can also use wildcards here like “* ftp *”. Then press F4. You will receive a list of function modules that match the name and you choose one.)

Then press the green OK button . The SAP GUI now generates the call pattern.

In this pattern, all mandatory parameters are shown in black, all optional parameters are commented out. It is now your job to fill in the parameters and, if necessary, to declare the required variables.

You see parameters that are exported from the report to the function module. The return values ​​of the function module are imported. These values that are returned are always optional parameters. You can always call the function module without being interested in the results (and possibly error messages) of the module. You should usually take care and be interested in the results and errors, but the calling syntax doesn’t require it.

The function module can also throw exceptions. These are mapped to error values ​​in sy-subrc. If you have not listed an exception and have not defined “other” (which handles “all others” that you did not declare) then the entire program aborts hard and you will find the abort logged in transaction ST22. Feel free to try this out as an exercise..

A quick note on importing and exporting parameters:

In the definition of the function module, we will soon see that data that is entered from the outside into the function module becomes import parameters of the module. Data that is returned from the module becomes the export parameters. This is also the natural way of naming import and export. However, when the module is called from the outside, the naming is reversed. The report, the calling program, exports data to the function module and imports the results. This is confusing at first. As often in the SAP world you can only state: this is the way things are done here. You cannot change that.

The structure of a SAP function module

As an example for developing your own function module, let’s look at a function module that does a little math with numbers. Of course, you would normally deal with this directly in ABAP and not delegate it to a function module. We just need it as an example that does some sample work done.
So we put two numbers into the module, plus an operation (+, -, *, /) and get a number back as the result.

SE37 – the transaction for creating and maintaining function modules

Function modules can be edited in the SAP GUI with transaction SE37. (It also works with SE80, but these are the same dialogs.)

The initial screen in transaction SE37 is simple:

You enter the name of a function module, then you can:

  • display it, if it already exists
  • change it, if it already exists
  • create it, if it does not already exist
  • or delete it (the icon with the bin), if it already exists.
SE37 initial screen

Press create and this dialog will be shown:

You need

  • a name of the new function module
  • the function group it belongs to and
  • a short description that will be displayed next to the name of the function module in some dialogs in SAP.

If you do not yet have a suitable function group then you cannot create it here. Creating function groups will be explained below.

The name of your own function modules should begin with Y_ or Z_. Z_ is common. Other names are possible, but lead to this warning:

function module name is reserved for SAP

The warning is also issued for Z if the Z is not directly followed by an underscore _.

So SAP allows you to write a new function module called HALLO_WORLD. This is different from the situation for reports in transaction SE38, where Z or Y as first letter is mandatory, otherwise you will be asked for a SAP access key, which you first have to order from SAP.

Next you come to an input dialog in which you can edit your function module. This dialog is divided into several tabs: attributes, import parameters, export parameters, changing parameters, table parameters, exceptions and (finally) the source text of the function module.

The attributes of the function module

The “attributes” tab looks like this:

SE37 attributes tab

The attribute tab shows us the name of the function module and the function group (name and brief description) to which it belongs. The package can also be seen, this is taken from the function group. In this example it is $ TMP, the example is created as a local development and is not included in the transport system.

Under processing type you can set whether it is

  • is a normal function module (this is the normal case) or
  • whether the module is remote-enabled (i.e. for RFC). If so it could be called directly from PO system, or it could be published as a web service directly from the SAP system.
  • There is also the option of declaring the module to be an update module, with four different sub-variants. That is very special and is beyond the scope of this article.

As a rule of thumb, your function module will be a normal module.

The module also has a person responsible and a time stamp of its last change. The responsible person is not the last one who changed it. This user name is set explicitly.

Based on the function group, the module also belongs to an ABAP program. It is stored as an include file to this program. The file name of this include is a technical name. It is not the name of the function module. More on this below under function group.

The import parameters of the function module

You can define the input parameters of the function module on the import tab. Each parameter has a name. It makes sense to follow naming conventions here (more on this below). If all input parameters start with i, then it is always evident in the program code that these variables are specified externally.

SE37 import tab

The typing is either “type” or “type ref to” (for objects) plus an “associated type”. In our example it is “type int4”.

You can also define a default value that is set automatically if the parameter is optional and the caller chooses to not pass a value.

Optional: a flag that determines whether the caller is obliged to set the parameter in the call, or whether he can omit it. If optional is checked, the caller may omit the parameter.

“Pass value” determines

  • not checked: the caller’s variable is used directly. (Please give preference to this variant)
  • checked: a copy is made in the parameter transfer. When working with large tables, this may lead to performance problems. In some cases, however, this variant is mandatory, for example with RFC. Please only use it if it is absolutely necessary.

The export parameters of the function module

The structure of the export parameters is not surprising. We see the typing, the associated type, we can decide again whether we should transfer values. (No, we don’t, unless we have to, like with RFC.)

SE37 export tab

Table parameters of a function group and changing parameters

The tables tab offers table parameters. These are used for both import and export at the same time and they are officially obsolete. They only exist for reasons of compatibility with old code.

As they shouldn’t be used at all, I will not go into details about these.

Changing parameters can be used, but they are unusual and I think they are superfluous. Please limit yourself to input and export parameters. Besides I would like to point out again that I consider function function modules to be the wrong approach. In most cases that one should rather write classes and methods.

The exceptions of a function module

On the exceptions tab, you can define possible exceptions. If you call a function module using the pattern dialog, all of these exceptions are listed in the generated code.

This exception system is inferior to the class-based exceptions from ABAP Objects, one more reason to prefer classes and methods. But here in this older exception system, the mapping of exceptions to sy-subrc values is part of the technology.

The names of the exceptions can be freely determined. If they are raised in the module, but not listed by the caller (or are treated with “other”), the program aborts and these codes can then be found in ST22 in the abort log.

In contrast to class-based exceptions, here you can only name the exception, but you cannot pass additional information to the caller.

The exception is triggered in the program code of the module using the ABAP command “raise”, followed by the constant assigned here. Warning: the name of the exception is not checked by the compiler. If you make a mistake here and use an exception that is not provided for in the signature, you will get a hard abort at runtime with the information that the exception xxx is not even defined in the function module!

SE37 exceptions tab

The source text of the function module

We now come to the most important part of the function module: its source code.

SE37 source code tab

This tab contains an ABAP editor. The interface of the function module can be found as a comment. You can delete this comment here, but as soon as you switch to another tab and then come back to the source code, this comment is there again. The actual interface cannot be edited in the source code tab in SE37. You have to go through the dialogs on the other tabs.

This is sometimes tedious if, for example, you want to copy extensive interfaces from one function module to another.

By the way: in the ABAP editor of Eclipse, which I would like to expressly recommend at this point, you can edit the interface directly in the source code.

Here is the complete example of our arithmetic module:

FUNCTION Z_HEV_TEST.
*"----------------------------------------------------------------------
*"*"Local Interface:
*"  IMPORTING
*"     REFERENCE(IF_NUM1) TYPE  INT4
*"     REFERENCE(IF_NUM2) TYPE  INT4
*"     REFERENCE(IF_OPERATION) TYPE  CHAR1
*"  EXPORTING
*"     REFERENCE(EF_RESULT) TYPE  INT4
*"  EXCEPTIONS
*"      DIVISION_BY_ZERO
*"      UNKNOWN_OPERATION
*"----------------------------------------------------------------------

if if_operation = '+'.
  ef_result = if_num1 + if_num2.
  return.
endif.

if if_operation = '-'.
  ef_result = if_num1 - if_num2.
  return.
endif.

if if_operation = '*'.
  ef_result = if_num1 + if_num2.
  return.
endif.

if if_operation = '/'.
  if if_num2 = 0.
    raise division_by_zero.
  endif.
  ef_result = if_num1 / if_num2.
  return.
endif.

raise UNKNOWN_OPERATION.

ENDFUNCTION.

The relationship between function module and function group

As mentioned above, a function module always belongs to a function group.

For the caller, it does not matter in which function group or even in which package the module is located. You just need to know the name of the module. It is only important for global variables that are defined within the function group in its top include. These are only valid within the entire function group. They are initialized the fist time a module of the function group is called. All subsequent calls to module from the function group keep these global variables. The values ​​are not changed from one call to the next.

Here is a representation of the file structure from SE80:

function group files

In order not to be misunderstood: I’m talking about global variables in the top include of the function group, not about data declarations within the function module. The latter are re-initialized each time the function group is called up.

These global variables of a function group are only rarely used and they should better be placed into a global class as as static class variables anyway. So there is no sensible reason to put global data into a top include.

The file structure of a function group

The function group has the following file structure:

  • main program: SAPL<function group>
  • top include: L<function group>TOP. Global data of the function group can be found here.
  • function modules: L<function group>U## with the two-digit number ##. These files are numbered, starting with U01. The last possible one is U99 A function group can therefore contain a maximum of 99 function modules. If you use functions modules a lot, you should plan a little in advance and distribute the modules over several function groups. Otherwise, the big reorganization begins when you hit the mark here.
  • A central list of the function modules in L<function group>UXX. It literally says XX here. This file lists one module after the other with include lz<function group>u ##. The name of the function module is then added as a comment.

So in our case it looks like this:

This has a direct and difficult effect on collaboration between multiple developers:

Anyone who transports their own code for a new function module also transports the UXX include and must therefore also transport all of the new function modules within the function group written by other developers. This frequently leads to transport complications. This is another reason why it makes sense to generously distribute function modules (if their content makes sense) to several function groups.

Creating a new function group

Creating a new function group works well from SE80, but also from SE37.

In the selection screen of SE37 go to “Menu / Goto/ Function groups/ Create group”.

create function group

This dialog is then shown:

Only the name of the function group needs to be entered here, along with a brief explanation of what the function group is for. A responsible developer for the group must also be named. However (as far as I have observed so far) this has no technical effects. Any developer can edit the function group.

Naming conventions for the parameters of a function group

For the names of the parameters, you should adhere to the naming conventions that are defined apply in the for your project. We usually use these prefixes:

  • if_: Input single value (“field”). Other companies might prefer iv_ (“value”)
  • is_: Input of a structure
  • it_: input of a table
  • ef_, es_, et: correspondingly for export parameters

You can find more articles about SAP here.

Recent Posts