Skip to Content

In the previous post Object Oriented Design Principles (OODP): Open-Closed Principle(OCP) of the series OODP, we have seen how we can achieve the OCP using Shape object like Square, Circle. In this blog post, we will see how we can use the Open-Closed Principle in business scenario.

As noted in the previous post thumb rule for OCP is: We can add new features in the module without changing the existing code (CLOSED) but by adding new code (OPEN).

 

Requirement:
There is a need for a data upload program to create a sales order. Flat file would be the source of the data for this program. We are getting some fields in the flat file like Customer number, Material number, Plant etc. Obviously, it is required to validate the input before calling the BAPI to create the sales order. For this example, we would concentrate on the validation part. We will use the polymorphism to achieve the OCP for this requirement.

 

UML diagram would look like this:

image

 

To realize this requirement, we would create an interface LIF_SUBOBJ for common methods which we can use in different classes like Customer LCL_KUNNR, Material LCL_MATNR, etc. Definition of the interface and interface impelementing classes:

 

Method IS_VALID in the customer class LCL_KUNNR validates the customer number against the customer master KNA1. Method IS_VALID in the material class LCL_MATNR validates the material number against the material master MARA.
Implementation for these classes LCL_KUNNR, LCL_MATNR:

 

Public attribute LT_OBJ of class LCL_SO is an internal table which holds the reference of different objects like Customer LCL_KUNNR, Material Number LCL_MATNR etc. Method VALIDATE_KEYS of the class LCL_SO calls the method IS_VALID of each object reference of the table LT_OBJ attribute. We will use down cast from the object reference in LT_OBJ to object reference of LIF_SUBOBJ. Definition and Implementation of the sales order class LCL_SO is:

 

Full code sinppet of the program could be found here. For completion purpose, I have included local class based exception in this coding.

 

Change in Requirement:
After successful validation of the object, it required to set some attributes of the each object. E.g. set the customer name attribute of the object customer. We will achieve this added requirement without any modification of the method VALIDATE_KEYS.

By adding a new method SET_ATTRIBUTES in the interface LIF_SUBOBJ, it will be available in all implementing classes like LCL_KUNNR, LCL_MATNR. Call this method inside the LOOP of objects after key validation in the method VALIDATE_KEYS. Updated UML will look like this:

image

And updated code snippet can be found here.

 

Conclusion:
Method VALIDATE_KEYS is closed for any modification:
* Achieve the same functionality (e.g. validating the object key) by creating a new class implementing LIF_SUBOBJ (e.g. LCL_WERKS for Plant validation)
* Add a new common functionality (e.g. saving data into Ztable) by creating a new method in the interface (e.g. method SAVE_DATA_TO_ZTAB in class LIF_SUBOBJ)

To report this post you need to login first.

6 Comments

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

  1. Christoffer Berg
    Hi Naimesh,

    Good blog about a good design principle!

    I have a suggestion to make the use of polymorphosm a little cleaner. Instead of declaring references as “TYPE REF TO object”, declare them as “TYPE REF TO lif_subobj”. This way you avoid the down cast. The point of putting common methods in an interface is that you can deal with references to the interface to call those methods without having to down cast.

    You could also declare lty_obj as “TYPE REF TO lif_subobj” instead of as a structure with a single component. This doesn’t really have anything to do with polymorphism, but you avoid having to go through the component “obeject” to call the methods of the interface.

    Best regards,
    Christoffer

    (0) 
    1. Naimesh Patel Post author
      Hello Christoffer,

      Thanks for the compliments.

      I definitely agree with you about the cleaner polymorphism. I can certainly refer to the LIF_SUBOBJ instead of the generic OBJECT in the type definition of the LTY_OBJ, if I am only dealing with the interface part of the LCL_MATNR or LCL_KUNNR. But in this example, I am appending the entire object reference of that object into the table T_OBJ. This object can be used later for any object specific activity. Please check the wiki for entire code snippet: https://wiki.sdn.sap.com/wiki/x/boJCBg

      For example:
      * Customer
        CREATE OBJECT lo_obj TYPE lcl_kunnr
          EXPORTING
            if_kunnr = ‘0001000072’.
        la_obj-object = lo_obj.
        APPEND la_obj TO lo_so->lt_obj.

      I hope it would help to clarify the need to take the REF TO OBJECT instead of the REF TO LIF_SUBOBJ.

      Regards,
      Naimesh Patel

      (0) 
      1. Christoffer Berg
        My idea was something like this:

        public section of lcl_so:

        TYPES: lty_obj TYPE REF TO lif_subobj.
        DATA: lt_obj TYPE STANDARD TABLE OF lty_obj.

        start of selection:

        DATA: lo_obj TYPE REF TO lif_subobj.
        CREATE OBJECT lo_obj TYPE lcl_kunnr
          EXPORTING
            if_kunnr = ‘0001000072’.
        APPEND lo_obj TO lo_so->lt_obj.

        validate keys:

        DATA: lo_subobj TYPE REF TO lif_subobj.
        LOOP AT me->lt_obj INTO lo_subobj.
          lf_valid = lo_subobj->is_valid( ).

        Here I only use references to the interface. As long as the objects in lo_so->lt_obj always should be objects that implement lif_subobj, I still don’t see the need to use ref to object.

        Best regards,
        Christoffer

        (0) 
        1. Naimesh Patel Post author
          Hello Christoffer,

          I see the point now. I have changed the code in the both WIKIs.

          Hope to hear from you again on my future blogs 🙂

          Regards,
          Naimesh Patel

          (0) 
  2. K S

    Hi Naimesh Patel,

    Could not hold back the appreciation for explaining with a business scenario and real time objects. Need time to scrutinize it, but really useful in the context you have explained.

    Regards,

    KS

    (0) 

Leave a Reply