There are different reasons why you would want both an ABAP and an ABAP-managed database procedures (AMDP) implementation of a method.
From a technical point of view, developing both is not a problem, since whether a method is written in SQLScript or ABAP is only determined when the method is implemented and doesn’t affect the definition of the method. In this blog post, we’ll look at a few typical use cases where more than one implementation exists.
Clean Code: Separation of Concerns
The principle of the separation of concerns was formulated in 1974 by Edsger W. Dijkstra. Under this principle, different tasks should also be performed by different components in a system. In our case, separation of concerns means that database access should not be mixed with other application code. Instead, different classes should be created for each aspect.
If you adhere to this principle, two-track development of AMDP and ABAP implementations is also relatively simple. Classes for database access can be easily exchanged.
Support of Different Database Systems
If the application needs to run on different database systems, you can have one implementation in Open SQL and one in AMDP. Of course, you can also create special implementations for each of the other databases.
Switching between the various implementations should take place automatically at runtime. For this purpose, you can use the factory design pattern. Below you’ll notice we used a static factory method, GET_INSTANCE, to generate the instances. Based on the SY-DBSYS field, this method decides which class implementation should be used.
The following code shows a simple implementation of the method GET_INSTANCE. Of course, other database systems could also be considered.
DATA lv_classname TYPE classname.
lv_classname = 'ZCL_READ_XYZ_AMDP'.
lv_classname = 'ZCL_READ_XYZ_OSQL'.
REATE OBJECT ro_instance TYPE (lv_classname).
Comparison Between ABAP and AMDP
If you want to test the differences between the implementations in ABAP and AMDP in runtime and result, inheritance is a rather useful concept as in, for example, the previous section where we leveraged inheritance from a shared superclass.
However, you’ll need a suitable switch that allows you the flexibility to select the relevant implementation. You can create these switches, for example, by using entries in a Customizing table or by defining user parameters. These switches can then be queried in a corresponding factory method.
Retroactive Implementation as AMDP
Let’s say you implemented a method in ABAP and later discover performance problems; you can implement the method as an AMDP. To preserve the original implementation for performance and result comparisons, creating a subclass is a good idea. The corresponding method is then implemented as an AMDP in this subclass.
Due to restrictions on AMDPs regarding access to instance attributes and parameters, this procedure must be taken into account when creating your methods. Alternatively, you can carry out a refactoring, as shown in the figure below, by following this approach:
- Outsource the logic into a new method that meets the requirements of an AMDP: no access to class and instance data, no RETURNING parameters, no parameters with structures.
- Create a subclass.
- Redefine the corresponding method as an AMDP.
To switch between the two versions of the class, you can use a factory method again.
ABAP Unit Tests
A mock object is often used to insert data into a class to be tested in a unit test. This object has the same external interface as a real object but provides predefined data that is independent of the database state.
Classes that contain an AMDP can, for example, be replaced for unit tests by a local subclass in which the AMDP method has been replaced by a corresponding ABAP implementation. For such tests, you can use the dependency injection design pattern.
Note that AMDP implementation is only possible in global classes. In local classes, only an implementation in ABAP is allowed.
Implementing a method in two ways—ABAP and AMDP—is desirable because it allows for flexibility for developers working with different database systems, for fixing performance problems in one method, and for testing the usability of methods. In this blog post, you were introduced to typical use cases for utilizing an AMDP implementation and how one differs from an ABAP method implementation.
Bonus content: See how to test the backend and frontend of ABAP programs.
Editor’s note: This post has been adapted from a section of the book SQLScript for SAP HANA by Jörg Brandeis.