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: 
joachim_gross
Explorer
This is part 3 of my series regarding migration function groups.

Starting Blog is Part 1 of 3

Now i will discuss the necessary adaptions in the callers to use the new code artifacts.


Post Creation Effort


Caller Adaption vs Function Group change


All these created classes must be used. Otherwise this whole activity doesn’t make sense.

The former function group need to be adapted/ deleted to avoid duplication of code.

There are two approaches which are both useful.

Approach 1: Function Group change


This approach is to be used for function groups / modules, which cannot be fully migrated. By example RFC function modules could be changed with this approach.

Nearly everything of the function group should be deleted. All function modules should be changed to call only the related method of the new class.
This approach follows the programming guideline rule ‘No implementations in function modules and subroutines’ https://help.sap.com/doc/abapdocu_751_index_htm/7.51/en-US/index.htm?file=abapraise_exception_messag....

Example


Function group ‘ZFG1’ has a function module called ‘ZFG1_FM1’. It has two exceptions ‘NOT_FOUND’ and ‘SOME_ERROR’.

A class ‘ZCL_FG1’ with method ‘ZIF_FG1~M1’ has been generated.
An exception class zcx_fg1 has been generated.














Function Module before generation Created Method Function Group / Module after code exchange

Function ZFG1_FM1.

If 1 = 1.

* Do something

Endif.

Endfunction

.

class zcl_fg1 definition.
public section.
interfaces zif_fg1.
endclass.

class zcl_fg1 implementation.
Method ZIF_FG1~M1.
If 1 = 1.
* Do something
Endif.
Endmethod.
endclass.



Event Load-of-program.

Data(gr_fg1) = Zcl_fg1=>s_get_instance( ).

 
Function ZFG1_FM1.

Try.
gr_fg1->m1( ).
Catch zcx_fg1 into data(lx_fg1).
Data(ls_t100) =
lx_fg1~if_t100_message~t100key.
Case ls_t100-attr1.
When ‘NOT_FOUND’.
Raise exception not_found.
When ‘SOME_ERROR’.
Raise exception some_error.
When others.
Endcase.
Endtry.

Endfunction.



Pros



  • The exchange of the implementation of the function modules now calling only the methods has the least impact as nearly no caller has to be adapted.

  • Dynamic calls of these function modules mostly work out of the box.


Cons



  • No testability improvement for the callers.

  • This approach doesn’t solve the task to get rid of the code style complexity.

  • It even doesn’t solve the problem with implicit enhancements mentioned at start: Enhancements of form routines and usage of other components of the function group like global variables are broken.


Approach 2: Caller Adaption


Adapt the caller(s) to call the new method instead of the previously used function module. The function module / function group should be deleted or set to obsolete raising assert in all function modules.

Example


A method ZCL_CALLER->m2 calls previously function module ‘ZFG_FM1’ (see example above).












Method ZCL_CALLER->m2 before Class ZCL_CALLER->m2 after adaption


 

 

 

 

 

Class zcl_caller implementation.

 

 

 

 

Method m2.



Call function ‘ZFG_FM1’

Exceptions

not_found = 1

some_error = 2

others = 3.

 

 

 

 

 

 

 

 

Case sy-subrc.

When 0.

When 1.

When 2.

When others.

Endcase.

 



Endmethod.

Endclass.


Class zcl_caller definition:

Private section.

Data mv_fg1 type ref to zif_fg1.

Endclass.

 

Class zcl_caller implementation.

Method constructor.

mv_fg1 = zcl_fg1=>s_get_instance( ).

Endmethod.

 

Method m2.



Try.

  mv_fg1->m1( ).

  Catch zcx_fg1 into data(lx_fg1).

    Data(ls_t100) = lx_fg1~if_t100_message~t100key.

    Case ls_t100-attr1.

      When ‘NOT_FOUND’.

       Sy-subrc = 1.

      When ‘SOME_ERROR’.

        Sy-subrc = 2.

      When others.

        Sy-subrc = 3.

    Endcase.

  Endtry.

Case sy-subrc.

When 0.

When 1.

When 2.

When others.

Endcase.

 



Endmethod.

Endclass.


A late instantiation of zcl_fg1 would also be possible.

One should think about not encapsulate this one method call with a specific try-catch-block but to have one big try-catch-block, if feasible.

Even better would be an adaption to class-based exception in the caller, too.

Pros



  • Enable mocking of the generated class in the caller, improve testability.

  • Avoid bouncing between procedural and class based code style.

  • Improves performance as no function group has to be loaded upon usage and one entry less in the call-stack.


Cons



  • If the function modules are called very often this could result into quite some workload.
    To ease this one the refactoring workbench can show a where-used-list. An automated adaption is questionable as this would only help if the function groups are converted in a bottom-up style.

  • Per each caller one has to make up her/his mind how to adapt exception handling.