Gyan Factory

Gyan Factory
SAP Technical Project Support

Tuesday, February 16, 2016

ABAP Object Oriented Approach for Reports – Redesign

In this post, I would show you a more flexible design using ABAP Objects. This design is to decouple logic, criteria, data display as much as possible.

Introduction

As discussed in the previous post ABAP Object Oriented Approach for Reports – Initial Design (which got very good response – 14 comments and counting), I see lot of developers following bad design while trying to use Object Oriented. This I generally refer as Pseudo Object Oriented as this design doesn’t leverage any OO features.
I would show you how to implement the example used in previous post with OO approach. This approach is based purely on Model View Controller aka MVC. If you are not yet familiar with MVC, I would suggest you to read my old 3 post series starting with: ABAP Objects Design Patterns – Model View Controller (MVC) Part 1

Participants

For the simple report, I would create three classes:
  • SEL – Class for SELECTION criteria
  • DATA (Model) – DATA Selection & processing class
  • ALV (View) – Class to Display data
Whole idea here is to decouple as much as possible. So, based on that, we would move all the data selection and processing related logic into a DATA class. This DATA Class would have different methods to retrieve and process the data based on the selection criteria. Instead of creating the selection criteria as parameters to the method or Attributes of the data class and having them embedded in the DATA class, I would have them in a separate class – SEL Class. This would provide me an advantage of passing the SEL object to DATA class as well as to ALV class if required. Next step is to decouple the View related functionality out of the report. So, I would create ALV class.

UML for the design

The basic design on UML…
Additionally I have created a Exception class ZCX_MSG to handle the messages raised from the object model. If you are not yet familiar with Class Based Exception, I would suggest you to read one of my multi-post series starting with Class-based Exceptions I – Basics and get used to it.

SEL Class

SEL Class would be responsible to carrying the attributes to Model (DATA) and View (ALV) as needed. Since the selection criteria are not embedded in MODEL class, you could easily pass the object to another model class. SEL Class responsibilities and attributes:
  • Contains the attributes for all the parameters and select options from selection screen
  • Contains the methods for Default value population on the screen
  • Contains the methods to validate the selection screen values
  • All the attributes would be only set just when processing the event START-OF-SELECTION

Code lines for SEL Class – ZCL_REPORT_T100_SEL

This demo SEL class has two attributes to hold selection criteria. It also has two methods, GET_DEFAULT for default values and VALIDATE_MESSAGE_CLASS for validation.
Code lines for SEL ZCL_REPORT_T100_SEL class

 
* Types for the Attributes
  TYPES:
    tt_MSGNR_Range TYPE RANGE OF t100-MSGNR .
 
  DATA V_ARBGB TYPE T100-ARBGB .
  DATA T_MSGNR_RANGE TYPE TT_MSGNR_RANGE .
*
CLASS ZCL_REPORT_T100_SEL IMPLEMENTATION.
  METHOD GET_DEFAULT.
"     returning value(RV_ARBGB) type T100-ARBGB .
    rv_arbgb = '00'.
  ENDMETHOD.
*
  METHOD validate_message_class.
"    importing !IV_ARBGB type T100-ARBGB
"    raising   ZCX_MSG .
    DATA: ls_msg TYPE symsg.
    SELECT SINGLE arbgb
      INTO v_arbgb
      FROM t100
      WHERE arbgb = iv_arbgb.
    IF sy-subrc NE 0.
      ls_msg-msgty ='E'.
      ls_msg-msgid ='00'.
      ls_msg-msgno = '398'.
      ls_msg-msgv1 = 'No Message class found'.
      RAISE EXCEPTION TYPE zcx_msg
        EXPORTING
          msg = ls_msg.
    ENDIF.
  ENDMETHOD.
ENDCLASS.
 

DATA Class

DATA class would be responsible to fetch the data and prepare it in desired output. Typical DATA Class would preform these:
  • Would contain all the methods for data selection
  • Would use the attributes from the SEL objects for the data selection and filtration
  • Would contain instance attributes. Only the one which are needed to be exposed would be made Public, all the rest would be Private.
  • This could in turn use different objects as needed

Demo DATA class – ZCL_REPORT_T100_DATA

This class contains two attributes: O_SEL reference to ZCL_REPORT_T100_SEL and T_T100 to store the selected data. In the method CONSTRUCTOR, we set the O_SEL from importing parameter. Method GET_DATA selects the data using the SEL object attributes.
Code lines for the methods of DATA class ZCL_REPORT_T100_DATA

 
CLASS ZCL_REPORT_T100_DATA IMPLEMENTATION.
  METHOD CONSTRUCTOR.
"    importing !IO_SEL type ref to ZCL_REPORT_T100_SEL .
    me->o_Sel = io_sel.
  ENDMETHOD.
*
  METHOD GET_DATA.
    SELECT * FROM t100
      INTO TABLE t_t100
      WHERE arbgb =  me->o_sel->v_arbgb
      AND   msgnr IN me->o_Sel->T_MSGNR_RANGE.
  ENDMETHOD.
ENDCLASS.
 

ALV class

Typical View class is responsible to display data to the Caller as well as handling any action. ALV class:
  • Would contain the logic related to ALV processing
  • Also contains the event handler methods to handle any needed events
  • Would contain the DATA class an attribute. This would provide the access to the Public attributes thus gaining access to Data contents

Demo ALV class – ZCL_REPORT_T100_ALV

This class contains two attributes O_DATA reference to data class ZCL_REPORT_T100_DATA and O_SALV reference to CL_SALV_TABLE. Contains couple of methods – CONSTRUCTOR to set the DATA object and GENERATE_ALV to generate the simple ALV.
Code lines for the methods of ALV class ZCL_REPORT_T100_ALV

 
CLASS ZCL_REPORT_T100_ALV IMPLEMENTATION.
  METHOD CONSTRUCTOR.
"   importing !IO_DATA type ref to ZCL_REPORT_T100_DATA .
    me->o_Data = io_data.
  ENDMETHOD.
*
  METHOD GENERATE_ALV.
    TRY.
        CALL METHOD cl_salv_table=>factory
          IMPORTING
            r_salv_table = me->o_salv
          CHANGING
            t_table      = me->o_data->t_t100.
*  
        me->o_salv->display( ).
*  
      CATCH cx_salv_msg .
    ENDTRY.
  ENDMETHOD.
ENDCLASS.
 

Program based on Object Oriented Approach

Here is the redesigned version of the procedural code to use the all the classes which we have declared.

 
*&---------------------------------------------------------------------*
*& Purpose - Object Oriented Implementation for a Report
*& Author  - Naimesh Patel
*& URL     - http://zevolving.com/?p=2045
*&---------------------------------------------------------------------*
REPORT ztest_np_t100_OO_report.
*
DATA: v_msgnr TYPE t100-msgnr.   " for selection screen
*
DATA: o_data TYPE REF TO zcl_report_t100_data.
DATA: o_sel  TYPE REF TO zcl_report_t100_sel.
DATA: o_alv  TYPE REF TO zcl_report_t100_alv.
DATA: o_exc  TYPE REF TO zcx_msg.
*
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.
*
INITIALIZATION.
  CREATE OBJECT o_sel.
  CREATE OBJECT o_data EXPORTING io_sel  = o_sel.
  CREATE OBJECT o_alv  EXPORTING io_data = o_data.
  p_arbgb = o_sel->get_default( ).
*
AT SELECTION-SCREEN ON p_arbgb.
  TRY.
      o_sel->validate_message_class( p_arbgb ).
    CATCH zcx_msg INTO o_exc.
      MESSAGE ID o_exc->msg-msgid TYPE o_exc->msg-msgty
              NUMBER o_exc->msg-msgno
              WITH  o_exc->msg-msgv1 o_exc->msg-msgv2
                    o_exc->msg-msgv3 o_exc->msg-msgv4.
  ENDTRY.
*
START-OF-SELECTION.
" Set the attributes of the SEL object from the
" Selection screen parameters & Options
  o_sel->v_arbgb = p_arbgb.
  o_sel->t_msgnr_range = s_msgno[].
*
* Get the data
  o_data->get_data( ).
*
* Generate the ALV
  o_alv->generate_alv( ).
 
 

UML for the demo program

This is how it looks from UML point of view

Advantages

This design definitely needs more effort to achieve than the procedural approach, but this would have more flexibility, less maintenance – reducing overall Total Cost of Ownership (TCO).
  • Since the Model class is decoupled from the program it acts independently. It can be plug and play in any different Views
  • Separate SEL object makes it free from using the Selection screen parameters and Select Options within the method implementation. This makes it independent than using any selection screen. As long as you set the proper attributes, you would be able use it with DATA class
  • Separate View makes it more reusable
Think about developing a WebDynpro using the same logic – Set the proper attributes to SEL object, Instantiate the DATA class and call methods to get the data. Pass the data to WebDynpro View to generate the Output.
OR
Think about exposing this data and use it in bigger application where you need the data to display in an existing complex design – same steps as above which would get you the desired output.

What Do You Think?

Will you be using this design? Do you think its good approach? or Do you think its over kill?

No comments:

Post a Comment