0
votes

I'm currently working on a rather complex ABAP application that is going to be split into several modules each performing a specific part of the job:

  • one for gathering some data from multiple sources;
  • one for displaying that data in UI (SALV grid, if that matters);
  • one for doing some business things based on that data.

According to my plan each module will be a global class. However, there is some logic that may need to be shared between these classes: helper subroutines, DB access logic and so on. All of this is a set of local classes at the moment.

I know could these classes global as well, but this would mean exposing them (as well as a number of internal data structures) to the public which I would not like to. Another approach would be sharing the includes with them between my global classes, but that is said to be a bad design.

So, my question is: how do real ABAPers solve problems like this?

4
Especially DB access logic sound like the need of another helper class. Maybe you could create a master class and inherit the subroutines from this master class (but it may be also a very bad idea - depends on your real code). - knut
I do have helper classes for that. My concern is to find a way to share them between the application modules without making them global (i.e. public). - Alex Kiselev

4 Answers

1
votes

Here is an example of how one can access a local class defined in a report.

The report with the class.

REPORT ZZZ_PJ1.

CLASS lcl_test DEFINITION FINAL.
  PUBLIC SECTION.
    METHODS:
      test.
ENDCLASS.

CLASS lcl_test IMPLEMENTATION.
  METHOD test.
    WRITE 'test'.
  ENDMETHOD.
ENDCLASS.

The report which uses the class.

REPORT ZZZ_PJ2.

CLASS lcl_main DEFINITION FINAL CREATE PRIVATE.
  PUBLIC SECTION.
    CLASS-METHODS:
      main.
ENDCLASS.

CLASS lcl_main IMPLEMENTATION.
  METHOD main.
    DATA:
      lr_object TYPE REF TO object.

    CREATE OBJECT lr_object
      TYPE ('\PROGRAM=ZZZ_PJ1\CLASS=LCL_TEST')

    CALL METHOD lr_object->('TEST').
  ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
  lcl_main=>main( ).

Of course this is not a clever solution as each method call would have to be a dynamic call.

CALL METHOD lr_object->('TEST').

This could be solved however by using global interfaces that would define the methods of your classes (of course if they are not static which I assume they are not). Then you have to control each of the instances through the interface. Your target would be fulfilled then, as only the interface would be exposed globally, the implementations would remain in local classes.

0
votes

You may want to do some reading on Model-View-Controller design patterns. Displaying data in a UI - would be a "view". Both the gathering and updating of data would be incorporated into a "Model" . Business logic should likely be implemented as an interaction between the view and the model in a "Controller".

That said, one approach to this is would be to utilize the friendship feature offered in ABAP OO.

As an example: create the model and view classes globally but only allow them to be instantiated privately, then grant private component access to the controller. Class definitions would be follows:

CLASS zcl_example_view DEFINITION
  PUBLIC
  FINAL
  CREATE PRIVATE
  GLOBAL FRIENDS zcl_example_controller


CLASS zcl_example_model DEFINITION
  PUBLIC
  FINAL
  CREATE PRIVATE
  GLOBAL FRIENDS zcl_example_controller


CLASS zcl_example_controller DEFINITION
  PUBLIC
  FINAL
  CREATE PUBLIC

Additionally it may be a good idea to make the controller singleton and store a reference to it in both the view and the model. By enforcing that the controller IS BOUND when the view and model are instantiated we can effectively ensure that these three classes exist as only you desire.

0
votes

Stepping back to your initial problem: I sounds to me like you're already using something like a MVC pattern in your development so your only problem is that some routines shall be used publicly by both models, views and controllers.

In this case I strongly recommend to put these routines in global available classes or to implement getter methods in your already existing classes to access those functionality.

Any hacks like \PROGRAM=ZZZ_PJ1\CLASS=LCL_TEST are sometimes essential but not here imho.

-2
votes

If your application is as large as you make it sound, you should organize it using multiple packages. You will certainly have to deal with non-OO stuff like function modules, data dictionary objects and other things that can not be part of a class, so using classes as the basic means to organize your application won't work outside of very small and specialized applications.

Furthermore, it sounds like you have some really severe flaws embedded in your plan if you think that "DB access logic" is something that should be "shared between classes". It is hard to guess without further information, but I would strongly suggest that you enlist someone who has experience in designing and implementing applications of that scale - at least to get the basic concept right.