Skip to Content

In this blog, I will not be discussing about Object Oriented Concepts and theory as there are many documents and information available regarding the same. I am gonna discuss about how to start thinking in object oriented rather than procedural approach, how to implement or use the object oriented concepts while writing your code by benefiting your code performance, making your code compact and more reusable etc.

THINK OO

It is easy for an ABAPer who has been coding in ABAP(procedural) to code in ABAP OO by defining a local class and using methods instead of performs but that is not object oriented! To make use of object oriented concepts, you need to think OO. Think of what you need to develop in your code as objects.

You need to first design the requirement in Object oriented then it will be easy when you start coding.

For e.g. if you need to develop a report which displays a header and item alv then consider a parent class alv which has all the common attributes and methods which are inherited by 2 sub classes header and item alv. you can define the methods that are common for both in the parent class and methods that are different in each of the sub classes.

CODING IN OO

After designing when you are coding in OO, make use of the following points:

  • Standard classes/ methods: Try to use standard classes and methods available as much as you can. There are methods available for almost all function modules and more.
  • Re-usability: keep re-usability in mind and create methods which can be re-used more than once in your program.
  • Encapsulation: Encapsulate code into methods wherever you can.
  • Class-constructor and Constructor: When you want to initialize(assign values to variables/attributes) or perform a particular task once initially when a class object/method is called then use class-constructor. If you want to do the same when an object is created of the class then use constructor(instance constructor).
  • Interfaces: Make use of interfaces when two or more classes need common methods but with different logic/implementation.
  • Events: events are used when you want to trigger a particular method when an event happens. For e.g. Events for hot spot click and top of page.
  • Static and Instance attributes/methods: Static methods or attributes are used when you don’t want it to change the whole time for that particular time but Instance attributes value changes for each object.
  • Abstract classes: When there are certain methods which we do not want to use in the parent class but want to implement in the sub classes then we can make the class and those methods as abstract. If we do not want to use them in the subclass then make the subclass as abstract too but then if there is a sub class for this subclass which is not abstract these methods will need to be implemented there.
  • Alias: Alias is used when you want to shorten the name of the interface methods for a class.

SAMPLE PROGRAM CODE

To develop a Report for Purchase order using ABAP OOPS.

  • The selection screen contains Purchase order No and Date in Ranges.

Three radio button

  1. PO released list,
  2. PO rejected List
  3. PO Not released list
  • On selecting the corresponding radio button it should show the details for given selection screen values using container ALV.
  • The PO Description should be editable. On changing the description and saving, it should be updated to corresponding PO Number.
  • On clicking on PO number it should show Item details.
  • No Global data to be used in the report
  • The header and the item fields to be displayed in the ALV is the programmers choice

As per the feedback and comments I have received from all of you, I have corrected my code. I hope that I have been able to remove the flaws in my previous design. I am not posting screen shots this time as one complained that it disables them to copy paste my code if they want to try it.

In the main program, you can see that I have separated various parts of the code inside includes. It is not recommended to add an include unless there is at least 200 lines of code but top of page/ data definitions is usually written inside the include as the variables/objects can be reused by other programs in the package(I have very few definitions and hence I have removed the data definitions include).

REPORT  ZPO_OOPS.

TABLES: ekko.

INCLUDE ZPO_OOPS_SS.  “Selection Screen

INCLUDE ZPO_OOPS_CDI. “Class Definitions and Implementations

DATA: o_purchaseorder TYPE REF TO cl_purchaseorder,

       o_cont1         TYPE REF TO cl_gui_custom_container,

       o_cont2         TYPE REF TO cl_gui_custom_container,

       o_grid1         TYPE REF TO cl_gui_alv_grid,

       o_grid2         TYPE REF TO cl_gui_alv_grid.

INCLUDE ZPO_OOPS_PBO. “PBO Modules

INCLUDE ZPO_OOPS_PAI. “PAI Modules

START-OF-SELECTION.

CREATE OBJECT: o_purchaseorder.

CALL METHOD o_purchaseorder->select_po.

Class definition deferred statement is used when we create the objects of the class before the actual definition and implementation. This way the debugger will come to know that the definition is written later in the code. If we do not define it later on then it will show an error.( I do not need to use the deferred statement here as I have declared classes after the definition).

Selection screen

SELECTION-SCREEN: BEGIN OF BLOCK po WITH FRAME TITLE text-009.

SELECT-OPTIONS: s_ebeln FOR ekko-ebeln,

                 s_aedat FOR ekko-aedat.

SELECTION-SCREEN: END OF BLOCK po.

SELECTION-SCREEN: BEGIN OF BLOCK rb WITH FRAME TITLE text-010.

SELECTION-SCREEN: BEGIN OF LINE.

PARAMETERS: r_releas  RADIOBUTTON GROUP r1.

SELECTION-SCREEN COMMENT 2(15) text-000 FOR FIELD r_releas.

PARAMETERS: r_reject  RADIOBUTTON GROUP r1.

SELECTION-SCREEN COMMENT 20(15) text-001 FOR FIELD r_reject.

PARAMETERS: r_no_rel  RADIOBUTTON GROUP r1.

SELECTION-SCREEN COMMENT 40(17) text-002 FOR FIELD r_no_rel.

SELECTION-SCREEN: END OF LINE.

SELECTION-SCREEN: END OF BLOCK rb.

I have used a controller interface just to separate the methods used for alv display.

INTERFACE i_controller.

   METHODS: alv_display EXPORTING cont TYPE REF TO cl_gui_custom_container

                                  grid TYPE REF TO cl_gui_alv_grid

                                  name TYPE scrfname,

            fc_header,

            on_click FOR EVENT hotspot_click

            OF cl_gui_alv_grid

            IMPORTING e_row_id.

ENDINTERFACE.                    “Interface for output


I have used one Purchase order class where the attributes and methods that are accessed by the program directly are declared in the Public section and the attributes that are used inside methods of the class are declared under Private section(Encapsulation). Class-constructor is used when you want to initiate the attributes when the class is accessed the first time. In this case I am assigning the layout structure initially.

*———————————————————————-*

*       CLASS cl_purchaseorder DEFINITION

*———————————————————————-*

*

*———————————————————————-*

CLASS cl_purchaseorder DEFINITION.

   PUBLIC SECTION.

     CONSTANTS:  lc_cont1     TYPE scrfname VALUE ‘HEAD_CON’,

                 lc_cont2     TYPE scrfname VALUE ‘ITEM_CON’.

     DATA:       lv_cont      TYPE scrfname.

     DATA:       lt_ekko TYPE STANDARD TABLE OF zpo_st_ekko,

                 lt_ekpo TYPE STANDARD TABLE OF zpo_st_ekpo.

     DATA: lt_ekko_tmp TYPE STANDARD TABLE OF zpo_st_ekko.

     CLASS-DATA: ok_code      TYPE syucomm.

     CLASS-DATA: lx_layout    TYPE lvc_s_layo.

     DATA:       lt_fcat      TYPE lvc_t_fcat.

     CLASS-METHODS: class_constructor.

     INTERFACES: i_controller.

     ALIASES: alv_display FOR i_controller~alv_display,

              fc_header   FOR i_controller~fc_header,

              on_click    FOR i_controller~on_click.

     METHODS:   select_po,

                save,

                back,

                exit.

   PRIVATE SECTION.

     CONSTANTS: lc_procstat1 TYPE meprocstate VALUE ’01’,

                lc_procstat4 TYPE meprocstate VALUE ’04’,

                lc_procstat5 TYPE meprocstate VALUE ’05’,

                lc_procstat6 TYPE meprocstate VALUE ’06’.

     DATA: lv_ans   TYPE c.

     DATA: lv_procstat1 TYPE meprocstate,

           lv_procstat2 TYPE meprocstate.

     DATA: lx_fcat TYPE lvc_s_fcat.

     DATA: lx_ekko     TYPE zpo_st_ekko,

           lx_ekko_tmp TYPE zpo_st_ekko.

     DATA: lt_fieldcat  TYPE slis_t_fieldcat_alv,

           lx_fieldcat  TYPE slis_fieldcat_alv.

ENDCLASS.                    “cl_purchaseorder DEFINITION


I am created structures in the database to avoid building the field catalog, used the FM ‘REUSE_ALV_FIELDCATALOG_MERGE’ to get field catalog of a structure in order to modify it for hotspot and to make a field editable. Event hotspot_click is used for the method on_click. When we call set handler for this event, the method gets called each time the event is triggered. Constructor is called initially when the object of a class is created.

*———————————————————————-*

*       CLASS cl_purchaseorder IMPLEMENTATION

*———————————————————————-*

*

*———————————————————————-*

CLASS cl_purchaseorder IMPLEMENTATION.


   METHOD class_constructor.

     lx_layout-zebra = ‘X’.

     lx_layout-cwidth_opt = ‘X’.

   ENDMETHOD.                    “class_constructor


   METHOD alv_display.

     CREATE OBJECT cont

       EXPORTING

         container_name = name.

     CREATE OBJECT grid

       EXPORTING

         i_parent = cont.

   ENDMETHOD.                    “alv_display

   METHOD select_po.

     IF r_releas EQ ‘X’.

       lv_procstat1 = lc_procstat5.

       lv_procstat2 = lc_procstat5.

     ELSEIF r_reject EQ ‘X’.

       lv_procstat1 = lc_procstat5.

       lv_procstat2 = lc_procstat6.

     ELSEIF r_no_rel EQ ‘X’.

       lv_procstat1 = lc_procstat1.

       lv_procstat2 = lc_procstat4.

     ENDIF.

     SELECT ebeln

            bukrs

            description

            bstyp

            bsart

            aedat

            ernam

     FROM ekko

     INTO TABLE lt_ekko

     WHERE ebeln IN s_ebeln

     AND   aedat IN s_aedat

     AND   procstat BETWEEN lv_procstat1 AND lv_procstat2.

     IF lt_ekko IS NOT INITIAL.

       lt_ekko_tmp[] = lt_ekko[].

       CALL SCREEN 9000.

     ELSE.

       MESSAGE s000(8i) WITH text-011 DISPLAY LIKE ‘E’.

     ENDIF.

   ENDMETHOD.                    “select_po

   METHOD back.

     CALL FUNCTION ‘POPUP_TO_CONFIRM’

       EXPORTING

         text_question  = text-006

         text_button_1  = text-007                           “‘Ja'(001)

         text_button_2  = text-008″‘Nein'(002)

       IMPORTING

         answer         = lv_ans

       EXCEPTIONS

         text_not_found = 1

         OTHERS         = 2.

     IF sy-subrc EQ 0.

       CASE lv_ans.

         WHEN ‘1’.

           CALL METHOD me->save.

           LEAVE TO SCREEN 0.

         WHEN ‘2’.

           LEAVE TO SCREEN 0.

         WHEN ‘X’.

       ENDCASE.

     ENDIF.

   ENDMETHOD.                    “back


   METHOD exit.

     CALL FUNCTION ‘POPUP_TO_CONFIRM’

       EXPORTING

         text_question  = text-006

         text_button_1  = text-007                           “‘Ja'(001)

         text_button_2  = text-008″‘Nein'(002)

       IMPORTING

         answer         = lv_ans

       EXCEPTIONS

         text_not_found = 1

         OTHERS         = 2.

     IF sy-subrc EQ 0.

       CASE lv_ans.

         WHEN ‘1’.

           CALL METHOD me->save.

           LEAVE PROGRAM.

         WHEN ‘2’.

           LEAVE PROGRAM.

         WHEN ‘X’.

       ENDCASE.

     ENDIF.

   ENDMETHOD.                  “constructor

   METHOD save.

     LOOP AT lt_ekko_tmp INTO lx_ekko_tmp.

       READ TABLE lt_ekko INTO lx_ekko WITH KEY ebeln = lx_ekko_tmp-ebeln.

       IF sy-subrc EQ 0.

         IF lx_ekko-description NE lx_ekko_tmp-description.

           UPDATE ekko

       SET description = lx_ekko-description

       WHERE ebeln = lx_ekko-ebeln.

           IF sy-subrc EQ 0.

             MESSAGE s000(8i) WITH text-005.

           ENDIF.

         ENDIF.

       ENDIF.

     ENDLOOP.

     lt_ekko_tmp[] = lt_ekko[].

   ENDMETHOD.                    “save

   METHOD fc_header.

     CALL FUNCTION ‘REUSE_ALV_FIELDCATALOG_MERGE’

       EXPORTING

         i_structure_name       = ‘ZPO_ST_EKKO’

       CHANGING

         ct_fieldcat            = lt_fieldcat

       EXCEPTIONS

         inconsistent_interface = 1

         program_error          = 2

         OTHERS                 = 3.

     LOOP AT lt_fieldcat INTO lx_fieldcat.

       MOVE-CORRESPONDING lx_fieldcat TO lx_fcat.

       lx_fcat-coltext = lx_fieldcat-seltext_l.

       IF lx_fcat-fieldname = ‘EBELN’.

         lx_fcat-hotspot   = ‘X’.

       ELSEIF lx_fcat-fieldname = ‘DESCRIPTION’.

         lx_fcat-edit      = ‘X’.

       ENDIF.

       APPEND lx_fcat TO lt_fcat.

     ENDLOOP.

   ENDMETHOD.                    “fc


   METHOD on_click.

     READ TABLE lt_ekko INTO lx_ekko INDEX e_row_id-index.

     IF sy-subrc EQ 0.

       SELECT ebelp

              werks

              lgort

              aedat

              txz01

              matnr

       FROM ekpo

       INTO TABLE lt_ekpo

       WHERE ebeln = lx_ekko-ebeln.

       IF sy-subrc EQ 0.

         CALL SCREEN 9001.

       ENDIF.

     ENDIF.

   ENDMETHOD.                    “on_click

ENDCLASS.                    “cl_purchaseorder IMPLEMENTATION

PBO

*&———————————————————————*

*&  Include           ZPO_OOPS_PBO

*&———————————————————————*

*&———————————————————————*

*&      Module  STATUS_9000  OUTPUT

*&———————————————————————*

*       Header screen

*———————————————————————-*

MODULE status_9000 OUTPUT.

   SET PF-STATUS ‘STATUS_9000’.

   SET TITLEBAR ‘TITLE_9000’.

   IF o_grid1 IS INITIAL.

     o_purchaseorder->lv_cont = o_purchaseorder->lc_cont1.

     CALL METHOD o_purchaseorder->alv_display

       IMPORTING

         cont = o_cont1

         grid = o_grid1

         name = o_purchaseorder->lv_cont.

     CALL METHOD o_purchaseorder->fc_header.

     CALL METHOD o_grid1->set_table_for_first_display

       EXPORTING

         is_layout        = o_purchaseorder->lx_layout

*        i_structure_name = ‘ZPO_ST_EKKO’

       CHANGING

         it_outtab        = o_purchaseorder->lt_ekko

         it_fieldcatalog  = o_purchaseorder->lt_fcat.

     SET HANDLER o_purchaseorder->on_click FOR o_grid1.

   ELSE.

     CALL METHOD o_grid1->refresh_table_display.

   ENDIF.

ENDMODULE.                 ” STATUS_9000  OUTPUT

*&———————————————————————*

*&      Module  STATUS_9001  OUTPUT

*&———————————————————————*

*       Item Screen

*———————————————————————-*

MODULE status_9001 OUTPUT.

   SET PF-STATUS ‘STATUS_9000’ EXCLUDING ‘SAVE’.

   SET TITLEBAR ‘TITLE_9001’.

   IF o_grid2 IS INITIAL.

     o_purchaseorder->lv_cont = o_purchaseorder->lc_cont2.

     CALL METHOD o_purchaseorder->alv_display

       IMPORTING

         cont = o_cont2

         grid = o_grid2

         name = o_purchaseorder->lv_cont.

     CALL METHOD o_grid2->set_table_for_first_display

       EXPORTING

         is_layout        = o_purchaseorder->lx_layout

         i_structure_name = ‘ZPO_ST_EKPO’

       CHANGING

         it_outtab        = o_purchaseorder->lt_ekpo.

   ELSE.

     CALL METHOD o_grid2->refresh_table_display.

   ENDIF.

ENDMODULE.                 ” STATUS_9001  OUTPUT

PAI

*&———————————————————————*

*&  Include           ZPO_OOPS_PAI

*&———————————————————————*

*&———————————————————————*

*&      Module  USER_COMMAND_9000  INPUT

*&———————————————————————*

*       text

*———————————————————————-*

MODULE user_command_9000 INPUT.

   CASE cl_purchaseorder=>ok_code.

     WHEN ‘BACK’.

       CALL METHOD o_grid1->check_changed_data.

       IF o_purchaseorder->lt_ekko_tmp NE o_purchaseorder->lt_ekko.

         CALL METHOD o_purchaseorder->back.

       ELSE.

         LEAVE TO SCREEN 0.

       ENDIF.

     WHEN ‘EXIT’ OR ‘CANCEL’.

       CALL METHOD o_grid1->check_changed_data.

       IF o_purchaseorder->lt_ekko_tmp NE o_purchaseorder->lt_ekko.

         CALL METHOD o_purchaseorder->exit.

       ELSE.

         LEAVE PROGRAM.

       ENDIF.

     WHEN ‘SAVE’.

       CALL METHOD o_grid1->check_changed_data.

       IF o_purchaseorder->lt_ekko_tmp NE o_purchaseorder->lt_ekko.

         CALL METHOD o_purchaseorder->save.

       ELSE.

         MESSAGE s000(8i) WITH text012 DISPLAY LIKE ‘E’.

       ENDIF.

   ENDCASE.

ENDMODULE.                 ” USER_COMMAND_9000  INPUT

*&———————————————————————*

*&      Module  USER_COMMAND_9001  INPUT

*&———————————————————————*

*       text

*———————————————————————-*

MODULE user_command_9001 INPUT.

   CASE cl_purchaseorder=>ok_code.

     WHEN ‘BACK’.

       LEAVE TO SCREEN 0.

     WHEN ‘EXIT’ OR ‘CANCEL’.

       CALL METHOD o_grid2->check_changed_data.

       IF o_purchaseorder->lt_ekko_tmp NE o_purchaseorder->lt_ekko.

         CALL METHOD o_purchaseorder->exit.

       ELSE.

         LEAVE PROGRAM.

       ENDIF.

   ENDCASE.

ENDMODULE.                 ” USER_COMMAND_9001  INPUT

To report this post you need to login first.

25 Comments

You must be Logged on to comment or reply to a post.

  1. Venkatramanan Gowrishankar

    Hello Yaseen,

    It is always challenging to adopt OO design for reports. People have their own styles , each with their own pro’s and con’s. However, in the above design, I see major issues.

    1. The Inheritance is semantically wrong. The model (CL_HEADER) should not be inheriting ALV display classes. The model’s job is to prepare the data for the report. There should be a layer above it ( a controller for all screen’s ) , whose job is to determine the output technique- this leads to my second question. This is a violation of seggregation of Duties.

    2. If i want to add a feature to the report, where i dont want to see the data in an ALV , but downloaded to a file , then the above design would not work. – You are inherting an ALV implementation, you cannot inherit a file implementation – which shows why you need a layer above the model and why SOD is so critical in desiging classes.

    3, Semantically – there should be a single ‘PO’ class. “A ‘PO’ class contains  an header and one or more items’ and there would be a collection of PO’s .

    4. There are other issues too,  for example:If i would like to adapt this report to a Web dynpro display would it work?, as there is an inheritance to a SAP GUI object…but then lets leave these aside.

    If at all we were design our reports like these, then the development time increases exponentially, but this would lead to a lot of code reusability; thats why it is tough but not impossible to adopt OO design for reports.

    I understand, its easy to write my comments here, My intentions are not to criticize your post 🙂 . Please feel free to correct me if I am assuming/missing anything.

    Thanks,

    Venkat.

    (0) 
    1. Thomas Zloch

      Critical yet constructive comments are always welcome, please keep them coming. This is much more valuable than just posting “good one”, for example.

      Thomas

      (0) 
    2. Yaseen AbdulRahiman Post author

      Hi Venkat,

      I agree with the segragation of duties part as I had designed this program just for alv display and not for any other purpose.

      I should have declared the objects for alv outside the class or a controller class which decides the mode of output like you have mentioned. I was asked to make all declarations inside the class in my assignment. I am happy that if I hadn’t posted this blog I wouldn’t have known this.

      Sorry for the late reply as I am busy in a project for enhancement of SAP MIM app in Java webdynpro 🙂

      BR,

      Yaz

      (0) 
  2. Jelena Perfiljeva

    Yaseen, I am sorry but I felt this example somehow missed the point you made in the first paragraph. It just looks like “OO for the sake of OO”. Might as well replace the methods with routines. OO advantages are just not very clear in this example.

    I was also surprised to see that some obvious reusability opportunities were missed.

    1. Since in SELECT statements only WHERE condition is different, I’d rather build it as a string and then use WHERE ( where_string ). Otherwise if someone would need to add one more field to this report, they’d have to change 3 SELECTs.

    2. Field catalog – copy-pasting kind of defeats the OO purpose. Maybe it’d be better to define the ALV structure in dictionary and just call a good old FM (or perhaps there is a method for that as well) to build the field catalog.

    Also there are no fields ‘description’ and ‘procstat’ in EKKO table, so I’m not sure how this could pass the syntax check. If this was not intended as a working code then it should’ve been noted (sorry if I missed the disclaimer).

    Maybe a different example would better illustrate what you were trying to say. It would be interesting to read how OO could be used to make the code more adaptable (e.g. for different output, as Venkat pointed out).

    Thank you.

    (0) 
    1. Yaseen AbdulRahiman Post author

      Dear jelena,

      1. Can you please explain on how this is done?

      2. Creating a Dictionary structure was not allowed and I had to add attributes like hotspot etc. to each field and thats why I used for it. If there is an FM or method to do this then please let me know.

      3. Both procstat and description fields are available in my ekko table and this is a working code.

      Thank you for your inputs 🙂

      BR,

      Yaz

      (0) 
      1. Jelena Perfiljeva

        Yaseen AbdulRahiman wrote:

        1. Can you please explain on how this is done?

        It’s already explained in ABAP Help. Hit F1 on WHERE.

        Yaseen AbdulRahiman wrote:

        3. Both procstat and description fields are available in my ekko table and this is a working code.

        These fields are not part of the standard table. I’m sure you’ll find that they were added (in an APPEND structure most likely) as customizing in your system.

        If I may suggest, check out the blog by Paul Hardy. It hardly has any code, but as far as exploring “the art of OO” 🙂 it has much more to offer, I think.

        (0) 
        1. Yaseen AbdulRahiman Post author

          LOL! I know what is explained when you hit F1 in where. You mentioned that you will pass it as a string and then use where in ABAP F1 help it says “Except for columns of type STRING or RAWSTRING, all columns of the database tables or views listed after FROM can be evaluated after the WHERE condition”.

          In my program, in two selects I am equating a value with procstat while in the other select I am using where procstat is NOT IN 2 values. I don’t think that this is possible by passing it to a string like you said.

          Although there is an alternate solution for this. I could build a range table for procstat and use if condition and pass the values accordingly but for the last condition I will need to pass all the other values except for 05 and 06 which will make the code longer than the present one.

          In the present code even though I am using select 3 times but select or database is hit only once if a condition is satisfied.

          I am using IDES and the INCLUDE or APPEND is made by SAP itself. In my question Procstat and Description fields are both needed and hence I used it.

          I agree that Venkat had a valid point but I feel other are criticizing for the sake of criticizing.

          (0) 
          1. Suhas Saha

            Hello Yaseen,

            As Thomas Zloch has mentioned it’s good to have positive comments.

            In the present code even though I am using select 3 times but select or database is hit only once if a condition is satisfied.

            If you say you’re thinking OO then your code does not fit the bill. The application does not have the flexibility – if there is any change in the business requirement, then you’ll have to change the code to incorporate a new IF clause. Have you heard about the “open-closed” principle in OO(rather software) design? Do you think your code satisfies this condition?

            That’s why i had said earlier your code is an effort to “use OO” and not “think OO”. I hope this clears the air.

            BR,

            Suhas

            (0) 
          2. Jelena Perfiljeva

            Yaseen AbdulRahiman wrote:

            In my program, in two selects I am equating a value with procstat while in the other select I am using where procstat is NOT IN 2 values. I don’t think that this is possible by passing it to a string like you said.

            Please check ABAP Help again under ‘ WHERE – (cond_syntax) ‘. There is a very clear example given there.

            (0) 
  3. Suhas Saha

    Let me be honest – i started coding in OO-ABAP merely by replacing the sub-routines in my program with local class methods 🙂

    Venkat & Jelena have already highlighted the flaws in your design. Imho your code seems more like an effort to “replace subroutines with local methods”.

    Thinking OO is more of an art & there is no prescribed way of designing your OO application. Even the fabled OO design patterns are more of a guideline to good object orientation.

    BR,

    Suhas

    (0) 
    1. Venkatramanan Gowrishankar

      Hi Suhas,

      Thinking OO is more of an art & there is no prescribed way of designing your OO application. Even the fabled OO design patterns are more of a guideline to good object orientation.

      Thats absolutely true, there is a serious debate on whether we are forced to think of design patterns that are already proven, when there might be a “Custom” design pattern , never before tried or tested which might be better for a solution.

      Thanks,

      Venkat.

      (0) 
      1. Suhas Saha

        Hi Venkat,

        Venkat Gowrishankar wrote:

        Thats absolutely true, there is a serious debate on whether we are forced to think of design patterns that are already proven, when there might be a “Custom” design pattern , never before tried or tested which might be better for a solution.

        Imo “Custom” (read:new) designs do not qualify to be DPs unless they have proven their worth in similar use-cases. 🙂

        Actually in OO there is no “on size fits all” solution, watsay?

        BR,

        Suhas

        (0) 
  4. Nigel James

    I found your code unreadable. There are provisions in the platform here on SCN to present your code nicely but you have used screen shots which are

    1. hard to read
    2. cant be copies by people wanting to try what you have suggested

    Keep blogging and keep in mind the points that other people have made.

    OO is a great way to think.

    Cheers,
    Nigel

    (0) 
    1. Venkatramanan Gowrishankar

      Hello Yaseen,

      To be honest, I personally feel I am not experienced enough ( 5 yrs)  to “review” . 🙂

      Since you asked for it, here is my feedback.

      1. The ALV grid classes are now outside the model class, which is fine.

      2. The segregation of duties is still missing. I could see that the class CL_PURCHASEORDER creates an ALV  grid object. Now, What is the role of the class CL_PURCHASEORDER?, Is it for fetching the data only? or is it Used for output of  the data?. If the answer is Both, then  I would think that the class is over burdened with the additional responsibility of creating output objects. I could see you have used interfaces,I will come to that later.

      Why is this class overburdened?, Now,If  I develop a Web dynpro appl, which displays the same data, It would make sense to use the class CL_PURCHASEORDER for fetching the data, I would be interested only in the Method SELECT_PO, as the display is taken care of by the ALV Component or the View controller of the WD applicaion. It is not a serious crme , but  creating a grid from the Model does not fit in the overall application.  Creation of the Grid objects as you would normally do in the Program/Report , should be fine.

      3. I believe the interfaces do not play any role. Interfaces are used to provide a common Access model for objects that may not be similar in classification by unfifying them with  a common behavior pattern. Hence the Usage of the interface in the above program is not justified. Interfaces  are a powerful technique ( In fact, the perfect) in implementing Encapsulation. .The controller is a separate class, not an Interface, hence the interface can be removed 

      4.Handling of function codes by the Model,  is a very touchy topic and hence I shall refrain from discussing it, but always keep in mind , how the model would react in an environment outside of SAP GUI.The same debate  applies to  popup’s too.

      Without the grid creation and the Interface, I guess your program is good to go from a Class design perspective.

      As always, please feel free to correct me 🙂 .

      WIshing you a succesful New year ! 🙂

      Thanks,

      Venkat.

      (0) 
      1. Suhas Saha

        Hence the Usage of the interface in the above program is not justified. Interfaces  are a powerful technique ( In fact, the perfect) in implementing Encapsulation.

        Venkatramanan Gowrishankar – “Encapsulation” 😕 I would have agreed more if you had mentioned “in implementing polymorphism” (or “inheritance”).

        Edit after a lil’ bit of introspection: Of course i/f’s provide a common public access to classes with similar behavior. I hope this is why you had mentioned “implementing encapsulation” – sorry for the confusion 😛

        Yaseen AbdulRahiman – In fact your code is more than ready to be used as a stand-alone report program and not as a full-fledged custom application.

        Reason: Your SELECT_PO( ) is tightly coupled to the selection-screen radio-buttons. Any additional radio-button will mean that you’ll have to change the application class coding => low maintainability.

        One of the projects i had worked on had a very strict policy regarding – “one class, one responsibility”. For e.g., we never had a PO class displaying an ALV 🙂 Tbh I never really liked the idea at that time & thought it was just another fancy term coined by the architect. But during the course of the project i started to appreciate this approach & i try to use it in my design now-a-days.

        I use the above example to highlight the fact that “thinking OO” does not come overnight. It took me a few years of hands-on experience & guidance by the SDN OO gurus – Marcin Pciak , Matthew Billingham , Uwe Schieferstein – to finally appreciate OO.

        Cheers,

        Suhas

        (0) 
        1. Venkatramanan Gowrishankar

          Hello Suhas,

          Encapsulation” 😕 I would have agreed mores e if you had mentioned “in implementing polymorphism” (or “inheritance”).

          Yes no doubts, it is used for Polymorphism, I should haved added ” and Polymorphism” 🙂 , an absolute bummer, How did  I miss that 😛 .

          But in the above example, If i were to talk polymorphism , then it would only make it complicated and totally out of scope, hence I guess that’s why  I refrained from using it.

          Regarding Encapsulation,   here is  Grady booch’s take, who as we know is one of the (or the) definitive authors of OO;  on ecapsulation .(Excerpt from Wikipedia).

          Grady Booch defined encapsulation as “the process of compartmentalizing the elements of an abstraction that constitute its structure and behavior; encapsulation serves to separate the contractual interface of an abstraction and its implementation.”

          I guess , this( Contractual interface) clears what I wanted to convey 🙂 .

          Nevertheless,  its always the class’s responsbility to Implement   Encapsulation properly. As you Already know and conveyed, When an object is accessed by its interface type, A client would only be  access the object’s public methods via the Interface and hence details/attributes of the actual class are hidden.

          I use the above example to highlight the fact that “thinking OO” does not come overnight.

          No doubts . I completely agree with you 🙂 .

          Thanks,

          Venkat

          (0) 
    2. Thomas Zloch

      As for calling me, I’m not that much of an OO buff (working on it since years…), so my role is limited to encourage constructive commenting.

      I enjoy reading the comments by our knowledgeable contributors, as much as Kumar Mayuresh seems to be convinced by each of yours.

      Thomas

      (0) 
  5. Naimesh Patel

    Hello Yaseen,

    I would congratulate you to start thinking of using OO ABAP. As many developers are not using that. But you are missing lot of basic points here.

    • Use of Select Options directly within the methods to select the data – Think like you are developing a Global class. Will you be able to use the selection screen parameters from you program to the class? NO, you wont be able to.

    What you should do is – Create a class for “SELECTION”. Create all the parameters and ranges (for select-options) in this class. Make this class as an attribute to your main selection class. Instantiate the object, set the parameters, ranges from the selection screen to this class.

    This way you would be easily able to detach your logic away from your program. Think of creating another program based on this class hierarchy again or a WebDynpro application.

    • View should be part of the controller – Controller should decide which view should be used. You have ALV related logic directly embedded in your main class. This would make pretty difficult to reuse if required.
    • When Designing a class always think of the scenario that someone will be using the class that in future to satisfy their requirement. If your class structure is complicated, I would hesitate to use it in future.

    You should concentrate on integrating OO Design patterns & OO Design Principles in your OO Development.

    Always try to use as much as patterns you can use, even though its small development.

    Also try to avoid CALL METHOD statement. Instead of that, use “Functional writing Style”. Like O_GRID->DISPLAY( ).

    Regards,
    Naimesh Patel

    (0) 
  6. Alejandro Bindi

    Very interesting blog and discussion.

    I tend to agree with the criticized points, having had a quick overview of the code.

    But personally, after a few years I came to the conclusion that using real OO for the standard report (standard meaning: read a few tables => build output structure => display ALV) is just overkill in terms of design. Yet there are many benefits in using the OO syntax alone (optional parameters and event handling, to name a few).

    In those cases I found it simpler to just use local classes with static methods (yes, the “procedural” approach), instead of using “OO for the sake of OO”, which of course doesn’t mean that this kind of report can’t instantiate and reuse some class already present globally in the system. The key thing is to always keep in mind that the local class can easily be converted to global, so that the simple data retrieval model can be reused (eg. in a Web dynpro report). The direct use of select-options / parameters inside data retrieval methods should be avoided for this reason, as mentioned by Naimesh. The fact that local classes allow global access to the whole program which contains them should not be abused (always think “how would I reuse this in a different context”, and keep model/business logic and user interface concepts separated as far as possible).

    OO works great in more complex scenarios, you really see the benefit when you find you can reuse complex logic which exists in correctly designed classes with little to no effort. After you go through that experience, it’s easier to design such classes yourself.

    My two cents

    (0) 

Leave a Reply