Object Oriented ABAP is taking slow phase in adoption for Pure ABAPers(Not working in Webdynpro or other object oriented space); even I took a yearlong to completely do my work in OO.
Even I was in a situation when one of my clients questioned, why you code in OO as he was not able to understand. I was dumbstruck and the thought provoked me to write this for guys who are in dilemma on how to move to OO.
I have seen many blogs on ABAP OO which will be a good start for learning (explaining concepts and examples) but still faced few challenges in moving to ABAP OO like where and how to start, just putting down my thoughts about the problems which faced little longer and ways I overcame
Few road blocks in using ABAP OO
o Understanding concepts of OO who has no previous knowledge on OO
o How to implement the same in our regular work in RICEF objects.
o How to use major advantages of OO
This blog is for experienced developers, who are familiar with OO concepts but lazy in implementing the same in ABAP. Before I talk about any of these stuff, I would like to tell how to get familiarize with classes. (Note: This blog only provides approach and not any examples)
For newbies to ABAP OO, can get familiarize with these links?
http://help.sap.com/saphelp_nw2004s/helpdata/en/c3/225b5654f411d194a60000e8353423/frameset.htm
http://wiki.scn.sap.com/wiki/display/ABAP/ABAP+Objects+Getting+Started
I will show a small example report getting some entries from MARA and using CL_SALV_TABLE to display the same in ALV in four ways here
· Traditional way of writing
· OO way (only using Static methods) – To get the hang of class and method concept
· OO way (Only Instance methods) – To get the hang of class and method concept
· My IDEAL way in OO
· New Trend of and completely moving your report to OO.
REPORT ysdnblog_classic.
PARAMETERS : p_rows TYPE count DEFAULT '100'.
START-OF-SELECTION.
DATA : it_mara TYPE STANDARD TABLE OF mara.
PERFORM get_data CHANGING it_mara.
PERFORM display USING it_mara.
*&---------------------------------------------------------------------*
*& Form GET_DATA
*&---------------------------------------------------------------------*
FORM get_data CHANGING ch_mara TYPE mara_tt.
SELECT * FROM mara INTO TABLE ch_mara UP TO p_rows ROWS .
ENDFORM. " GET_DATA
*&---------------------------------------------------------------------*
*& Form DISPLAY
*&---------------------------------------------------------------------*
FORM display USING i_mara TYPE mara_tt.
DATA : lr_table TYPE REF TO cl_salv_table.
cl_salv_table=>factory( IMPORTING r_salv_table = lr_table
CHANGING t_table = i_mara ) .
lr_table->display( ).
ENDFORM. " DISPLAY
Let’s start with classes and don’t go in to boring part of explaining what is a STATIC or INSTANCE method (Please google or go through about this stuff). Major developers who are new to OO, first question is whether my method should be INSTANCE or STATIC? Let’s save this question to the last.
First to get the hang of the OO ABAP from traditional ABAP using STATIC methods only and above report looks like this: (suggest continuing writing couple of reports/objects)
REPORT ysdnblog_class_static. START-OF-SELECTION. lcl_main=>get_data( ). lcl_main=>display( ).
PARAMETERS : p_rows TYPE count DEFAULT '100'.
*----------------------------------------------------------------------*
* CLASS lcl_main DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_main DEFINITION.
PUBLIC SECTION.
CLASS-METHODS : get_data ,
display.
PRIVATE SECTION.
CLASS-DATA it_mara TYPE mara_tt.
ENDCLASS. "lcl_main DEFINITION
*----------------------------------------------------------------------*
* CLASS lcl_main IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_main IMPLEMENTATION.
METHOD get_data.
SELECT * FROM mara INTO TABLE lcl_main=>it_mara UP TO p_rows ROWS .
ENDMETHOD. "GET_DATA
METHOD display.
DATA : lr_table TYPE REF TO cl_salv_table.
cl_salv_table=>factory( IMPORTING r_salv_table = lr_table
CHANGING t_table = lcl_main=>it_mara ) .
lr_table->display( ).
ENDMETHOD. "display
ENDCLASS. "lcl_main IMPLEMENTATION
OK... I hope by now you got hang of what a traditional report looks in CLASS/METHODS.
OO way (Only Instance methods) – To get the hang of class and method concept
What’s next? Let’s see the same program with instance methods. Additional steps would be declaration of an object and instantiate it to use in your program.
REPORT ysdnblog_class_instance. START-OF-SELECTION. data : lr_main TYPE REF TO lcl_main. create OBJECT lr_main.
PARAMETERS : p_rows TYPE count DEFAULT '100'.
*----------------------------------------------------------------------*
* CLASS lcl_main DEFINITION
*----------------------------------------------------------------------*
CLASS lcl_main DEFINITION.
PUBLIC SECTION.
METHODS : get_data ,
display.
PRIVATE SECTION.
DATA it_mara TYPE mara_tt.
ENDCLASS. "lcl_main DEFINITION
*----------------------------------------------------------------------*
* CLASS lcl_main IMPLEMENTATION
*----------------------------------------------------------------------*
CLASS lcl_main IMPLEMENTATION.
METHOD get_data.
SELECT * FROM mara INTO TABLE me->it_mara UP TO P_rows ROWS .
ENDMETHOD. "GET_DATA
METHOD display.
DATA : lr_table TYPE REF TO cl_salv_table.
cl_salv_table=>factory( IMPORTING r_salv_table = lr_table
CHANGING t_table = me->it_mara ) .
lr_table->display( ).
ENDMETHOD. "display
ENDCLASS. "lcl_main IMPLEMENTATION
lr_main->get_data( ).
lr_main->display( ).
In the above example we declare an object reference of type LCL_MAIN and have to command CREATE OBJECT to create a reference for further usage of the same in program. (The same LCL_MAIN can be declared with different names (many references) and initiated based on the requirement needs)
Please do some live programs either using with any of the above ways to really get initial kick start of OO.
My IDEAL way in OO
MY IDEAL way of writing the above program would be as below.
REPORT ysdnblog_class_ideal.
parameters : p_rows type count default '100'.
*----------------------------------------------------------------------*
* CLASS lcl_main DEFINITION
*----------------------------------------------------------------------*
CLASS lcl_main DEFINITION.
PUBLIC SECTION.
CLASS-METHODS : start.
PRIVATE SECTION.
METHODS : get_data ,
display.
CLASS-DATA : lr_main TYPE REF TO lcl_main.
DATA it_mara TYPE mara_tt.
ENDCLASS. "lcl_main DEFINITION
*----------------------------------------------------------------------*
* CLASS lcl_main IMPLEMENTATION
*----------------------------------------------------------------------*
CLASS lcl_main IMPLEMENTATION.
METHOD start.
CREATE OBJECT lr_main.
lr_main->get_data( ).
lr_main->display( ).
ENDMETHOD. "start
METHOD get_data.
SELECT * FROM mara INTO TABLE me->it_mara UP TO P_rows ROWS .
ENDMETHOD. "GET_DATA
METHOD display.
DATA : lr_table TYPE REF TO cl_salv_table.
cl_salv_table=>factory( IMPORTING r_salv_table = lr_table
CHANGING t_table = me->it_mara ) .
lr_table->display( ).
ENDMETHOD. "display
ENDCLASS. "lcl_main IMPLEMENTATION
START-OF-SELECTION.
lcl_main=>start( ).
Here we call the START method only once for a program and so I made it as a static method and one static object (LR_MAIN referencing the same class ) for dealing with rest of the business logic. (There can be many better ways as well.. )
New Trend of and completely moving your report to OO:
The new way of writing the reports includes t-code to launch your report. Let’s start with T-code creation as below and select 3rd option METHOD OF A CLASS (OO TRANSACTION).
Next step navigates to below screen and un check the box OO TRANSACTION MODEL enabling another field LOCAL IN PROGRAM
Now provide your program name and local class name and method for the below program. Program looks like below
REPORT ysdnblog_class_new.
SELECTION-SCREEN : BEGIN OF SCREEN 200.
PARAMETERS p_rows TYPE count DEFAULT '100'.
SELECTION-SCREEN : END OF SCREEN 200.
*----------------------------------------------------------------------*
* CLASS lcl_main DEFINITION
*----------------------------------------------------------------------*
CLASS lcl_main DEFINITION.
PUBLIC SECTION.
CLASS-METHODS : start.
PRIVATE SECTION.
METHODS : get_data ,
display.
CLASS-DATA : lr_main TYPE REF TO lcl_main.
DATA it_mara TYPE mara_tt.
ENDCLASS. "lcl_main DEFINITION
*----------------------------------------------------------------------*
* CLASS lcl_main IMPLEMENTATION
*----------------------------------------------------------------------*
CLASS lcl_main IMPLEMENTATION.
METHOD start.
BREAK-POINT.
CALL SELECTION-SCREEN 200.
IF sy-subrc IS INITIAL.
CREATE OBJECT lr_main.
lr_main->get_data( ).
lr_main->display( ).
ENDIF.
ENDMETHOD. "start
METHOD get_data.
SELECT * FROM mara INTO TABLE me->it_mara UP TO p_rows ROWS .
ENDMETHOD. "GET_DATA
METHOD display.
DATA : lr_table TYPE REF TO cl_salv_table.
cl_salv_table=>factory( IMPORTING r_salv_table = lr_table
CHANGING t_table = me->it_mara ) .
lr_table->display( ).
ENDMETHOD. "display
ENDCLASS. "lcl_main IMPLEMENTATION
START-OF-SELECTION.
lcl_main=>start( ).
Here you are taking control on when your selection screen should trigger. Things you need to observe in above program
· Your selection screen is defined as a screen with a different number, which is 200
· You are explicitly triggering your selection screen 200 in the START method rather than giving control to framework. (Note the other events AT SELECTION SCREEN will work as usual.)
· When the transaction is executed; first it triggers the method specified in the transaction
By slowly adapting to above approached you can change your coding style to OO.
There can be many other ways and this is just little knowledge sharing based on my experience. Comments and suggestions are welcome.