styleguides
styleguides copied to clipboard
Singleton vs static class
In the guidelines there is only a small passage about singleton and there are no scenarios given where it should and shouldn't be used. Maybe to extend this section?
Consider the use-case: I want to reuse some data (itab) and save it to global class attribute, this class is called by RFC module. The data is big and is the result of complex calculations on BOMs and financial tables, and I don't want to recalc them with each RFC call, I want to reuse them. What should I use for persistence: static or instance class with singleton?
In static/singleton ABAPDOCU section they say:
A global static class is loaded once with its class pool into the current internal session. Like every ABAP program, it cannot be explicitly deleted from the session
so it seems the best fit for my case. Maybe I am missing something about singletons?
If a class is being called by RFC then it will be a new session and static data will not be relevant.
I agree with the guidelines, singletons are not entirely dissimilar to global variables and should be used with care. Static classes are also something that should in theory be limited to the most basic utility functions. The third option is to use static data, which is what I would do.
CLASS zcaching_calculator DEFINITION.
PUBLIC SECTION.
METHODS get_data.
PRIVATE SECTION.
CLASS-DATA calculated_stuff.
ENDCLASS.
CLASS zcaching_calculator IMPLEMENTATION
METHOD get_calculated_stuff.
IF calculated_stuff IS INITIAL.
"go and get / calculate it
ENDIF.
ENDMETHOD.
ENDCLASS.
Another option which will work in RFC is shared memory objects, but that's a completely different animal.
The ABAP docu itself recommends to prefer singletons to static classes, and Clean ABAP agrees with this. The reason is less the way they store data, more how you consume them. With a static class, the consuming class will call a static method that cannot be replaced and mocked:
METHOD do_something.
DATA(result) = some_static_class=>calculate_it( ).
ENDMETHOD.
Such a hard dependency can be acceptable, esp. if the method is stateless and fast. In most cases however, it is unwelcome, and the consumer would like to decouple from the instance. The singleton pattern enables this, as the consumer depends only on the interface and is able to supply other implementations, esp. mocks for unit tests.
CLASS my_class DEFINITION
"...
DATA some_dependency TYPE REF TO some_interface.
METHOD do_something.
DATA(result) = some_dependency->calculate_it( ).
ENDMETHOD.
If a class is being called by RFC then it will be a new session and static data will not be relevant
the problem is that my tests showed that RFC calls reuse the same connection, at least in Jco implementation like described here https://stackoverflow.com/a/57235435/911419
When I make frequent calls I see that the user session and internal sessions are reused, so static data can perfectly be used in RFC.
Another option which will work in RFC is shared memory objects, but that's a completely different animal.
this has another problem. We have 16 application servers in the system, and we never know which instance will accept RFC call, and shared memory applied only to one server, so this scenario seems inapplicable to it.
So from your posts, guys, I got that singleton is recommended in my case, correct? And what about static variables directly in RFC function group? Is it already obsolete approach?