"The R/3 enhancement concept allows you to add your own functionality to SAP's standard business applications without having to modify the original applications." (Introduction to the Enhancement Concept).
This blog is about a specific type of exit, namely Function Module Exits. Assuming that you are familiar with transactions CMOD and SMOD I will show you how User-Exits can be organized in order to achieve four major goals:
- Easy Maintenance
- High Transparency
- Process-Independent Testing
- Avoidance of Dangerous Liaisons
User-Exits are normally implemented "On-Demand". Having found out that a specific behaviour of a standard application cannot be realized by means of customizing the next step is to look for appropriate User-Exits. An enhancement project (CMOD) is created and the required enhancements assigned. Now it is time to create the implementation of the User-Exit which occurs in a ZX-include predefined by SAP.
These ZX-includes have to be assigned to customer packages. Depending on who implements the ZX-includes and for which purposes they are implemented these User-Exit includes are likely to be scattered around many packages.
On one of our ERP systems the situation looks like this:
- 98 implemented ZX-includes are assigned to 15 different packages
The ZX-includes of User-Exit XLTO (User Exits for TO Processing) have been assigned to four(!) different packages demonstrating the historical evolution of this User-Exit.
Considering the fact that these User-Exits are shared by three different companies residing on three different clients this is already a bad situation regarding maintenance and transparency of the User-Exits.
From Bad to Worse
Being responsible for SAP-XI & EDI support at our company I sooner or later had to modify existing User-Exits for Billing-Doc-Output (XEDF). However, I almost got a heart attack when I saw the implementation of include ZXEDFU02 (EXIT_SAPLVEDF_002) for the first time (see below).
While it is easy to spot the two companies (Spain & Switzerland) that have used this User-Exits it is less obvious to identify and understand the manifold requirements that have been implemented.
Step 1 - Organizing the Mess
In order to organize the existing and new User-Exits in a more meaningful way I created a new package ZCMOD. This package is intended to contain all User-Exit related repository objects.
The next step was to clearly separate the company specific coding. This was achieved by a generic Five-Step approach:
- Create a Z-exit function group (if not already existing)
- Copy the Exit-Function Module to a Z-Exit Function Module
- Create company specific Z-Exit Function Modules
- Replace coding in ZX-include with function module call
- Reassign ZX-includes to the new package ZCMOD
The result of the first three steps is shown below:
A new function group ZXEDF was created and assigned to the package ZCMOD. The Exit-Function module EXIT_SAPLVEDF_002 was copied to ZEXIT_SAPLVEDF_002 in function group ZXEDF. This function module was again copied twice to yield ZEXIT_SAPLVEDF_002_CH and ZEXIT_SAPLVEDF_002_ES. The main point is that all Z-exit function modules have the same interface like the SAP Standard Function Module-Exit.
Implementing User-Exits: Once and for All
If we need to touch SAP standard objects we should always try to do it once and for all. In case of Function Module-Exits this can be done quite easily:
The ZX-include contains nothing but a call to the frame Z-exit function module (see below).
Using this approach we obviously never ever have to touch this ZX-include again.
The Frame Z-Exit Function Module
The frame function module ZEXIT_SAPLVEDF_002 has the function to separate the coding logic at the highest hierarchical level which in our case are the companies:
The company specific function modules contain the company specific coding:
Step 2 - Complete Structural Separation of Concerns
Even though we have now separated the company specific coding the function modules are still linked together into a single function group. Thus, if developers need to change the User-Exit for different companies at the same time they might interfere with each others. Therefore the next level of organizing User-Exits is required: the complete structural separation of concerns.
For each company a specific Z-Exit function group is created:
- ZXMGV - Frame Z-Exit function group
- ZXMGV_CH - specific for Lindt Switzerland
- ZXMGV_ES - specific for Lindt Spain
- ZXMGV_ES - specific for Lindt Poland
Within the frame function module ZEXIT_SAPMV01_002 we determine the name of the company specific function module and dynamically call it.
There are two obvious advantages of this structural organization of User-Exits:
- Errors accidentially introduced into a User-Exit will not affect any other company.
- Different companies can modify the same User-Exit at the same time without interfering with each other.
In this weblog I presented a possible strategy how to organize User-Exits (CMOD / SMOD). The major steps of this approach are:
- Create a specific package (e.g. ZCMOD) containing all User-Exit related repository objects
- Copy the Exit-Function module to a Z-Exit function module having the very same interface. Only the frame function module is called in the ZX-include.
- Implement the ZX-include once and for all.
- Create Z-Exit function groups for the highest hierarchical level that employs the User-Exit
An example for a hierarchy of Z-Exit function modules is given below:
- Frame: ZEXIT_SAPLVEDA_001
- Country specific: ZEXIT_SAPLVEDA_001_CH
- Country & Customer specific: ZEXIT_SAPLVEDA_001_CH_SHOP
If I need to change the User-Exit for inbound ORDERS IDocs intended for our Lindt Shops I immediately know that I have to change function module ZEXIT_SAPLVEDA_001_CH_SHOP. Thus, based on the requirements (SD-EDI User-Exit & Lindt Shops) I can deduce the affected Z-Exit function module.
Is there another advantage of replacing the coding in the ZX-includes with the call to the frame Z-Exit function module?
Yes, there is.
The Z-Exit function modules enable you to test the User-Exit independent of the entire process / transaction !!!
If you are already working on SAP releases >= 6.20 you can define ABAP Unit Tests for each Z-Exit function module. Having assigned all User-Exit related repository objects (ZX-includes and Z-Exit function groups) into a single package you can then use the Code Inspector (transaction SCI) to easily test all your User-Exits at once:
- Define an object set containing this package
- Define a check variant executing all dynamic tests (ABAP Unit)
- Run an inspection with object set and check variant created before
Finally, if you intend to get rid of obsolete User-Exits and revert back to the SAP standard processes a package like ZCMOD will give you a headstart for your project.
Function Module-Exits (CMOD / SMOD) can be organized by simple means into a useful structure thereby achieving major goals like
- Easy Maintenance
- High Transparency
- Process-Independent Testing
and at the same time avoiding dangerous liaisons by separating concerns into completely independent structural components.
The topic of this blog has been continued in: