Migration from Function Groups to ABAP-OO Artifacts; the manual way 3/3
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_message.htm.
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|
Data(gr_fg1) = Zcl_fg1=>s_get_instance( ).
- 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.
- 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.
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.
Call function ‘ZFG_FM1’
not_found = 1
some_error = 2
others = 3.
Class zcl_caller definition:
Data mv_fg1 type ref to zif_fg1.
Class zcl_caller implementation.
mv_fg1 = zcl_fg1=>s_get_instance( ).
Catch zcx_fg1 into data(lx_fg1).
Data(ls_t100) = lx_fg1~if_t100_message~t100key.
Sy-subrc = 1.
Sy-subrc = 2.
Sy-subrc = 3.
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.
- 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.
- 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.