Design patterns

  1. Application patterns
      • Single window pattern
        • Call control
          • Process flow ( guided maintenance )
        1. Object-oriented patterns
          • Creational design patterns
            • Singleton
            • Multiton
            • Abstract factory
            • Builder
            • Factory
            • Lazy initialization
            • Prototype
          • Structural design patterns
            • Bridge
            • Adapter
            • Composite
            • Data access object
            • Decorator
            • Facade
            • Flyweight
            • Property container
            • Proxy
            • Chain of responsibility
          • Behavior design patterns
            • Strategy
            • Command
            • Mediator
            • Memento
            • Observer
            • Servant
            • State 
            • Template method
            • Visitor
            • Iterator
        2. Object-oriented programming
        3. SOA
        4. SA patterns
        5. Other
          •  А должен ли это быть микросервис? Имейте в виду шесть факторов (09.09.2021)

        Application patterns

        §1 Single window pattern

        A single window pattern is used to arrange/collect functions and processes related to the object in a single application window. Examples: VELO transaction in SAP VMS, batch cockpit, and handling unit monitor in SAP ECC.

        §2 Call control

        The pattern is applied in the Automotive solutions from SAP to standardize the tools for different parties and make the process more traceable what is important for production and automotive industry. It consists of several entities:
        • Business object;
        • Internal/External status for communication and management;
        • Action which encapsulates a separate business function changing the state of the business object;
        • The matrix which states the allowed behavior ( business processes ).

        §3 Process flow ( guided maintenance )

        To be added.

        Object-oriented design 

        Design Principles
        1. Open Close Principle: open for extension but closed for modifications.
        2. Dependency Inversion Principle
        3. Interface Segregation Principle: When we write our interfaces we should take care to add only methods that should be there. 
        4. Single Responsibility Principle: This principle states that if we have 2 reasons to change for a class, we have to split the functionality into two classes. 
        5. Liskov's Substitution Principle

        ========================Creational design patterns========================

        Singleton

        Ensure that only one instance of a class is created and provide a global point of access to the object:
        • a static member in the "Singleton" class, 
        • a private constructor and a static public method that returns a reference to the static member.

        Examples: Logger Classes, Configuration Classes, Accessing resources in shared mode,  Factories implemented as Singletons.


        Example! 
        As part of this article, I would first recap on how to setup your class to achieve Singleton design pattern. After that, we jump on to a simple example using the Singleton in Sales Order processing. Before we start, take a look at how the sequence UML would look like:

        Create a Global class in SE24. When you create the class, select the Private as Instantiation. This control how object is instantiated. In other words this controls where CREATE OBJECT statement for this object can be written. Since for Singleton you want to get the same object back if it was already created earlier, you need to control how the object is setup. Thus, you would need to select Private as Instantiation.
        Next you need to create an attribute which would hold the reference of the object. This needs to be Static as it needs to hold the object reference throughout the Session or Transaction.
        Now create a method to streamline the object creation. Since we already declared the object instantiation as Private, we need to instantiate the object within the class itself. This method would be responsible to do exactly that. You would need to add a return parameter to this message so object can be passed back to the client. I always prefer to call this method as GET_OBJECT. So, whenever I see GET_OBJECT, I know that this is Singleton – at least in my development.
        In implementation of the method GET_OBJECT, we check if the object already BOUND, use that otherwise create a new one.

        METHOD GET_OBJECT.
        " returning  value(RO_OBJECT) type ref to ZCL_SO_ADD_DETAILS .
        *
          IF zcl_so_add_details=>o_singleton IS NOT BOUND.
            CREATE OBJECT zcl_so_add_details=>o_singleton.
          ENDIF.
        *
          ro_object = zcl_so_add_details=>o_singleton .
        ENDMETHOD.

        FORM userexit_move_field_to_vbak.
          DATA: lo_add_data TYPE REF TO zcl_so_add_details.
          lo_add_data = zcl_so_add_details=>get_object( ).
          lo_add_data->set_header_fields( vbak ).
        ENDFORM.                    "userexit_move_field_to_vbak
        *
        FORM userexit_move_field_to_vbap.
          DATA: lo_add_data TYPE REF TO zcl_so_add_details.
          lo_add_data = zcl_so_add_details=>get_object( ).
          lo_add_data->set_item_fields( vbap ).
        ENDFORM.                    "userexit_move_field_to_vbap
        *
        FORM userexit_save_document.
          DATA: lo_add_data TYPE REF TO zcl_so_add_details.
          lo_add_data = zcl_so_add_details=>get_object( ).
          lo_add_data->save_data( ).
        ENDFORM.                    "userexit_save_document


        Reference: http://zevolving.com/2013/04/abap-objects-design-patterns-singleton-usage/

        Multiton

        The same as the Singleton, the difference instead of on an instance the class will comprise a static array of objects with the key.

        Abstract factory

        Use: Produce families of related objects without specifying their concrete classes.
        Steps: 
        1. Abstract Factory pattern suggests is to explicitly declare interfaces for each distinct product of the product family
        2. Make all variants of products follow those interfaces (concrete class).
        3. Declare the Abstract Factory: an interface with a list of creation methods for all products that are part of the product family.
        4. These methods must return abstract product types represented by the interfaces we extracted previously
        5. For each variant of a product family, we create a separate factory class based on the AbstractFactory interface.A factory is a class that returns products of a particular kind. 
        Example: Product families and their variants ({chair, sofa, table}, {art, modern, classic}).



        Builder

        Create a complex object by splitting the process of creation into meaningful steps:
        1. The Builder class specifies an abstract interface for creating parts of a Product object.
        2. The ConcreteBuilder constructs and puts together parts of the product by implementing the Builder interface. It defines and keeps track of the representation it creates and provides an interface for saving the product.
        3. The Director class constructs the complex object using the Builder interface.
        4. The Product represents the complex object that is being built.



        Note:
        • In the case of the Abstract Factory, the client uses the factory's methods to create its own objects. 
        • In the Builder case, the Builder class is instructed on how to create the object and then it is asked for it, but the way that the class is put together is up to the Builder class.
        Abstract factory generally returns the object immediately where as Builder has complex step-by-step process to build the object for you. Builder first instantiates the objects and follows through all the necessary steps to make sure object is ready for consumption.

        Factory

        Using SWITCH


        ro_obj =
        SWITCH #( iv_output_type
        WHEN 'ZABC' THEN NEW ophandler_zabc( )
        WHEN 'ZXYZ' THEN NEW ophandler_zxyz( )
        ELSE THROW cx_sy_no_handler( )
        ).


        Example

        REPORT  znp_dp_factory_method.
        *&---------------------------------------------------------------------*
        *& Purpose: Factory method Design Pattern
        *& Author : Naimesh Patel
        *&---------------------------------------------------------------------*
        
        *=====
        CLASS ophandler DEFINITION ABSTRACT.
          PUBLIC SECTION.
            CLASS-METHODSfactory
              IMPORTING iv_output_type TYPE kschl
              RETURNING value(ro_objTYPE REF TO ophandler.
            METHODSprocess_output ABSTRACT.
        ENDCLASS.                    "ophandler DEFINITION
        
        *=====
        CLASS ophandler_zabc DEFINITION INHERITING FROM ophandler.
          PUBLIC SECTION.
            METHODSprocess_output REDEFINITION.
        ENDCLASS.                    "ophandler_zabc DEFINITION
        *
        CLASS ophandler_zabc IMPLEMENTATION.
          METHOD process_output.
            WRITE'Processing ZABC'.
          ENDMETHOD.                    "process_output
        ENDCLASS.                    "ophandler_zabc IMPLEMENTATION
        
        *
        CLASS ophandler IMPLEMENTATION.
          METHOD factory.
            CASE iv_output_type.
              WHEN 'ZABC'.
        *       This could be very complex logic to instantiate the object
        *       so, this wrapper will make sure all that complexity is
        *       hidden from the consumer.
                CREATE OBJECT ro_obj TYPE ophandler_zabc.
              WHEN 'ZXYZ'.
                "create another object
              WHEN OTHERS.
                " raise exception
            ENDCASE.
          ENDMETHOD.                    "factory
        ENDCLASS.                    "ophandler IMPLEMENTATION
        
        *=====
        CLASS lcl_main_app DEFINITION.
          PUBLIC SECTION.
            CLASS-METHODSrun.
        ENDCLASS.                    "lcl_main_app DEFINITION
        *
        CLASS lcl_main_app IMPLEMENTATION.
          METHOD run.
            DATAlo_output TYPE REF TO ophandler.
            lo_output ophandler=>factory'ZABC' ).
            lo_output->process_output).
          ENDMETHOD.                    "run
        ENDCLASS.                    "lcl_main_app IMPLEMENTATION
        
        
        START-OF-SELECTION.
          lcl_main_app=>run).

        Lazy initialization

        Postpone creation of an object until the first access.

        Prototype

        Use: The idea behind the prototype is to clone an existing object to create a new one. This design pattern makes sense in cases where the constructor of an object has a demanding runtime. Cloning and modifying an existing object prevents the re-execution of the slow code.

        Example
         
        PROGRAM znp_dp_prototype.
        *
        CLASS lcl_report_data DEFINITION ABSTRACT.
          PUBLIC SECTION.
            METHODS: clone ABSTRACT
              RETURNING VALUE(ro_object) TYPE REF TO lcl_report_data.
            METHODS: select_data ABSTRACT.
        ENDCLASS.                    "lcl_report_data DEFINITION
        *
        CLASS lcl_detail_report_data DEFINITION INHERITING FROM lcl_report_data.
          PUBLIC SECTION.
            METHODS: clone REDEFINITION.
            METHODS: select_data REDEFINITION.
            DATA: t_data TYPE STANDARD TABLE OF t100.
        ENDCLASS.                    "lcl_detail_report_data DEFINITION
        *
        CLASS lcl_detail_report_data IMPLEMENTATION.
          METHOD select_data.
            SELECT * FROM t100
              INTO TABLE t_data
              UP TO 20 ROWS
              WHERE sprsl = sy-langu.
          ENDMETHOD.                    "select_Data
          METHOD clone.
        *   instantiate a new object
        *   Declaring a temp variable helps to set all the attributes
        *   by its name and allows to call the methods of the subclass
        *   itself as RO_OBJECT is defined wrt to Super class
            DATA: lo_object TYPE REF TO lcl_detail_report_data.
            CREATE OBJECT lo_object.
        *   list down all the attributes which needs to be copied over
            lo_object->t_data = me->t_data.
         
        *   Set it to return object
            ro_object = lo_object.
         
          ENDMETHOD.                    "clone
        ENDCLASS.                    "lcl_detail_report_data IMPLEMENTATION
        *
        CLASS lcl_main DEFINITION.
          PUBLIC SECTION.
            CLASS-METHODS: run.
        ENDCLASS.                    "lcl_main DEFINITION
        *
        CLASS lcl_main IMPLEMENTATION.
          METHOD run.
            DATA: lo_report TYPE REF TO lcl_report_data.
            CREATE OBJECT lo_report TYPE lcl_detail_report_data.
            lo_report->select_data( ).
         
            DATA: lo_rep_2 TYPE REF TO lcl_report_data.
            lo_rep_2 = lo_report->clone( ).
         
          ENDMETHOD.                    "run
        ENDCLASS.                    "lcl_main IMPLEMENTATION
        *
        START-OF-SELECTION.
          lcl_main=>run( ).
         

        ========================Structural design patterns========================

        Bridge

        The bridge is a structural design pattern that let us to split a large class or a set of closely related classes into two separate hierarchies—abstraction and implementation—which can be developed independently of each other.

        Example with a shape and color. How many combinations can we have?

        The Bridge pattern attempts to solve this problem by switching from inheritance to the object composition. As the number of cases on each side of the bridge increases, the advantage of
        using the bridge design pattern becomes more and more significant.

        Adapter

        Adapter converts the objects which are incompatible due to the difference in the “Interface”. By implementing Adapter, we can allow classes to work together, which can’t work without implementing the Adapter.

         
        REPORT ZNP_DP_ADAPTER.
        *
        INTERFACE lif_output.
          METHODS: generate_output.
        ENDINTERFACE.                    "lif_output
        *
        CLASS simple_op DEFINITION.
          PUBLIC SECTION.
            INTERFACES: lif_output.
        ENDCLASS.                    "simple_op DEFINITION
        *
        CLASS simple_op IMPLEMENTATION.
          METHOD lif_output~generate_output.
            WRITE: / 'Simple Output - just using WRITE'.
          ENDMETHOD.                    "lif_output~generate_output
        ENDCLASS.                    "simple_op IMPLEMENTATION
        *
        CLASS tree_output DEFINITION.
          PUBLIC SECTION.
            METHODS: generate_tree.
        ENDCLASS.                    "tree_output DEFINITION
        *
        CLASS tree_output IMPLEMENTATION.
          METHOD generate_tree.
            WRITE: / 'Creating Tree ... using CL_GUI_ALV_TREE'.
          ENDMETHOD.                    "generate_tree
        ENDCLASS.                    "tree_output IMPLEMENTATION
        *
        CLASS new_complex_op DEFINITION.
          PUBLIC SECTION.
            INTERFACES: lif_output.
        ENDCLASS.                    "new_complex_op DEFINITION
        *
        CLASS new_complex_op IMPLEMENTATION.
          METHOD lif_output~generate_output.
            DATA: o_tree_op TYPE REF TO tree_output.
            CREATE OBJECT o_tree_op.
            o_tree_op->generate_tree( ).
          ENDMETHOD.                    "lif_output~generate_output
        ENDCLASS.                    "new_complex_op IMPLEMENTATION
        *
        START-OF-SELECTION.
          DATA: o_op TYPE REF TO lif_output.
          CREATE OBJECT o_op TYPE simple_op.
          o_op->generate_output( ).
         
        * using the same "simple" Interface to perform the "complex",
        * Since Client only wants to use Simple interface ..
          CREATE OBJECT o_op TYPE new_complex_op.
          o_op->generate_output( ).
         

        Composite

        Sometimes we have to deal with Hierarchical or Tree type of data. The data which are related with each other and form a type of hierarchy. We can write the recursive logic to process related entries.

        Data access object

        If there are different data sources for the same object type, a data access object isolates the data operation logic from the business logic through a common data interface.
        1. Create a class as a Value object list;
        2. Create a Data Access Object Interface;
        3. Create Data Access Object concrete classes to extract data for each data source and set the interface to them for implementation.

        Decorator

        The decorator is useful when the state of a single object needs to be modified for multiple purposes. Each change is isolated in a separate class.

        DATA: lo_obj TYPE REF TOobject,
                    lo_decorator TYPE REF TO zif_decorator,
                    lt_cls TYPE STANDARD TABLE OF seometarel-clsname.

        SELECT clsname INTO TABLE lt_cls
        FROM seometarel WHERE refclsname eq ‘ZIF_DECORATOR’.

        LOOP AT lt_clsnameASSIGNINGFIELD-SYMBOL(<lv_clsname>).
        CREATE OBJECT lo_obj TYPE(<lv_clsname>).
        lo_decorator?=lo_obj.
        lo_decorator->decorate(CHANGING cs_data = ls_data).
        ENDLOOP.

        The decorators to be called dynamically during runtime.

        Example

        REPORT znp_dp_decorator.
        *&---------------------------------------------------------------------*
        *& Purpose: Decorator Design Pattern Demo
        *& Author : Naimesh Patel
        *&---------------------------------------------------------------------*
        
        * ===
        CLASS output DEFINITION ABSTRACT.
          PUBLIC SECTION.
            METHODS:
              process_output ABSTRACT.
        ENDCLASS.                    "output DEFINITION
        
        * ====
        CLASS alvoutput DEFINITION INHERITING FROM output.
          PUBLIC SECTION.
            METHODS:
              process_output REDEFINITION.
        ENDCLASS.                    "alvoutput DEFINITION
        
        *
        CLASS alvoutput IMPLEMENTATION.
          METHOD process_output.
            WRITE'Standard ALV output'.
          ENDMETHOD.                    "process_output
        ENDCLASS.                    "alvoutput IMPLEMENTATION
        
        * ====
        CLASS opdecorator DEFINITION INHERITING FROM output.
          PUBLIC SECTION.
            METHODS:
              constructor
                IMPORTING io_decorator TYPE REF TO output,
              process_output REDEFINITION.
          PRIVATE SECTION.
            DATAo_decorator TYPE REF TO output.
        ENDCLASS.                    "opdecorator DEFINITION
        
        *
        CLASS opdecorator IMPLEMENTATION.
          METHOD constructor.
            super->constructor).
            me->o_decorator io_decorator.
          ENDMETHOD.                    "constructor
          METHOD process_output.
            CHECK o_decorator IS BOUND.
            o_decorator->process_output).
          ENDMETHOD.                    "process_output
        ENDCLASS.                    "opdecorator IMPLEMENTATION
        
        * =====
        CLASS op_pdf DEFINITION INHERITING FROM opdecorator.
          PUBLIC SECTION.
            METHODSprocess_output REDEFINITION.
        ENDCLASS.                    "op_pdf DEFINITION
        
        *
        CLASS op_pdf IMPLEMENTATION.
          METHOD process_output.
            super->process_output).
            WRITE/(10space'Generating PDF'.
          ENDMETHOD.                    "process_output
        ENDCLASS.                    "op_pdf IMPLEMENTATION
        
        * ======
        CLASS op_xls DEFINITION INHERITING FROM opdecorator.
          PUBLIC SECTION.
            METHODSprocess_output REDEFINITION.
        ENDCLASS.                    "op_xls DEFINITION
        
        *
        CLASS op_xls IMPLEMENTATION.
          METHOD process_output.
            super->process_output).
            WRITE/(10space'Generating Excel'.
          ENDMETHOD.                    "process_output
        ENDCLASS.                    "op_xls IMPLEMENTATION
        
        * =====
        CLASS op_email DEFINITION INHERITING FROM opdecorator.
          PUBLIC SECTION.
            METHODSprocess_output REDEFINITION.
        ENDCLASS.                    "op_email DEFINITION
        
        *
        CLASS op_email  IMPLEMENTATION.
          METHOD process_output.
            super->process_output).
            WRITE/(10space'Sending Email'.
          ENDMETHOD.                    "process_output
        ENDCLASS.                    "op_email IMPLEMENTATION
        
        * ====
        CLASS op_alv DEFINITION INHERITING FROM opdecorator.
          PUBLIC SECTION.
            METHODSprocess_output REDEFINITION.
        ENDCLASS.                    "op_alv DEFINITION
        
        *
        CLASS op_alv IMPLEMENTATION.
          METHOD process_output.
            super->process_output).
            WRITE/(10space'Generating ALV'.
          ENDMETHOD.                    "process_output
        ENDCLASS.                    "op_alv IMPLEMENTATION
        
        * ====
        CLASS mainapp DEFINITION.
          PUBLIC SECTION.
            CLASS-METHODS:
              run IMPORTING
                iv_pdf   TYPE flag
                iv_email TYPE flag
                iv_xls   TYPE flag.
        ENDCLASS.                    "mainapp DEFINITION
        
        *
        CLASS mainapp IMPLEMENTATION.
          METHOD run.
            DATAlo_decorator TYPE REF TO output,
                  lo_pre TYPE REF TO output.          " Helper Variable
        
        * .... Setup objects
        *   standarad object
            CREATE OBJECT lo_decorator TYPE alvoutput.
            lo_pre lo_decorator.
        
        *   testing Decorator
            IF iv_pdf IS NOT INITIAL.
              CREATE OBJECT lo_decorator
                TYPE
                  op_pdf
                EXPORTING
                  io_decorator lo_pre.
              lo_pre lo_decorator.
            ENDIF.
            IF iv_email IS NOT INITIAL.
              CREATE OBJECT lo_decorator
                TYPE
                  op_email
                EXPORTING
                  io_decorator lo_pre.
              lo_pre lo_decorator.
            ENDIF.
            IF iv_xls IS NOT INITIAL.
              CREATE OBJECT lo_decorator
                TYPE
                  op_xls
                EXPORTING
                  io_decorator lo_pre.
              lo_pre  lo_decorator.
            ENDIF.
        
            lo_decorator->process_output).
        
          ENDMETHOD.                    "run
        ENDCLASS.                    "mainapp IMPLEMENTATION
        
        PARAMETERSp_pdf AS CHECKBOX,
                    p_email AS CHECKBOX,
                    p_xls AS CHECKBOX.
        
        START-OF-SELECTION.
          mainapp=>runiv_pdf p_pdf
                        iv_email p_email
                        iv_xls   p_xls
                         ).


        Facade

        The aim of the façade design pattern is to provide an access point to a complex set of classes. Depending on the complexity, the facade can be designed as a new singleton class or like a static method of a toolkit class.

        Example
        REPORT  z_np_dp_facade.
         
        *
        CLASS lcl_data DEFINITION.
          PUBLIC SECTION.
            METHODS: constructor.
        ENDCLASS.                    "lcl_Data DEFINITION
        *
        INTERFACE lif_write.
          METHODS: write_data.
        ENDINTERFACE.                    "lif_write DEFINITION
        *
        CLASS lcl_write_alv DEFINITION.
          PUBLIC SECTION.
            INTERFACES: lif_write.
        ENDCLASS.                    "lcl_write_alv DEFINITION
        *
        CLASS lcl_write_log DEFINITION.
          PUBLIC SECTION.
            INTERFACES: lif_write.
        ENDCLASS.                    "lcl_write_log DEFINITION
        *
        CLASS lcl_facade DEFINITION.
          PUBLIC SECTION.
            METHODS: process_report IMPORTING iv_write_type TYPE char1.
        ENDCLASS.                    "lcl_facade DEFINITION
        *
        CLASS lcl_data IMPLEMENTATION.
          METHOD constructor.
            WRITE: / 'Getting Data'.
          ENDMETHOD.                    "constructor
        ENDCLASS.                    "lcl_Data IMPLEMENTATION
        *
        CLASS lcl_write_alv IMPLEMENTATION.
          METHOD lif_write~write_data.
            WRITE: / 'Writing data in ALV'.
          ENDMETHOD.                    "lif_write~write_Data
        ENDCLASS.                    "lcl_write_alv IMPLEMENTATION
        *
        CLASS lcl_write_log IMPLEMENTATION.
          METHOD lif_write~write_data.
            WRITE: / 'writing data in Log'.
          ENDMETHOD.                    "lif_write~write_Data
        ENDCLASS.                    "lcl_write_log IMPLEMENTATION
        *
        CLASS lcl_facade IMPLEMENTATION.
          METHOD process_report.
            DATA: lo_data TYPE REF TO lcl_data.
            CREATE OBJECT lo_data.
         
            DATA: lo_write TYPE REF TO lif_write.
            IF iv_write_type = 'A'.
              CREATE OBJECT lo_write TYPE lcl_write_alv.
            ELSE.
              CREATE OBJECT lo_write TYPE lcl_write_log.
            ENDIF.
            lo_write->write_data( ).
          ENDMETHOD.                    "process_report
        ENDCLASS.                    "lcl_facade IMPLEMENTATION
         
        START-OF-SELECTION.
          DATA: lo_facade TYPE REF TO lcl_facade.
          CREATE OBJECT lo_facade.
          lo_facade->process_report( iv_write_type = 'A' ).
         

        Flyweight

        Flyweight makes sense if you foresee a large number of similar objects. Flyweight objects are usually created using a factory method, and the factory method. 


        Property container

        A property container is a package of variables passed around between classes. A property container usually goes with a companion to the decorator design pattern.

        Proxy

        The proxy design pattern is about wrapping an existing class with a new one, where the wrapper preserves the interface but behaves differently.

        What problems can the Proxy design pattern solve? 
        • Access to an object should be controlled.
        • The additional functionality should be provided when accessing an object.
        When accessing sensitive objects, for example, it should be possible to check that clients have the needed access rights.

        Proxy object only instantiate the object when it is required. If the object is not needed, it would not be created. Once the object is created, all the future operations would be carried over on the “Real” object instead of on the proxy object. Both – proxy and real – objects would implement the same interface. Thus both object can perform same operations seamlessly. Also the proxy object can pass all the signature to the real object. Proxy acts on behalf of some other objects. When working with Proxies, as name suggest, you work with another object rather than actual object.

        Example
         
        REPORT  znp_dp_proxy.
        *
        INTERFACE lif_data.
          DATA: t_t100 TYPE tt_t100.
          METHODS: get_data
            IMPORTING iv_spras TYPE spras OPTIONAL
            CHANGING ct_data TYPE tt_t100.
          METHODS: write_data.
        ENDINTERFACE.                    "lif_data
        *
        CLASS lcl_proxy_data DEFINITION.
          PUBLIC SECTION.
            INTERFACES: lif_data.
          PRIVATE SECTION.
            DATA: o_t100_data TYPE REF TO lif_data.
        ENDCLASS.                    "lcl_proxy_Data DEFINITION
        *
        CLASS lcl_t100_data DEFINITION.
          PUBLIC SECTION.
            INTERFACES: lif_data.
        ENDCLASS.                    "lcl_t100_Data DEFINITION
        *
        CLASS lcl_proxy_data IMPLEMENTATION.
          METHOD lif_data~get_data.
        *   validations
            IF iv_spras NE sy-langu.
              EXIT.
            ENDIF.
         
        *   Authority check
        *   some other check
         
        *   instantiate "Real" Object
            CREATE OBJECT o_t100_data TYPE lcl_t100_data.
            o_t100_data->get_data(
              EXPORTING
                iv_spras = iv_spras
              CHANGING
                ct_data = ct_data ).
         
          ENDMETHOD.                    "lif_data~get_data
          METHOD lif_data~write_data.
            IF o_t100_data IS NOT BOUND.
              WRITE:/ 'No data to display'.
            ELSE.
              o_t100_data->write_data( ).
            ENDIF.
          ENDMETHOD.                    "lif_data~write_Data
        ENDCLASS.                    "lcl_proxy_Data IMPLEMENTATION
        *
        CLASS lcl_t100_data IMPLEMENTATION.
          METHOD lif_data~get_data.
        *   This process takes very long time to
        *   get the data. You can imagine this happening
        *   when accessing big tables without index.
            SELECT * FROM t100
              INTO TABLE lif_data~t_t100
              UP TO 20 ROWS
              WHERE sprsl = iv_spras.
            ct_data = lif_data~t_t100.
          ENDMETHOD.                    "lif_data~get_data
          METHOD lif_data~write_data.
            DATA: lv_lines TYPE i.
            lv_lines = LINES( lif_data~t_t100 ).
            WRITE: / 'Total lines',lv_lines.
          ENDMETHOD.                    "lif_data~write_Data
        ENDCLASS.                    "lcl_t100_Data IMPLEMENTATION
        *
        CLASS lcl_main_app DEFINITION.
          PUBLIC SECTION.
            CLASS-METHODS: run.
        ENDCLASS.                    "lcl_main_app DEFINITION
        *
        CLASS lcl_main_app IMPLEMENTATION.
          METHOD run.
            DATA: lo_proxy TYPE REF TO lif_data.
            DATA: lt_data TYPE tt_t100.
         
        *
            CREATE OBJECT lo_proxy TYPE lcl_proxy_data.
            lo_proxy->get_data( EXPORTING iv_spras = 'D'
                                CHANGING ct_data = lt_data ).
            lo_proxy->write_data( ).
         
        *
            CREATE OBJECT lo_proxy TYPE lcl_proxy_data.
            lo_proxy->get_data( EXPORTING iv_spras = sy-langu
                                CHANGING ct_data = lt_data ).
            lo_proxy->write_data( ).
         
         
          ENDMETHOD.                    "run
        ENDCLASS.                    "lcl_main_app IMPLEMENTATION
        *
        START-OF-SELECTION.
          lcl_main_app=>run( ).
         

        Chain of responsibility

        A chain of responsibility might be used when you have many potential classes to handle a request but you do not know which should handle it. Each class inspects the request and either handle it or forwards it to the next candidate.


        ========================Behavior design patterns========================

        Strategy

        Use: Having multiple algorithms to share the same interface.
        1. Create an interface to cover all algorithms with the method ‘calculate’;
        2. Decide how to pass the data to the strategy object:
          • In the form of internal tables, working areas, variables, and objects
          • Passing the context object itself 
        3. Decide if the algorithms' classes have the same. If it is, then creates an abstract intermediate class for that;
        4. Create a class for each algorithm and implement the method ‘calculate’;
        5. Create an object using the interface based on the criteria, a sample:
          • DATA: lo_obj TYPE REF TO object.
          • DATA: lo_obj TYPE REF TO zif_strategy.
          • DATA(lv_class) = COND seoclasname(  WHEN.. , THEN ..)
          • CREATE OBJECT lo_obj TYPE lv_class.
          • strategy ?= lo_obj.
          • strategy->calculate().

        Command

        Mediator

        Provide a central point that administers how objects interact.

        Memento

        Observer

        The observer design pattern informs other classes when something important happens in the source class.
        1. Define Subject, Observer interface, and Observer objects.
        2. so that when a subject changes state, all registered observers are notified and updated automatically (and probably asynchronously).


        Example
        We have a Subject class as MAINPROCESS. This class has the event as STATE_CHANGED. We would trigger the event whenever there is any change in the state of the object. Thus, we raise the event when we set the new status of the object – attribute CURRENT_STATE using the method SET_STATE( ).

        We have an abstract super class MYFUNCTION. We created event handler method ON_STATE_CHANGED for the event STATE_CHANGED of class MAINPROCESS. We inherite two classes MYALV and MYDB from it. We redefine the methods to refresh their status.

        program znp_dp_observer.
        
        *====
        CLASS mainprocess DEFINITION.
          PUBLIC SECTION.
            METHODSset_state IMPORTING iv_state TYPE char1.
            EVENTSstate_changed EXPORTING value(new_stateTYPE char1.
          PRIVATE SECTION.
            DATAcurrent_state TYPE char1.
        ENDCLASS.                    "mainprocess DEFINITION
        *
        CLASS mainprocess IMPLEMENTATION.
          METHOD set_state.
            current_state iv_state.
            SKIP 2.
            WRITE'Main Process new state'current_state.
            RAISE EVENT state_changed EXPORTING new_state current_state.
          ENDMETHOD.                    "set_state
        ENDCLASS.                    "mainprocess IMPLEMENTATION
        
        *====
        CLASS myfunction DEFINITION ABSTRACT.
          PUBLIC SECTION.
            METHODSon_state_changed ABSTRACT
              FOR EVENT state_changed OF mainprocess
              IMPORTING new_state.
        ENDCLASS.                    "myfunction DEFINITION
        
        *====
        CLASS myalv DEFINITION INHERITING FROM myfunction.
          PUBLIC SECTION.
            METHODSon_state_changed REDEFINITION.
        ENDCLASS.                    "myalv DEFINITION
        *
        CLASS myalv IMPLEMENTATION.
          METHOD on_state_changed.
            WRITE'New state in ALV processing'new_state.
          ENDMETHOD.                    "on_state_changed
        ENDCLASS.                    "myalv IMPLEMENTATION
        *====
        CLASS mydb DEFINITION INHERITING FROM myfunction.
          PUBLIC SECTION.
            METHODSon_state_changed REDEFINITION.
        ENDCLASS.                    "mydb DEFINITION
        *
        CLASS mydb IMPLEMENTATION.
          METHOD on_state_changed.
            WRITE'New State in DB processing'new_state.
          ENDMETHOD.                    "on_state_changed
        ENDCLASS.                    "mydb IMPLEMENTATION
        
        *====
        CLASS mainapp DEFINITION.
          PUBLIC SECTION.
            CLASS-METHODSrun.
        ENDCLASS.                    "mainapp DEFINITION
        *
        CLASS mainapp IMPLEMENTATION.
          METHOD run.
        
            DATAlo_process TYPE REF TO mainprocess.
            DATAlo_alv TYPE REF TO myalv.
            DATAlo_db TYPE REF TO mydb.
        
        *   Instantiate the objects
            CREATE OBJECT lo_process.
            CREATE OBJECTlo_alvlo_db.
        
        *   Event handlers
            SET HANDLER lo_alv->on_state_changed FOR lo_process.
            SET HANDLER lo_db->on_state_changed FOR lo_process.
        
        *   Set new state
            lo_process->set_state'A' ).
            lo_process->set_state'B' ).
            lo_process->set_state'C' ).
        
          ENDMETHOD.                    "run
        ENDCLASS.                    "mainapp IMPLEMENTATION
        
        START-OF-SELECTION.
          mainapp=>run).

        Servant

        If you have several methods to be shared among multiple unrelated classes,  put them inside of a servant class instead of copying and pasting them into each and every client.  The servant classes are useful for small utility methods.
        1. Create a servant class (utility, service)l
        2. Create an interface to group classes to be served for;
        3. Add attributes (with the interface type) and implementation;
        4. Add classes where the servant class should be used and set the interface to them.

        State 

        Allow an object to alter its behavior when its internal state changes. The object will appear to change its class. This pattern will reduce conditional statements and reduce duplication.
        1. Define an interface containing the methods that should act differently depending on the state;
        2. Create an implementation of the interface for each possible state;
        3. Set up the main class so it uses the corresponding state class depending on the state itself.

        Template method

        Developing the classes that work mostly on the same logic but have small deviations.A template method defines an algorithm in a base class using abstract operations that subclasses override to provide concrete behavior.

        1. Abstract Class:
          • defines abstract primitive operations (#PROTECTED SECTION) that concrete subclasses define to implement steps of an algorithm. It's important when designing template methods to minimize the number of primitive methods that a subclass must override in order to provide a clear easy way to implement concrete templates.
          • implements a template method (#FINAL it should not be overridden) which defines the skeleton of an algorithm and calls primitive operations as well as operations defined in AbstractClass or those of other objects.
        2. Concrete Class implements the primitive operations (#REDEFINITION) to carry out subclass-specific steps of the algorithm.
        Template Method and Strategy Design Pattern: The difference consists in the fact that Strategy uses delegation while the Template Methods uses the inheritance.

        Visitor


        Iterator

        Iterator design pattern is to provide a way to access the underlying object collection without exposing the underlying representations. Iterator decouples the logic to access the collection of objects out of the Collection object itselft. This decoupling provides added adavantage while traversing through the different type of collection objects.

        We should try to implement Iterator because,
        • We could create as many iterator as we want to traverse objects in the different sequence.
        • Linked List Object collection – When we need to use the Linked List type of the object collection, it would be difficult for every client to implement the accessing algorithm. Rather than that, we can create the Iterator and all clients can straight away use Iterator to access any object collection – ITAB or Linked List.
        http://zevolving.com/2012/01/iterator-design-pattern-to-access-linked-list/

        Object-oriented programming

        #Class

        FINAL prevents the class from having any further subclasses.
        CREATE PUBLIC means any program, class, etc. can create an instance of this class freely.
        Public, private, and protected (Any variable or method defined here can be accessed by the subclasses only) sections.
        The distinction of public/protected/private sections is traditionally called encapsulation.
        Polymorphism is the ability to present the same interface for different underlying classes.\
        #Superclass (inheritance is about re-using the code of the parent class)

        #Abstract Class 

        ..is used to make a partial implementation and to let the subclasses complete what is missing.
        • The methods that must be redefined are marked as ABSTRACT
        • The methods that can optionally be redefined are not marked at all,
        • The methods that should not be redefined are marked as FINAL.

        #Interface

        A class can implement multiple interfaces.
        Usually, we should start from the most abstract level and move down to the concrete level.
        If we are implementing an interface into an abstract class, you can define which methods are abstract (must be implemented by subclasses) or final (must be implemented by the abstract class).
        CLASS zcl_abstr_cls DEFINITION PUBLIC ABSTRACT CREATE PUBLIC.
        PUBLIC SECTION.
        INTERFACES if_intf_1 ALL METHODS FINAL.
        ...
        PUBLIC SECTION.
        INTERFACES if_intf_2 ALL METHODS ABSTRACT.

        SOA

        Service-Oriented Architecture (SOA) is a style of software design where services are provided to the other components by application components, through a communication protocol over a network. Its principles are independent of vendors and other technologies. In service oriented architecture, a number of services communicate with each other, in one of two ways: through passing data or through two or more services coordinating an activity. 

        Service-Oriented Architecture Patterns

        There are three roles in each of the Service-Oriented Architecture building blocks: 
        • service provider; 
        • service broker, service registry, service repository; a
        • nd service requester/consumer.

        The service provider works in conjunction with the service registry, debating the whys and hows of the services being offered, such as security, availability, what to charge, and more. This role also determines the service category and if there need to be any trading agreements.

        The service broker makes information regarding the service available to those requesting it. The scope of the broker is determined by whoever implements it.

        The service requester locates entries in the broker registry and then binds them to the service provider. They may or may not be able to access multiple services; that depends on the capability of the service requester.

        Implementing Service-Oriented Architecture

        When it comes to implementing service-oriented architecture (SOA), there is a wide range of technologies that can be used, depending on what your end goal is and what you’re trying to accomplish.

        Typically, Service-Oriented Architecture is implemented with web services, which makes the “functional building blocks accessible over standard internet protocols.”

        An example of a web service standard is SOAP, which stands for Simple Object Access Protocol. In a nutshell, SOAP “is a messaging protocol specification for exchanging structured information in the implementation of web services in computer networks. Although SOAP wasn’t well-received at first, since 2003 it has gained more popularity and is becoming more widely used and accepted. Other options for implementing Service-Oriented Architecture include Jini, COBRA, or REST.

        It’s important to note that architectures can “operate independently of specific technologies,” which means they can be implemented in a variety of ways, including messaging, such as ActiveMQ; Apache Thrift; and SORCER.


        Differences Between Service-Oriented Architecture and Microservices

        Microservices, also known as Microservice Architecture, is an “architectural style that structures an application as a collection of small autonomous services, modeled around a business domain.”

        While microservices and Service-Oriented Architecture are similar in some ways, the key differences come in their functionality. Services is, obviously, the main component of both. There are four basic types of services:
        • Functional service: these define core business operations
        • Enterprise service: these implement the functionality defined by the functional services
        • Application service: these are confined to specific application content
        • Infrastructure service: implements non-functional tasks such as authentication, auditing, security, and logging
        As you can see, each of these services builds on the one before it, creating a system that is not only easy to use, but provides you with a variety of ways to manage your business. As with any functionality, it’s a matter of figuring out what works best for you and your business.


        SA patterns

        Every system has an architecture — some high-level structure that underlies the whole system. Software architecture is how the pieces fit together to build the solution to some business or technical need that your customer or client wants solved. The architecture has a purpose. The decisions made during the creation of the architecture are truly fundamental to the system because they set the stage for all the other decisions that will come later.
        • Components of software architecture
        • Goals and philosophy of the system
        • Architectural assumptions and dependencies
        • Architecturally significant requirements
        • Packaging instructions for subsystems and components
        • Critical subsystems and layers
        • References to architecturally significant design elements
        • Critical system interfaces
        • Key scenarios that describe critical behavior of the system
        All the components in the preceding section go into an architecture document, which contains the information needed to interpret the architecture. 

        Models
        1. Logical: Maps the system onto classes and components. 
        2. Process: Explains how the parts of the architecture work together and how the parts stay synchronized.
        3. Physical: Explains how the software that implements the system is mapped onto the computing platforms.
        4. Development: Explains how the software will be managed during development.
        The problems that you solve with software architectures have four main 
        attributes:
        • Function: Describes the problem to be solved
        • Form: Describes the shape of the solution and how it fits into the environment of other systems and technologies
        • Economy: Describes how much it costs to build, operate, and maintain the solution
        • Time: Describes how the problem is expected to change in the future
        Based on your understanding of the problem from completing the preceding four steps, you can write a problem statement that brings in the four attributes of function, form, economy, and time (see the preceding section) in a way that explains it to the customer or client.

        Other

        А должен ли это быть микросервис? Имейте в виду шесть факторов

        1. Различные скорости изменений
          • Части вашей системы должны развиваться с разной скоростью или в разных направлениях? Тогда разделите их на микросервисы. Это позволит каждому компоненту иметь свой независимый жизненный цикл.
        2. Независимые жизненные циклы
          • Если модуль обладает полностью независимым жизненным циклом (имеется в виду от фиксации кода до продакшена), то он должен быть микросервисом. У него будет свой собственный репозиторий кода, CI/CD пайплайн и так далее.
        3. Независимая масштабируемость
          • Если характеристики нагрузки или пропускной способности частей системы различны, они могут иметь разные требования к масштабированию. Решение: разделите эти компоненты на независимые микросервисы! Таким образом, сервисы могут масштабироваться с разной скоростью.
        4. Изолированный сбой
          • Иногда мы хотим изолировать наше приложение от определенного типа сбоев. Например, что произойдет, если у нас есть зависимость от внешнего сервиса, который не соответствует нашим требованиям по доступности? Можно создать микросервис, чтобы изолировать эту зависимость от остальной системы. Затем встроим соответствующие механизмы обхода отказа в эту службу.
        5. Микросервисы могут действовать как косвенный уровень, чтобы изолировать вас от сторонней зависимости. Вместо того чтобы напрямую вызывать зависимость, можно разместить слой абстракции (который мы контролируем) между основным приложением и зависимостью. Кроме того, мы можем построить этот слой так, чтобы он был легким для потребления нашим приложением, скрывая сложность зависимости. Если в будущем ситуация изменится - и вам придется мигрировать - ваши изменения ограничатся только фасадом, а не более масштабным рефакторингом.
        6. С микросервисами команды могут свободно использовать предпочитаемые стеки технологий. Иногда бизнес-требования соответствуют конкретному выбору технологии. В других случаях это обусловлено предпочтениями разработчиков и их привычками.

        Comments

        1. Please, let us know, if you have yours patterns you use for ABAP development.

          ReplyDelete

        Post a Comment