Many times, I see incorrect usage of ABAP Objects in custom development. In this two post blog series, I would show few incorrect designs and finally would show OO approach.
Incorrect Usage of Object Oriented
As part of my QA review responsibilities, many times, I see the report programs which are trying to use Object Oriented but would fail achieving any kind of object orientation. I consider these approaches as Pseudo OO Designs where the OO becomes just a vehicle to drive the procedural code. Something like this:
I would start this post with few bad examples. After them, I would take you back to procedural program – very simple program using subroutines. After that, I would show you the way I generally write Report programs using OO.
Only Static methods
Most of the times, I see developers are using only static methods in local class. Mainly the methods serve kind of wrapper to just have all the logic within it. Generally, there would GET_DATA and SHOW_DATA methods. This is not at all considered as Object Oriented design as there no objects involved only static method calls !
* Class definition CLASS LCL_VALIDATION DEFINITION FINAL. PUBLIC SECTION. CLASS-METHODS : AUTHORITY_CHECK_TCODE, VALIDATE_CUSTOMER, VALIDATE_BILLING_TYPE. ENDCLASS.
Basic problems using this approach
- The core logic of the report is hidden beneath the local classes in the program. As I have noted in when to use local class, this limits the reuse of the core logic
- Static methods along with other issues, lacks the basic advantage of method redefinition as we recently discussed in ABAP Static vs Instance method – Which to use when?
Wrapper methods to call Subroutines
Another flavor of what I generally face the design using the wrapper methods. You would see a method call in say START-OF-SELECTION, but that method would just call another subroutine. This subroutine would have more code modularization.
CLASS LCL_REPORT_PROCESS IMPLEMENTATION. * METHOD GET_DATA. PERFORM F_GET_DATA. ENDMETHOD. * METHOD FILL_FINAL_DATA. PERFORM F_FILL_FINAL_DATA. ENDMETHOD. * METHOD GENERATE_OUTPUT. PERFORM F_GENERATE_OUTPUT. ENDMETHOD. * ENDCLASS. " LCL_REPORT_PROCESS IMPLEMENTATION
By simply looking at the design you would think what would be the benefit of using the methods as wrapper to the subroutines. This design has more issues than the previous one as this creates lot more confusion on which method calls which.
Use of Selection Screen Parameters & Select Options in the method implementations
All the time, whenever I see the OO ABAP used for any report, I see that developers are always using the parameters and select options directly in the method implementation. This makes the method impossible to use in any other way.
* DATA: V_WERKS TYPE T001W-WERKS. * CLASS LCL_VALIDATION DEFINITION FINAL. PUBLIC SECTION. CLASS-METHODS :VALIDATE_PLANT. ENDCLASS. * * *... * Validate Plant. METHOD VALIDATE_PLANT. IF S_WERKS IS NOT INITIAL. " << Select Option SELECT WERKS UP TO 1 ROWS FROM T001W INTO V_WERKS WHERE WERKS IN S_WERKS. ENDSELECT. IF SY-SUBRC NE 0 AND V_WERKS IS INITIAL. " ENDIF. ENDIF. ENDMETHOD. "VALIDATE_PLANT
Global Variables instead of Instances
In this approach, developers try to use the Local Instance methods, but they still declare all the TYPES, DATA, Internal tables everything as Global Variables. Many times, these variables wont be used in more than one place.
In the code above, you can see that V_WERKS is not declared locally in the method. There isn’t any need for doing that.
Lets take a step back and think how this design can be improved. So, Start with this basic program. Program has few subroutines to validate the input, get the data and generate the output.
*&---------------------------------------------------------------------* *& Purpose - Simple procedrual report *& Author - Naimesh Patel *& URL - http://zevolving.com/?p=2037 *&---------------------------------------------------------------------* REPORT ztest_np_t100_report. * DATA: v_msgnr TYPE t100-msgnr. DATA: v_arbgb LIKE t100-arbgb. * DATA: t_t100 TYPE STANDARD TABLE OF t100. DATA: o_salv TYPE REF TO cl_salv_table. * SELECTION-SCREEN: BEGIN OF BLOCK blk1 WITH FRAME TITLE text-t01. PARAMETERS: p_arbgb TYPE t100-arbgb OBLIGATORY. SELECT-OPTIONS: s_msgno FOR v_msgnr. SELECTION-SCREEN: END OF BLOCK blk1. * AT SELECTION-SCREEN ON p_arbgb. PERFORM f_validate_message_class. * START-OF-SELECTION. PERFORM f_get_data. * END-OF-SELECTION. PERFORM f_show_data. * FORM f_validate_message_class. SELECT SINGLE arbgb INTO v_arbgb FROM t100 WHERE arbgb = p_arbgb. IF sy-subrc NE 0. MESSAGE 'Message Class not found' TYPE 'E'. ENDIF. ENDFORM. "f_validate_message_Class * * FORM f_get_data. SELECT * FROM t100 INTO TABLE t_t100 WHERE arbgb = p_arbgb AND msgnr IN s_msgno. ENDFORM. "f_get_Data * * FORM f_show_data. TRY. CALL METHOD cl_salv_table=>factory IMPORTING r_salv_table = o_salv CHANGING t_table = t_t100. o_salv->display( ). CATCH cx_salv_msg . ENDTRY. ENDFORM. "f_show_Data
In the next post, I would cover, how you can achieve much more flexible and reusable design. The second part is now available at ABAP Object Oriented Approach for Reports – Redesign