Thursday, November 3, 2022

Looping & Performance in ABAP - Work Area, Field Symbol or Data Reference

Let's consider following test scenarios:


1. Changing the number of rows and looping over an internal table of type BSEG​

The graph represents the avarage performance of 1000 runs​


2. Changing the number of fields in an internal table of 1000 rows​

The graph represents the avarage performance of 1000 runs​




Conclusions:

  • Field-symbols are slightly faster than reference variables​
  • The larger the internal table, the more it matters  how you loop​
  • In smaller internal tables you can use reference into, in order to achieve more object-oriented-like code​
  • The winner in terms of performance - field symbols




Design Patterns in ABAP - The Singleton Factory

Design Patterns provide reusable solutions for common problems. So why to solve a problem twice?

Singleton and factory are among the most widely used software patterns. This post demonstrates a combination both - the singleton factory.


Problem: Creating the same object and retrieving the same data objects multiple times throughout a session results in a huge performance issue.

 

Solution: Store the Object Instances in a static class and address them by key when needed. In terms of Design Patterns - a Singleton Factory 

 

Background: Design Patterns - Singleton and Factory 


  • Singleton 

The Singleton is a creational design pattern that makes sure that only one instance of a class is running at a time.  

The client does not even realise that they are working with the same instance all the time. 


  • Factory 

The Factory is a creational design pattern and provides an interface for creating objects. 


Goal: Use the Singleton instance as a data store for objects created through the factory method 


Let's move to ABAP and get more specific.


Problem: Too many duplicate objects of type ZCL_CATS_INTERNAL_ORDER are being created which results in poor performance. 


Solution:  ZCL_CATS_INTERNAL_ORDER_STORE  should be implemented as a singleton-factory in order to keep the data and make sure no duplicates are created.


- Singleton Implementation

In order to impose the singleton behaviour, we need to make sure that the class is defined with:


- private instantiation (private construcor)

- static attribute as a reference to an object of the very same class

- static method to provide access to the sole instance of the class



In our case there is no constructor method, because nothing is happening at the moment of the class creation. In another scenario, for example it would make sence to read and store some customizing data.








The method get_object (often also called  get_instance or instantiate) serves as an access point to the object. 




- Factory Method Implementation

The factory method returns an object of type ZCL_CATS_INTERNAL_ORDER.
If the object is in the store, it is taken from the store, if not it will be created and stored. 
Typically, the factory returns an object of an interface type. The class type itself is defined by the factory.





Used Links:

http://zevolving.com/2012/02/abap-objects-design-patterns-singleton-factory/

The Catalog of Design Patterns (refactoring.guru)

 




Tuesday, March 8, 2022

CDS Views: Performant Status Query using the JEST Table

 The application and the system status in SAP play a very big role in many reports, search helps and evaluations. 

The conventional approach to retrieve the JEST status is to use the dedicated function module STATUS_READ or STATUS_READ_MULTI from the function group BSVA.

If you need the application or the user status just in order to exclude certain objects from a result list or a search help, it is more comfortable to use dictionary objects, such as CDS Views.

In this post I am going to demonstrate how to classify QM notifications into a group of valid and invalid. The invalid notifications include the status values 'completed' and 'cancelled' and have to be filtered out. All the other notifications are valid and have to be shown.

This can be achieved with the help of two CDS Views. 

The main CDS View contains the join with the JEST Table and casts priorities to the status values in the where clause. It is split into two, because we want to have a 'valid' or 'invalid' for every notification.


Here goes the code for the first CDS View:

@AbapCatalog.sqlViewName: 'zcds_notif_main'
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Main View JEST, QMEL'
define view Z_CDS_NOTIF_MAIN as select distinct from qmel as notif
association [1] to jest as _jest on notif.objnr = _jest.objnr{
    _jest.objnr,
    _jest.stat,
    notif.qmnum,
    cast('invalid' as abap.char( 10 )) as status,
    cast('5' as abap.int1) as prio
} where _jest.stat = 'E0016' and  _jest.stat like 'E%' and _jest.inact = ''
// or _jest.stat = 'E0012' //completed or cancelled, maybe join with table tj30, this is just a demo!
union select distinct from qmel as notif
association [1] to jest as _jest on notif.objnr = _jest.objnr{
    _jest.objnr,
    _jest.stat,
    notif.qmnum,
    cast(' valid' as abap.char( 10 )) as status,
    cast('4' as abap.int1) as prio
} where _jest.stat != 'E0016' and  _jest.stat like 'E%' and _jest.inact = ''
//and _jest.stat != 'E0012'

The second CDS View accumulates the values of the first view, here we have one entry per QM notification, according to priority.

Here goes the code for the second CDS View:

@AbapCatalog.sqlViewName: 'ZDS_NOTIF_STATUS'
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'QMEL mit Status'
define view Z_CDS_NOTIF_STATUS as select from qmel  as NOTIF inner join zcds_notif_main as MAIN
on NOTIF.qmnum = MAIN.qmnum {
 key   NOTIF.qmnum,
 max(MAIN.status) as status,
 max(prio) as stat
} group by NOTIF.qmnum

You could create an auxiliary view on the JEST Table, using only the relevant status schema. Another improvement would be to push the 'valid / invalid' logics to a customizng table.

Have fun while trying, adjustung and improving the approach!