Monday, 13 April 2020

Constants management

In every system i work i usually have a table for constants management, some tables are designed for single values, some tables to accept ranges too, but generally each table i found for constants management have some limitations.

I’m actually using a solution that give me enough freedom to accomodate any kind of constant i need and i’ve been built a class to work with the table in a way i feel comfortable, i’m going to share some code to work with single values and SAP ranges, but the class is expandable and the table fields can hold anything you need, while reading i recommend you to see the code in the github repository at the end of the post, without full source code it may be hard to follow the explanation.

I usually find tables with a single field or with fields for SIGN, OPTION, LOW and HIGH to let you define range constants too, but the table field to hold the values usually is defined with a length, this can be a limitation if you have to write a very long constant, the fields i defined for my constant table are:

SAP ABAP Development, SAP ABAP Guides, SAP ABAP Learning, SAP ABAP Certifications, SAP ABAP Prep

The value will be a string, and i defined just a single field, because to have the flexibility i’m looking for i will be writing the constants in an XML format sometimes, for example in the case i want to write a SAP range. This xml will be generated and processed by a class that will have the purpose of ease the developer work.

The public interface of my class will have two main methods:

◉ READ_CONSTANT – For reading a constant i will need just one input parameter the constant name (PI_NAME) and the main output parameter will be PE_VALUE defined as type ANY.

◉ WRITE_CONSTANT – For writing a constant i will need four input parameters, the contant name (PI_NAME), the constant group (PI_GROUP), which only purpose is organizative, i will also need the type of constant i want to write (PI_TYPE), for this post i will work with two types, single field or SAP range, and finally i will need a variable with the value i must write to constants table (PI_VALUE).

Inside the READ_CONSTANT and WRITE_CONSTANT i will organize the code in separate methods for each type of constant, this methods will be private, for this post i will have:

◉ HELPER_READ_CONST_FIELD
◉ HELPER_WRITE_CONST_FIELD
◉ HELPER_READ_CONST_SAP_RANGE
◉ HELPER_WRITE_CONST_SAP_RANGE

It means that you can add new types and code for your new types, this makes the constant manager expandable and when combined with XML string that means that you would could save anything you need. You can use JSON if you feel more confortable or any kind of custom format you want, you just have to code a READ and WRITE method that know how to save and retrieve it back to a variable of the correct type.

You will notice the class have a CONFIGURE_CONSTANT method too, the purpose of this method is to show some kind of UI that allow the developer to configure it in a comfortable way, i didn’t found yet a way that fully satisfy me when configuring SAP ranges this is why, for now, CONFIGURE_CONSTANT will have just a private method for single fields, but in the examples below i will show how i work with range constants to make my life as easy as possible.

For details of implementation you can go to github repository, let’s now explain how i use this when coding a program, i’m going to explain first how i work with single field constants, in the github repository you have the program ZTOOLS_CM_R001 which code is:

*&---------------------------------------------------------------------*
*& Report ZTOOLS_CM_R001
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT ZTOOLS_CM_R001.

TABLES: sscrfields.

CONSTANTS: c_const_group TYPE ztools_const_group VALUE 'ZTOOLS_CM_R001',
           c_const_name TYPE ztools_const_name VALUE 'TEST_FIELD_CONSTANT'.

DATA: d_developer TYPE abap_bool.

PARAMETERS: p_value TYPE i.
SELECTION-SCREEN FUNCTION KEY 1.

INITIALIZATION.
  PERFORM initialization.
AT SELECTION-SCREEN.
  PERFORM at_selection_screen.
START-OF-SELECTION.
  PERFORM start_of_selection.
*&---------------------------------------------------------------------*
*& Form INITIALIZATION
*&---------------------------------------------------------------------*
FORM initialization .
* Determine if the user is a developer, constant configuration buttons
* will be shown only for developers.
* For testing purposes all users are devs.
  d_developer = abap_true.

  IF d_developer = abap_true.
    CONCATENATE icon_configuration 'Config. test constant'
    INTO sscrfields-functxt_01.
  ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  AT_SELECTION_SCREEN
*&---------------------------------------------------------------------*
FORM at_selection_screen .
  CASE sy-ucomm.
    WHEN 'FC01'.
      PERFORM configure_test_constant.
  ENDCASE.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form CONFIGURE_TEST_CONSTANT
*&---------------------------------------------------------------------*
FORM configure_test_constant .
  DATA: l_subrc TYPE sysubrc,

        lwa_accepts_creation TYPE ztools_constants_manager=>t_accepts_creation.

  lwa_accepts_creation-group = c_const_group.
  lwa_accepts_creation-type = ztools_constants_manager=>e_constant_types-field.

  CALL METHOD ztools_constants_manager=>configure_constant
    EXPORTING
      pi_name             = c_const_name
      pi_accepts_creation = lwa_accepts_creation
    IMPORTING
      pe_subrc            = l_subrc.

  IF l_subrc = 0.
    MESSAGE 'Constant updated.' TYPE 'S'.
  ELSE.
    MESSAGE 'Constant not updated.' TYPE 'W'.
  ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form START_OF_SELECTION
*&---------------------------------------------------------------------*
FORM start_of_selection .
  DATA: l_value TYPE i,
        l_total TYPE i.

  CALL METHOD ztools_constants_manager=>read_constant
    EXPORTING
      pi_name  = c_const_name
    IMPORTING
      pe_value = l_value.

  l_total = l_value + p_value.

  WRITE: / 'Constant value =', l_value.
  WRITE: / 'Sum =', l_total.
ENDFORM.

I develop the programs but many times constants value are decided by another team, this team are not developers, i want to make the life of the person who are going to configure them as easy as possible no matter if it’s me or another team. This is why this sample program has a function key in selection screen, this function key must not be shown for final users, but i found it comfortable to visually have an option to configure constants involved in the program, if another developer is working in the program it easily will know which constants are and it would be easy to visualize or change the value.

The function key code is just a call to CONFIGURE_METHOD for the constant i want to configure and the result is:

SAP ABAP Development, SAP ABAP Guides, SAP ABAP Learning, SAP ABAP Certifications, SAP ABAP Prep

But as explained before i didn’t build a CONFIGURE_METHOD for SAP ranges which are by far more difficult to directly define in database table as they are an XML document. To solve this problem i usually build a selection screen, i coded a sample program ZTOOLS_CM_R002 you can find in github which source code is:

*&---------------------------------------------------------------------*
*& Report ZTOOLS_CM_R002
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT ZTOOLS_CM_R002.

TABLES: sscrfields.

CONSTANTS: c_const_group TYPE ztools_const_group VALUE 'ZTOOLS_CM_R002',
           c_const_name TYPE ztools_const_name VALUE 'TEST_SAP_RANGE_CONSTANT'.

DATA: d_developer TYPE abap_bool.

PARAMETERS: p_value TYPE i.
SELECTION-SCREEN FUNCTION KEY 1.

SELECTION-SCREEN: BEGIN OF SCREEN 9001.
  SELECT-OPTIONS: s_valran FOR p_value.
SELECTION-SCREEN: END OF SCREEN 9001.

INITIALIZATION.
  PERFORM initialization.
AT SELECTION-SCREEN.
  PERFORM at_selection_screen.
START-OF-SELECTION.
  PERFORM start_of_selection.
*&---------------------------------------------------------------------*
*& Form INITIALIZATION
*&---------------------------------------------------------------------*
FORM initialization .
* Determine if the user is a developer, constant configuration buttons
* will be shown only for developers.
* For testing purposes all users are devs.
  d_developer = abap_true.

  IF d_developer = abap_true.
    CONCATENATE icon_configuration 'Config. test constant'
    INTO sscrfields-functxt_01.
  ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  AT_SELECTION_SCREEN
*&---------------------------------------------------------------------*
FORM at_selection_screen .
  CASE sy-ucomm.
    WHEN 'FC01'.
      PERFORM configure_test_constant.
  ENDCASE.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form CONFIGURE_TEST_CONSTANT
*&---------------------------------------------------------------------*
FORM configure_test_constant .
  CALL METHOD ztools_constants_manager=>read_constant
    EXPORTING
      pi_name  = c_const_name
    IMPORTING
      pe_value = s_valran[].

  CALL SELECTION-SCREEN 9001 STARTING AT 10 10 ENDING AT 100 11.

  IF sy-subrc = 0.
    CALL METHOD ztools_constants_manager=>write_constant
      EXPORTING
        pi_name  = c_const_name
        pi_group = c_const_group
        pi_type  = ztools_constants_manager=>e_constant_types-sap_range
        pi_value = s_valran[].

    MESSAGE 'Constant updated.' TYPE 'S'.
  ELSE.
    MESSAGE 'Constant not updated.' TYPE 'W'.
  ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form START_OF_SELECTION
*&---------------------------------------------------------------------*
FORM start_of_selection .
  DATA: li_value_range TYPE RANGE OF i.

  CALL METHOD ztools_constants_manager=>read_constant
    EXPORTING
      pi_name  = c_const_name
    IMPORTING
      pe_value = li_value_range.

  IF p_value IN li_value_range.
    WRITE: / 'The value is inside the range'.
  ELSE.
    WRITE: / 'The value is not inside the range'.
  ENDIF.
ENDFORM.

I have a function key for configure the SAP range, but as i don’t have a CONFIGURE_METHOD that works with ranges in the function key code i call a selection screen, before to display the selection screen i read the constant i will be configuring and i’m passing the current value of the constant to screen range variable, if the selection-screen is executed (SY-SUBRC = 0) then i will call the WRITE_CONSTANT method to save the selection screen range variable as constant in the database.

The resulting UI for configuring a range is:

SAP ABAP Development, SAP ABAP Guides, SAP ABAP Learning, SAP ABAP Certifications, SAP ABAP Prep

I hope you can find it useful if you have no constant management code in your project or if you have a worse solution to handle constants, every comment with ideas on how to improve the solution or potential problems this solution may have are welcome.

No comments:

Post a Comment