Excerpt from the book Design Patterns in ABAP Objects by Kerem Koseoglu. Used with permission of SAP PRESS. All rights reserved.

 

In this blog, see how the prototype design pattern is used for item cloning in an ABAP system.

Item Clone

In this example, we will work on an imaginary purchase requisition application where the user has to enter the vendor code (LIFNR), material number (MATNR), unit price (PREIS and WAERS), and quantity (MENGE and MEINS) into the GUI. We will want it to be possible to enter multiple line items.

Below demonstrates what the model class of such an application would roughly look like.

 

CLASS zcl_purchase DEFINITION

  PUBLIC FINAL CREATE PUBLIC.



  PUBLIC SECTION.

    “ Some type definitions



  METHODS add_line IMPORTING !is_line TYPE t_line.

  METHODS load_from_db IMPORTING !iv_docno TYPE zdocno.

  METHODS save_to_db.



  PRIVATE SECTION.

    “ Some hidden variables

    “ Some boring methods

  PROTECTED SECTION.

ENDCLASS.



CLASS zcl_purchase IMPLEMENTATION.



  METHOD add_line.

    APPEND VALUE #(

      obj_material = NEW zcl_material( is_line-matnr )

      lifnr = is_line-lifnr

      matnr = is_line-matnr

      price = VALUE #(

        preis = is_line-preis

        waers = is_line-waers )

      quan = VALUE #(

      menge = is_line-menge

      meins = is_line-meins )

    ) TO gt_line.

  ENDMETHOD.



  METHOD load_from_db.

    “ Some boring code containing SELECT, etc.

  ENDMETHOD.



  METHOD save_to_db.

    “ Some boring code containing MODIFY, etc.

  ENDMETHOD.



ENDCLASS.

So far, so good. As you see, GT_LINE is a nested internal table with five fields: one object (OBJ_MATERIAL); two variables (LIFNR, MATNR); and two work areas (PRICE, QUAN). At this point, we will assume that creating a new CL_MATERIAL has a high runtime cost, which means that CL_MATERIAL~CONSTRUCTOR contains costly code snippets that take quite some time to execute.

Below demonstrates what the CL_MATERIAL class looks like.

CLASS zcl_material DEFINITION

  PUBLIC FINAL CREATE PUBLIC.



  PUBLIC SECTION.

    “ Some type definitions

   

    METHODS constructor IMPORTING !iv_matnr TYPE matnr.

      “ Some further methods



  PRIVATE SECTION.

    “ Some hidden methods

  PROTECTED SECTION.

ENDCLASS.



CLASS zcl_material IMPLEMENTATION.



  METHOD constructor.

    “ Some very slow but unavoidable code

  ENDMETHOD.



  “ Some more methods

ENDCLASS.

If the user enters a new line item containing a brand new material, we must call ADD_LINE again. Thus, because we will be creating a new instance of CL_MATERIAL we will have to endure high runtime cost. On the other hand, what if the user enters a material number that he/she had entered before? Would we still create a brand new instance of CL_MATERIAL? With our current code, we would. So we must ask ourselves, “Is there a better way?”

Luckily there is! What we will do is clone an existing material object instead of creating a new one—the core logic of the prototype design pattern. Let’s look at the Unified Modeling Language (UML) diagram below to see what this should look like.

The UML diagram has only one extra method: CLONE. This method will do exactly what it says: clone the object. That’s the easy part; the relatively tricky part will transpire in CL_PURCHASE. Let’s start simple and see what CL_MATERIAL looks like below.

CLASS zcl_material DEFINITION

  PUBLIC FINAL CREATE PUBLIC.



  PUBLIC SECTION.

    “ Some type definitions



    METHODS constructor IMPORTING !iv_matnr TYPE matnr.

    METHODS clone RETURNING VALUE(ro_material) TYPE REF TO zcl_material.

    “ Some further methods



  PRIVATE SECTION.

    “ Some hidden methods

  PROTECTED SECTION.

ENDCLASS.



CLASS zcl_material IMPLEMENTATION.



  METHOD constructor.

    “ Some very slow but unavoidable code

  ENDMETHOD.



  METHOD clone.

    SYSTEM-CALL OBJMGR CLONE me TO ro_material.

  ENDMETHOD.

 

  “ Some more methods

ENDCLASS.

Normally, within the CLONE method, we would create the object RO_MATERIAL (avoiding the slow code in the constructor using flag variables and conditions) and copy the entire state of ME to RO_MATERIAL. However, we used a cheat code. What you see is a system call to clone ME, which is not meant for external use. No one gets hurt by little hacks like this, as long as the unit tests are done well.

Now, back to CL_PURCHASE. Instead of creating a new CL_MATERIAL object every time ADD_LINE is called, we will clone an existing material object whenever possible. The code to do so can be seen below.

METHOD add_line.

    DATA lo_material TYPE REF TO zcl_material.



    ASSIGN gt_line[ matnr = is_line-matnr ]

      TO FIELD-SYMBOL(<ls_line>).

    IF sy-subrc EQ 0.

      lo_material = <ls_line>-obj_material->clone( ).

    ELSE.

      lo_material = NEW zcl_material( is_line-matnr ).

  ENDIF.



  APPEND VALUE #(

    obj_material = lo_material

    lifnr = is_line-lifnr

    matnr = is_line-matnr

    price = VALUE #(

      preis = is_line-preis

      waers = is_line-waers )

    quan = VALUE #(

      menge = is_line-menge

      meins = is_line-meins )

    ) TO gt_line.

ENDMETHOD.

Brilliant, isn’t it? Instead of re-calling the constructor every time the same material is added, we simply cloned an existing object and avoided the initialization runtime cost.

Excerpt from the book Design Patterns in ABAP Objects by Kerem Koseoglu. Used with permission of SAP PRESS. All rights reserved

To report this post you need to login first.

7 Comments

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

    1. Suhas Saha

      Unfortunately i could not find the documentation in the online help, however in SAPGUI/ADT  i could find it.

      The documentation begins with the following warning:

      SYSTEM-CALL – ABAP-Schlüsselwortdokumentation

      This statement is intended solely for

      *** Internal use within SAP Basis Development ***

      Even within SAP Basis, it may be used only in programs within the ABAP+GUI dvelopment groups.

      Its use is subject to various restrictions, some of which may not be described in the documentation. This documentation is intended for internal SAP use within the Basis development group ABAP+GUI.

      Changes and further developments, which may be incompatible, can occur at any time without prior notice!

      After diving deeper into the “Object Manage Calls”, i found

      SYSTEM-CALL OBJMGR CLONE f1 TO f2 -> Only available to ensure compatibility

      IMHO i will think twice before using this construct.

      BR

      Suhas

      (1) 
      1. Jürgen L

        You are asking the post man. The author of this blog is marketing books which are sold by his company. I would be very astonished if he had really the knowledge of all what he posted so far as blogs here and could answer the question.

        (1) 
  1. Suhas Saha

    Hi Sean,

    nice blog, i learnt something new. Thanks for sharing this piece of info!

    If i understand correctly, you are cloning the object to avoid the overhead of instantiating the same material during the lifetime of the application.

    Instead of re-calling the constructor every time the same material is added, we simply cloned an existing object and avoided the initialization runtime cost.

    Could you not have stored the material instance(s) in a “hashed” internal table, with material number(MATNR) as the key field? But then you would be reusing the instance.

    I am not sure if cloning creates a new instance or does it simply return the existing one? Maybe if you could elaborate on it.

    BR

    Suhas

    (0) 
  2. Paul Hardy

    At my company we have been using this for ages, years and years, and have never had any problems.

     

    To answer a question above, naturally if you say LO_SOMETHING = LO_SOMETHING_ELSE then both reference variables point to the same area of memory and changing one will change the other. This is just like Quantum Entanglement.

     

    With a clone though, you end up with two reference variables pointing to TWO different areas of memory, so you can change one without affecting the other. This concept was explored many years ago in the book “Spock Must Die!” by James Blish.

     

    This cloning thing can also be used in the “Memento” pattern where you want to keep a copy of an object instance at a point in time, so you can revert back to it if needed.

     

    Apropos SAP suddenly taking this statement away, in the same way they can delete unreleased function modules, this is in real life a bit of a rarity. The clone call still works in ECC6 EHP8 and it will most likely be there for the remaining life of ECC 6.0. It may not, however, be available in S/4 HANA. Mind you, the official position seems to be that using any sort of ABAP in S/4 HANA is naughty for us “customers”.

    (0) 
    1. Paul Hardy

      Just to clarify this a bit more.

      Have a look at standard SAP interface IF_OS_CLONE in your system and do a where used list. It pops up a fair few times in standard SAP programs and once or twice a standard SAP class does the SYSTEM-CALL thing to clone the object.

      The point of the interface is to hide the implementation, so I would advocate defining your code using the interfaces, so if SAP does ever take away the system call clone then you can do this a different way (which would not be easy) but the calling programs do not have to be changed.

       

      in regard to the example code in the blog above (from a book) about creating material objects followed by the “isn’t this brilliant?”. No it is not. It the worst possible way to achieve the desired result.

      Given that an instance of a material is essentially a singleton i.e. why would two instances of the same material behave in a different way? They would not, therefore you can re-use an existing instance.

      You could have a static factory method, where you input the material number, and if you already have an instance for that material in a static internal table return that, otherwise create a new one, add it to the static table while you are at it. You end up with 1 instance per material.

      You can buffer such instances locally in an internal table, as has been described above. This is the same as the factory method really. You end up with 1 instance per material.

      In the example in the design pattern book, the cloning creates a new instance for the same material, despite the fact you already have such an instance. therefore the number of instances of the material increases depending on the number of request for the same material. That is not quite as brilliant as suggested.

      I want people to use design patterns, but only for the purposes they were created for.

       

       

       

      (0) 
  3. Tanmoy Mondal

    I agree that the above example is not the best of the examples demonstrating the usage of Prototype Design Pattern. This pattern is useful while cloning objects where the object instantiation is an expensive and time consuming task.

    I think a good usage for this Design Pattern may be cloning of BOPF based business objects. I know that SAP has provided no functionality to copy an existing Incident in the EHSM based system and the ability to clone objects in such scenarios can be very useful. Each node in the business object is represented generically using the instance of the class CL_EHFND_ENA_NODE. Probably we could use the Prototype Design Pattern here more meaningfully; remember easier said than done 🙂 .

    What could be the other possible use cases and where does SAP use it? Thanks

    .

    Regards,

    Tanmoy

     

     

    (0) 

Leave a Reply