Application Development Blog Posts
Learn and share on deeper, cross technology development topics such as integration and connectivity, automation, cloud extensibility, developing at scale, and security.
cancel
Showing results for 
Search instead for 
Did you mean: 
Sougata
Active Contributor

Introduction

Quite often we come across such cumbersome enhancement implementations at various customer sites that are not only difficult to support but has very little or no reusability at all across the development landscape. The source code behind these enhancements continue to grow from bad to worse over time as the business continues to request changes to these objects frequently as the business itself grows and evolves; to a point where it becomes simply a nightmare to support these objects not only from the development perspective but also from the testing standpoint, for example, to perform regression testing of all the existing functionalities when a current enhancement is extended and it results in change of behaviour of the enhancement in regards to the current business processes.

The objective of this blog is to demonstrate a simplified approach to implement custom enhancements by leveraging the powerful features of the new Enhancement framework together with the Switch framework that is well integrated into each other.

The Problem

Let us take an example of a classical User Exit (UE) component in the HR module PBAS0001 and its most common implementation at customer sites. Those unfamiliar with this particular UE - Two Function/Exit Modules are provided by SAP to the customers one to default values at PBO and the other to check values at PAI at the time of HR Infotype master data maintenance via its related transactions.

A Classic UE Implementation via CMOD - Example (of a developer's nightmare)

"The source code shell below is to demonstrate the support difficulties over time
"Developer #1 starts initial development...
CASE innnn-infty.
     WHEN '0000'.
          PERFORM do_something.
          IF var1 = constant1
             PERFORM do_something_else.
"Developer #2 starts making changes...
          ELSE.
            PERFORM read_something.
"Developer #3 starts making changes...He spends hours figuring out how to make his changes
"without interrupting any of the current functionlities
            "IF var2 = constant2.                         "del Developer #3
               IF var2 = constant2 AND var1 = constant1.     "add Developer #3
               MESSAGE e001 WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4
                    RAISING errors_occured.
             ENDIF.
          ENDIF.
           IF...
             IF...
"Developer #4 starts making changes. He is completely lost! He spends days trying to make sense of it all
                CASE...
                     IF...
                     ENDIF.
                ENDCASE.
           ENDIF.
             ENDIF.
     WHEN '0001'.
          "same story repeats here as well...
     WHEN '0002'.
          "same story continues here as well.... 
      WHEN OTHERS.
ENDCASE.

   

The Drawbacks of this Model

  • Code is procedural as a result the entire Function Group with all its global data is loaded every time into the memory at each call of the UE
  • Extremely messy to program
  • The framework does not support multiple implementations
  • A Classic BAdI definition without multiple implementation option has similar limitations to that of a Classic CMOD UE
  • Source code is cluttered everywhere as the implementation grows with time - Lots and lots of IF statements constructs
  • Implementations are not structured; they have no layers - they are extremely cumbersome to maintain
  • Business logic is not decoupled - No decoupling within this (old) framework
  • Hence no reusability across the development landscape
  • Support nightmare - Developer #4 needs to be extremely careful when changing source code as not to interfere with the functionalities of Developer#1, 2 & 3
  • Difficult to test especially in terms of regression testing - Difficult to pinpoint defects and isolate them
  • Difficult to sustain the solution in the long run
  • No flexibility over full or part of the functionality/implementation to make them active/inactive i.e. they are not Switchable

The (much) Better Approach

"Converting" classic UEs (and classic BAdIs) implementation to call custom Kernel BAdI implementations to leverage the power of the Switch Framework that is so well integrated within the new Enhancement Framework. This not only simplifies all the enhancement implementations but provides a structured development approach that is bound to add a lot of value to the SAP landscape in the long run.

The Advantages

  • Kernel BAdIs (or Enhancement Spot BAdIs or New BAdIs) are way faster than Classic BAdIs and/or the Classical UEs
  • Multiple Kernel BAdI implementations are possible where a Classic BAdI definition allows only a single implementation (Not multiple use)
  • Multiple Kernel BAdI implementations should normally be the approach for Classic UEs as they never can be marked for Multiple use
  • Multiple BAdI implementations can be done on a single Enhancement Implementation (EI) or it could be 1:1 depending on the requirement
  • Implementations are Filter dependent which means applications have control over calling specific implementations of a BAdI and not all
  • Implementations are clean, separated from each other as a result they are structured - source code is never cluttered
  • The entire business functionality (i.e. the UE) is Switchable
  • Each implementation of the UE is also Switchable by its own defined Switch
  • Business logic is decoupled
  • Hence business logic is reusable across the development landscape - for e.g. A standalone application reusing a specific business logic of a large enhancement implementation; Call the BAdI but return the business logic result for Infotype 0001 only!
  • No pain in regression testing - just turn off the Switch of a specific implementation to isolate errors
  • No more support maintenance nightmares - Developer #4 now simply creates his own new BAdI implementation on the same EI or creates a new EI

Example of a Custom Kernel BAdI with Switchable Enhancement Implementations

In our example, we will convert, simplify, integrate and structure the Classical UE/CMOD implementation PBAS0001 into the new Enhancement Framework. In our sequence of building blocks, we will first build the objects related to the Switch framework followed by the objects in the Enhancement framework to make it easier for the audience to understand the building flow and the integration between these two frameworks.

Package Hierarchy


We will start off by building a Package Hierarchy in order to structure our enhancement development - we will see later that this is very important so that we could leverage the switches to make our enhancements as flexible as possible. In any case, it is a good practice to to group development objects into the appropriate Packages and to have a meaningful Package Hierarchy in a development landscape.

where HR = Human Resources, PA = Personnel Administration, MD = Master Data, UE = User Exit, INFTY = Infotype followed by the infotype number.

Business Function Set, Business Function & Switches

Next, we will create a Business Function Set (BFS), an (Enterprise) Business Function (BF), link the BF with the BFS, create 5 Switches then link these Switches with our BF and finally assign appropriate Packages to our Switches (or not).

Business Function ZHR_BF_PA_MD_UE consists of 5 Switches which are required to control our New custom BAdI implementations.

Our BF is also assigned to a Business Function Set - which does not hold much context to our current demonstration but its good to know that every BF needs an asignment to a BFS to complete the SFW hierarchy.

Linkage between Switches and Packages


The table below contains the details of the Switches along with their individual Package Assignments and activation status.

Swich IDSwitch DescriptionPackage AssignmentActivation Status

ZHR_SFW_PA_MD_UE_INFTY_0000

Switch for Infotype 0000ZHR_PA_MD_UE_INFTY_0000Standby
ZHR_SFW_PA_MD_UE_INFTY_0001Switch for Infotype 0001ZHR_PA_MD_UE_INFTY_0001Active
ZHR_SFW_PA_MD_UE_INFTY_0001_01Switch for Infotype 0001 - Seq 01NoneStandby
ZHR_SFW_PA_MD_UE_INFTY_0001_02Switch for Infotype 0001 - Seq 02ZHR_PA_MD_UE_INFTY_0001_02Active
ZHR_SFW_PA_MD_UE_INFTY_0001_2ASwitch for Infotype 0001 - Seq 2ANoneStandby

Business Function Activation


Our BF is fully reversible i.e. it can be turned ON or OFF any time in the development system - we have turned our BF ON (Green traffic lights) however it contains 5 Switches some of which are turned ON (Green traffic lights) and others are on Standby (Yellow traffic lights). You can also view the Package Assignments for every Switch from the SFW hierarchy browser (see screen-shot below)

Confirmation that the Business Function is Active

Custom Enhancement Spot BAdI Definition and Enhancement Implementations


In the next step we create our custom Kernel BAdI definition and mark it for Multiple Use, Reusing Instantiation for Instance creation.

Our BAdI definition uses standard interface IF_EX_HRPAD00INFTY but because it is an Enhancement Spot BAdI it also requires the interface IF_BADI_INTERFACE to work with. As a result I had to create interface ZHR_IF_EX_PA_MD_UE then include the standard interfaces as above.

The BAdI defintion also defines a Filter i.e. it is Filter Dependent on the Infotype number (see screen shot below) which in effect means every implementation will be called by the framework with a match of the specific Filter value (in this case it is the infotype number) that will be defined in its BAdI implementation.

In the below screen-shot the value of the Filter has been specified in the BAdI implementation for Infotype 0000; which is bound within the rules of the Filter defined within the BAdI Definition.

We proceed to create our first Enhancement Implementation on this BAdI (for Infotype 0000 processing) assigning it to the Package ZHR_PA_MD_UE_INFTY_0000. This is because we had assigned this Package to Switch ZHR_SFW_PA_MD_UE_INFTY_0000 earlier therefore we would like to control this implementation of infotype 0000 with this Switch (refer table of Linkage above)

You will notice under Runtime Behaviour, in the field Switch Framework, the system has detected that this implementation is currently switched off by the assigned Switch ZHR_SFW_PA_MD_UE_INFTY_0000. The properties of this Enhancement Implementation also automatically is set to Standby as per the activation status of the assigned switch (see screen-shot below)

The developer can now proceed to create a BAdI implementation on this Enhancement Implementation then write the source code in its implementing Class (in the methods of the interface that it inherits) as per normal. Note that neither the BAdI implementation nor its implementing Class are switchable by themselves - it is the Enhancement Implementation object that is connected with the Switch which then controls its BAdI implementations & their respective implementation Classes.

Next, we create 2 Enhancement implementations (EIs) for Infotype 0001 - then we create 3 BAdI implementations on top of these 2 EIs. (as per screen-shots below). Actually I did create one more EI in the prototype but let's just ignore it as the ones explained below is exactly the same.

Note that the above EI is assigned to the Package  ZHR_PA_MD_UE_INFTY_0001 which in turn has been assigned to Switch ZHR_SFW_PA_MD_UE_INFTY_0001 and its activation status in ON

Our final EI on (Infotype 0001) has two BAdI implementations. As stated already, the BAdI implementations themselves are not switchable but they are controlled by the Switch incorporated in their EI. The EI above is assigned to Package ZHR_PA_MD_UE_INFTY_0001_02 which in turn is assigned to the Switch ZHR_SFW_PA_MD_UE_INFTY_0001_02 and its activation status is ON. However, the second BAdI implementation 02A has its own defined Switch ZHR_SFW_PA_MD_UE_INFTY_0001_2A which has no Package assignment and it is turned OFF.

Because the Switch behind the EI is turned ON, both the BAdI implementations will be called by the system but we have deactivated the Switch of the second one and therefore we do not want to call its business logic at runtime. To achieve this requirement, we implicitly check the Switch in the implementing Class of 02A as per screen-shots below in both its Methods that are called by the system at the time of HR master data maintenance.

Implicit Switch check in the PBO Method

And the same for the PAI Method

Finally, we call our BAdI from the Function Exits of PBAS0001 - we call the Method before_output from the PBO passing the infotype number to the BAdI Filter

And the Method after_input from the PAI passing the infotype number to the BAdI Filter

That's the only source code that is ever going to be there so this is going to be pretty much static. All business logic for all the infotypes will reside separately in the BAdI implementation Classes.

Now that our model is ready, let's revisit the SFW Browser to look at the final relationships.

Let's also revisit all the components of our Enhancement Spot and its relationships.

     Benefits of the Enhancement Spot BAdI


  • The business logic has now been decoupled - we are now free to call it in any application by using the same source code above - we also have control over which particular infotype logic we want to call/validate in our applications taking advantage of the BAdI Filter by simply passing the infotype number to the filter. Hence this BAdI is reusable across the landscape.
  • If another object (zcl__xyz) needs access to a Private method of a specific implemention class (for e.g. to reuse a method which does a complicated calc and returns a value) - this can also be achieved by making it "Friends" with the BAdI Impl. class then simply instatiate it from zcl_xyz as normal.
  • The developers no longer have to worry about existing logic and functionalities in place as long as they implement their own business logic via a new implementation of this BAdI.
  • The entire Business Function (the UE in question) can be turned ON or OFF easily via the Switch framework.
  • Each implementation can also be turned ON or OFF via the Switch framework therefore control is available at more granular level - commenting out of source code etc. are not required.
  • Implementations are structured, layered by business logic and source code is not cluttered any more as the developers do not need to touch the old/existing implementations but focus on their own implementations.
  • Testing and regression testing is much easier now - Isolate the cause of the defects by simply turning the implementations OFF then ON one at a time as when required.

Conclusion

We have demonstrated the ease of developing enhancements by using the New Enhancement Framework leveraging the benefits of the powerful Switch framework to simplify, structure and add lots of flexibility to the enhancement builds.

22 Comments