This is a test message to test the length of the message box.
Login
|
ABAP OO Method Interface
Created by Software-Heroes

OO Design - Method Interface

381

What should an interface for an ABAP method actually look like, and what advantages do the different designs offer? In this article, we'll look at parameters, structures, and objects for mapping the interface.

Advertising


In this article, we'll look at the design and use of method interfaces and what they should ideally look like today.

 

Introduction

Nowadays, ABAP code should primarily be defined in classes. You can follow various patterns to adhere to best practices and ensure testability. However, there are also further best practices for defining and designing method interfaces. How many parameters should this interface have, and how is the data actually passed from method to method? Every developer, regardless of their experience level, will encounter certain challenges or interfaces that may not adhere to best practices.

 

Initial Situation

Let's first look at the initial situation. This is an example implementation that doesn't fully implement all best practices but is intended for demonstration purposes. The class doesn't implement an interface but is instance-based. Please remember to follow best practices in a real class (see the pattern above).

 

Class

This example implements a relatively large class. We have a constructor that accepts various values to initialize variables within the class. Furthermore, we have a run method that executes the actual logic. Within the Run method, we first validate whether the configuration is complete and well-maintained, and then execute an additional internal Run method which implements the actual logic and may branch into further logic.

CLASS zcl_bs_demo_oo_intf1_start DEFINITION
  PUBLIC FINAL
  CREATE PUBLIC.

  PUBLIC SECTION.
    METHODS constructor
      IMPORTING config_id        TYPE char10
                !destination     TYPE string
                number_of_errors TYPE i
                !log             TYPE REF TO zif_aml_log.

    METHODS run
      EXPORTING system_id TYPE char3
                !message  TYPE string.

  PRIVATE SECTION.
    DATA config_id        TYPE char10.
    DATA destination      TYPE string.
    DATA number_of_errors TYPE i.
    DATA log              TYPE REF TO zif_aml_log.

    METHODS is_config_valid
      RETURNING VALUE(result) TYPE abap_boolean.

    METHODS internal_run
      IMPORTING config_id        TYPE char10
                !destination     TYPE string
                number_of_errors TYPE i
      EXPORTING system_id        TYPE char3
                !message         TYPE string.
ENDCLASS.


CLASS zcl_bs_demo_oo_intf1_start IMPLEMENTATION.
  METHOD constructor.
    me->config_id        = config_id.
    me->destination      = destination.
    me->number_of_errors = number_of_errors.
    me->log              = log.
  ENDMETHOD.


  METHOD run.
    IF NOT is_config_valid( ).
      RETURN.
    ENDIF.

    internal_run( EXPORTING config_id        = config_id
                            destination      = destination
                            number_of_errors = number_of_errors
                  IMPORTING system_id        = system_id
                            message          = message ).
  ENDMETHOD.


  METHOD is_config_valid.
    IF config_id IS INITIAL.
      log->add_message_text( `Config is initial` ).
    ENDIF.

    IF destination IS INITIAL.
      log->add_message_text( `Destination is mandatory` ).
    ENDIF.

    IF number_of_errors <= 0.
      log->add_message_text( `Insert a number bigger than 0` ).
    ENDIF.

    RETURN xsdbool( log->has_error( ) = abap_false ).
  ENDMETHOD.


  METHOD internal_run.
    " Do processing
  ENDMETHOD.
ENDCLASS.

 

Challenges

Now we have several challenges that we can actually define quite well in this class. For example, when calling the constructor, we have a relatively large interface with variables. Four different variables have already been passed here, which are handled individually internally.

METHODS constructor
  IMPORTING config_id        TYPE char10
            !destination     TYPE string
            number_of_errors TYPE i
            !log             TYPE REF TO zif_aml_log.

 

The interface is therefore relatively large. If we later need to adjust the interface to include another parameter, we will also have to add a local attribute, adjust the input interface, and extend our run methods as well, since these will also accept the parameters. This means that adjusting one parameter requires us to extend three places within our code. Likewise, the interfaces are not particularly lean when we look at the implementation and the call.

internal_run( EXPORTING config_id        = config_id
                        destination      = destination
                        number_of_errors = number_of_errors
              IMPORTING system_id        = system_id
                        message          = message ).

 

Another point we might be able to fix later is that we have configuration validation here. This is implemented locally and is independent of the data passed over. In a later refactoring, however, this could also mean that we have to duplicate the logic to be able to perform the validation in another object as well.

 

Clean ABAP

A first important piece of advice you can get is from the Clean ABAP Style Guide. This is a community-created guide that defines best practices for development in the ABAP context, but also in the ABAP context more generally. This section provides many best practices and helpful tips on how to create good and clean ABAP code. You should take a closer look at the Methods section to learn about naming, structure, and calling methods.

Our goal is to keep methods as lean as possible, minimizing the number of parameters taken in and returned. We can achieve this by bundling different elements. This allows for easy adjustments to the bundled object. This way, we avoid modifying the entire object and only need to make consistent adjustments to the content in a few key places. At the same time, the writing effort is reduced and the flexibility for later adjustments is greater.

 

Variant A - Structure

In the first variant, we use a structure to pass our configuration into the object, but also to output results from the object.

 

Definition

To do this, we first define two different structures, firstly to receive our configurations and secondly to return the result of the run. The advantage of bundled structures is that we can pass them to any method, but they themselves remain flexible, for example, to add further fields. In case of doubt, we only need to extend the structure, but not the interfaces of the methods; these remain stable.

TYPES:
  BEGIN OF configuration,
    config_id        TYPE char10,
    destination      TYPE string,
    number_of_errors TYPE i,
    log              TYPE REF TO zif_aml_log,
  END OF configuration.

TYPES:
  BEGIN OF run_result,
    system_id TYPE char3,
    message   TYPE string,
  END OF run_result.

 

Methods

If we then replace the parameters in the method with our structures, we get a manageable picture. We have exactly one input parameter and one output parameter. Each is defined as RETURNING, which makes passing to other values or direct assignment much, much simpler.

METHODS internal_run
  IMPORTING config        TYPE configuration
  RETURNING VALUE(result) TYPE run_result.

 

We then replace the call in our Run method and see that the method call now only consists of one line. We can call the method directly on the return, pass the configuration, and handle everything that way. Additionally, we save ourselves the parameter assignment on the call, since we only have one input parameter and can therefore omit the name.

METHOD run.
  IF NOT is_config_valid( ).
    RETURN.
  ENDIF.

  RETURN internal_run( config ).
ENDMETHOD.

 

In the configuration check (IS_CONFIG_VALID), we then need to reference the structures and no longer the individual values. Otherwise, the structure of the method remains unchanged. Our Run method now returns a structure and can therefore use the RETURNING parameter. If we later want to extend the structure and return additional fields as a result, we can simply adjust the structure and thus avoid having to switch to, for example, EXPORTING.

 

Variant B - Object

In the second variant, we restructure our configuration and create a separate object for this purpose. For the sake of simplicity, we use a simple class without an interface here. If you want to make the whole thing testable, you should also create an interface to keep the implementation flexible. In this example, we create all attributes as public attributes and set them to READ-ONLY. They are populated via the constructor, as in the other implementation. As a crucial design decision, you can also decide here whether you want to define getters and setters for each attribute. This is easily implemented using the ABAP Development Tools. Getters and setters each have the advantage that we can check or adjust the values and attributes we receive before incorporating them into the actual implementation. In the final step, we can even add additional methods to the configuration object that function based on the data. We also adopt the IS_VALID method to test and validate the passed attributes and ensure the object's consistency.

CLASS zcl_bs_demo_oo_intf_config DEFINITION
  PUBLIC FINAL
  CREATE PUBLIC.

  PUBLIC SECTION.
    DATA config_id        TYPE char10             READ-ONLY.
    DATA destination      TYPE string             READ-ONLY.
    DATA number_of_errors TYPE i                  READ-ONLY.
    DATA log              TYPE REF TO zif_aml_log READ-ONLY.

    METHODS constructor
      IMPORTING config_id        TYPE char10
                !destination     TYPE string
                number_of_errors TYPE i
                !log             TYPE REF TO zif_aml_log.

    METHODS is_valid
      RETURNING VALUE(result) TYPE abap_boolean.
ENDCLASS.


CLASS zcl_bs_demo_oo_intf_config IMPLEMENTATION.
  METHOD constructor.
    me->config_id        = config_id.
    me->destination      = destination.
    me->number_of_errors = number_of_errors.
    me->log              = log.
  ENDMETHOD.


  METHOD is_valid.
    IF config_id IS INITIAL.
      log->add_message_text( `Config is initial` ).
    ENDIF.

    IF destination IS INITIAL.
      log->add_message_text( `Destination is mandatory` ).
    ENDIF.

    IF number_of_errors <= 0.
      log->add_message_text( `Insert a number bigger than 0` ).
    ENDIF.

    RETURN xsdbool( log->has_error( ) = abap_false ).
  ENDMETHOD.
ENDCLASS.

 

Basically, we have now extracted most of the logic from the actual implementing class. This allows us to dynamically implement the configuration and also the calling class, which decouples the two objects. If we then use the configuration object in our RUN method, we can directly call the IS_VALID method from the configuration object to validate that the data is consistent. We can then simply pass the instance to the RUN method to retrieve the data from it.

METHOD run.
  IF NOT config->is_valid( ).
    RETURN.
  ENDIF.

  RETURN internal_run( config ).
ENDMETHOD.

 

This implementation is also very flexible, as we can easily add further attributes to the configuration class without having to modify the actual interface. Additionally, we have the flexibility to implement getters and setters, as well as other methods related to the configuration, such as saving the configuration or creating a unified log. The advantage of this is that we can now use the configuration in various other classes and it is not limited to our actual implementation.

 

Complete Example

All the source code shown can be found in the GitHub repository for ABAP OO examples. There you will also find further examples when it comes to class design patterns.

 

Conclusion

For each of the structure or object variants, there are advantages and disadvantages, and the community is not yet 100% in agreement on this. Perhaps the best approach is to decide which of the mentioned methods you want to use depending on the scenario, as this will also result in the creation of new objects or implementation costs. The most important point, however, is to focus on a lean and clean method architecture to minimize the effort required to adapt the code later.


Included topics:
OOABAP OOMethodInterface
Comments (0)



And further ...

Are you satisfied with the content of the article? We post new content in the ABAP area every Tuesday and Friday and irregularly in all other areas. Take a look at our tools and apps, we provide them free of charge.


ABAP Tools - VS Code (ABAP Cleaner)

Category - ABAP

One feature we missed in Visual Studio Code was the ABAP Cleaner. This has now been made available. Let's take a look at its installation, configuration and usage.

07/07/2026

ABAP Tools - VS Code (Agentic AI)

Category - ABAP

ABAP Development Tools for VS Code is here, so how do you get started with Agentic AI? Let's take a look at a basic configuration and how to get it running.

06/03/2026

ABAP Tools - VS Code (Quick Start)

Category - ABAP

The ABAP Development Tools for VS Code are now available, and in this short guide we'll look at everything you need to get started.

05/30/2026

ABAP Tools - Working with Eclipse (Classes)

Category - ABAP

In this article, we'd like to discuss working with classes and how you can extend them cleanly and easily in Eclipse. We'll also look at further options available in the ABAP Development Tools.

04/21/2026

ADT - RAP Extension Assistent [MIA]

Category - ABAP

You want to extend a RAP object and don't know exactly where to start? Perhaps the Extension Assistant can help you and guide you through the process step by step.

03/06/2026