ABAP IF 구문 최적화

Updated:

BDC, BAPI Function Module을 활용해서 작성한 프로그램에 해당하는 코드를 활용했다.
Function Module : ZFM_ECHO061_01, ZFM_ECHO061_02
Program : ZECHO061_03

IF 구문 최적화

1) CONTINUE 사용

아래와 같이IF ~ ELSE ~ ENDIF 간격이 큰 경우나 IF문 여러 개가 중첩되어 사용될 경우에는 하나의 IF 문을 끝내고 다음 IF 문을 사용하도록 한다. 그래야지 코드를 이해하는 사람도 해당 조건을 굳이 계속 생각하지 않아도 된다. 보는 입장에서 논리적 단위가 짧게 끊길 수 있도록 짠다.

*  BDC BUILD
    IF IS_INFO-IND_SECTOR NE SPACE
      AND IS_INFO-MATERIAL NE SPACE
      AND IS_INFO-MATL_TYPE NE SPACE
      AND IS_INFO-BASE_UOM NE SPACE.

*     MM01
      PERFORM SET_BDC USING: 'X' 'SAPLMGMM' '0060' 'X',
                             ' ' 'RMMG1-MATNR' IS_INFO-MATERIAL '',
                             ' ' 'RMMG1-MBRSH' IS_INFO-IND_SECTOR '',
                             ' ' 'RMMG1-MTART' IS_INFO-MATL_TYPE '',
                             ' ' 'BDC_OKCODE' '=ENTR' '',
                             'X' 'SAPLMGMM' '0070' 'X',
                             ' ' 'BDC_OKCODE' '=SELA' '',
                             ' ' 'BDC_OKCODE' '=RESA' '',
                             ' ' 'MSICHTAUSW-KZSEL(01)' 'X' '',
                             ' ' 'MSICHTAUSW-KZSEL(02)' 'X' '',
                             ' ' 'BDC_OKCODE' '=ENTR' ''.

*     BASIC VIEW
      PERFORM SET_BDC USING: 'X' 'SAPLMGMM' '4004' 'X',
                             ' ' 'MAKT-MAKTX' IS_INFO-MATL_DESC '',
                             ' ' 'MARA-MEINS' IS_INFO-BASE_UOM '',
                             ' ' 'MARA-MTPOS_MARA' 'NORM' '',
                             ' ' 'BDC_OKCODE' '/00' ''.
      ENDIF.

*     SAVE
      PERFORM SET_BDC USING: ' ' 'BDC_OKCODE' '/00' '',
                             'X' 'SAPLSPO1' '0300' 'X',
                             ' ' 'BDC_OKCODE' '=YES' ''.
    ENDIF.

  ELSE. " 필수값이 없는 경우
    LS_BODY-MATNR   = IS_INFO-MATERIAL.
    "Required data is missing for transaction MM01.
    LS_BODY-MESSAGE = TEXT-M06.
    LS_BODY-TYPE    = 'E'.
    APPEND LS_BODY TO ET_RETURN_BODY.

    LS_RETURN-MATNR   = IS_INFO-MATERIAL.
    "Required data is missing for transaction MM01.
    LS_RETURN-MESSAGE = TEXT-M06.
    LS_RETURN-TYPE    = 'E'.
    APPEND LS_RETURN TO ET_RETURN.

  ENDIF.

위의 코드를 보다 알맞게 작성하면 다음과 같다.

*  BDC BUILD
    IF IS_INFO-IND_SECTOR EQ SPACE
      OR IS_INFO-MATERIAL EQ SPACE
      OR IS_INFO-MATL_TYPE EQ SPACE
      OR IS_INFO-BASE_UOM EQ SPACE.

      LS_BODY-MATNR   = IS_INFO-MATERIAL.
      "Required data is missing for transaction MM01.
      LS_BODY-MESSAGE = TEXT-M06.
      LS_BODY-TYPE    = 'E'.
      APPEND LS_BODY TO ET_RETURN_BODY.

      LS_RETURN-MATNR   = IS_INFO-MATERIAL.
      "Required data is missing for transaction MM01.
      LS_RETURN-MESSAGE = TEXT-M06.
      LS_RETURN-TYPE    = 'E'.
      APPEND LS_RETURN TO ET_RETURN.
      CONTINUE.
    ENDIF.
    
*   MM01
    PERFORM SET_BDC USING: 'X' 'SAPLMGMM' '0060' 'X',
                           ' ' 'RMMG1-MATNR' IS_INFO-MATERIAL '',
                           ' ' 'RMMG1-MBRSH' IS_INFO-IND_SECTOR '',
                           ' ' 'RMMG1-MTART' IS_INFO-MATL_TYPE '',
                           ' ' 'BDC_OKCODE' '=ENTR' '',
                           'X' 'SAPLMGMM' '0070' 'X',
                           ' ' 'BDC_OKCODE' '=SELA' '',
                           ' ' 'BDC_OKCODE' '=RESA' '',
                           ' ' 'MSICHTAUSW-KZSEL(01)' 'X' '',
                           ' ' 'MSICHTAUSW-KZSEL(02)' 'X' '',
                           ' ' 'BDC_OKCODE' '=ENTR' ''.
*   BASIC VIEW
    PERFORM SET_BDC USING: 'X' 'SAPLMGMM' '4004' 'X',
                           ' ' 'MAKT-MAKTX' IS_INFO-MATL_DESC '',
                           ' ' 'MARA-MEINS' IS_INFO-BASE_UOM '',
                           ' ' 'MARA-MTPOS_MARA' 'NORM' '',
                           ' ' 'BDC_OKCODE' '/00' ''.
    ENDIF.

*   SAVE
    PERFORM SET_BDC USING: ' ' 'BDC_OKCODE' '/00' '',
                           'X' 'SAPLSPO1' '0300' 'X',
                           ' ' 'BDC_OKCODE' '=YES' ''. 

해당 코드를 보면 앞에서 조건을 충족하지 못하는 경우의 로직만 타고 CONTINUE 로 빠져나오게 되기 때문에 이후의 구문을 타지 않는다. 즉, 처음 코드와 동일하게 작동한다. 하지만, 이전과 달리 IF ~ ENDIF 에 대한 논리적인 단위가 짧기 때문에 코드를 읽는 입장에서 굳이 ENDIF, ELSE를 염두하지 않고 이후 구문을 읽으면 된다.



2) 다중 IF ~ ENDIF 분리

위의 경우는 ELSE, ELSEIF 에 해당되는 아주 뒤의 로직을 앞으로 가져와서 처리하고 CONTINUE 로 빠져오도록 함으로써 IF 의 구간을 줄였다. 그러나 이 외에도 다중 IF 문을 처리해야 하는 상황이 있다. 아래 경우는 여러 조건에 대한 로직을 작성할 때, 하나 조건에 대한 로직 처리를 한 후 다음 로직을 처리 하도록 IF 문을 분리하는 방식을 이용해 최적화해보자.

*   BDC OPTION & RUN BDC
    CLEAR LS_OPT.
    LS_OPT-DISMODE  = 'N'.
    LS_OPT-UPDMODE  = 'S'.
    CLEAR: LT_MSG[], LS_MSG, LS_RETURN, LV_LAST_INDEX, LV_MSG.
    CALL TRANSACTION 'MM01' USING GT_BDC
                            OPTIONS FROM LS_OPT
                            MESSAGES INTO LT_MSG.

*   MESSAGE
    CLEAR: LV_MSG, LS_MSG, LV_LAST_INDEX.
    DESCRIBE TABLE LT_MSG LINES LV_LAST_INDEX.
    LOOP AT LT_MSG INTO LS_MSG.
      MESSAGE ID LS_MSG-MSGID TYPE   LS_MSG-MSGTYP
                              NUMBER LS_MSG-MSGNR
                              WITH   LS_MSG-MSGV1
                                     LS_MSG-MSGV2
                                     LS_MSG-MSGV3
                                     LS_MSG-MSGV4
                              INTO   LV_MSG .

      "SPECIFIC MESSAGE
      IF LS_MSG-MSGTYP NE 'S'.
        CLEAR: LS_BODY.
        LS_BODY-MATNR     = IS_INFO-MATERIAL.
        LS_BODY-TYPE      = LS_MSG-MSGTYP.
        LS_BODY-MESSAGE   = LV_MSG.
        APPEND LS_BODY TO ET_RETURN_BODY.
      ENDIF.

      "FINAL MESSAGE
      IF SY-TABIX EQ LV_LAST_INDEX.

        IF LS_MSG-MSGTYP EQ 'S'
          AND LS_MSG-MSGID EQ 'M3'
          AND LS_MSG-MSGNR EQ '800'.
          LS_RETURN-MATNR   = IS_INFO-MATERIAL.
          LS_RETURN-TYPE    = 'S'.
          LS_RETURN-MESSAGE = LV_MSG.

*         CHECK CREATED VIEW
          PERFORM GET_MARA USING IS_INFO-MATERIAL
                           CHANGING LV_PSTAT.

          CLEAR: LV_RESULT.
          PERFORM GET_VIEW USING LV_PSTAT
                                 LV_RESULT.

          LS_RETURN-RESULT_VIEW  = LV_RESULT.

        ELSE.
          IF LS_MSG-MSGTYP EQ 'S'.
            LS_MSG-MSGTYP = 'E'.
          ENDIF.
          LS_RETURN-MATNR   = IS_INFO-MATERIAL.
          LS_RETURN-TYPE    = LS_MSG-MSGTYP.
          LS_RETURN-MESSAGE = LV_MSG.
        ENDIF.
      ENDIF.
    ENDLOOP.	

위의 코드는 메세지를 읽어들이면서 성공 및 실패 경우에 따라 메세지 처리를 (성공인 경우 마지막 메세지만 값을 내보내고 실패인 경우에는 마지막 메세지 및 상세 오류 로그를 내보내도록 함) 진행한다. 그러나 IF ~ ENDIF 구문의 영역이 크다. 따라서 성공 경우에 성공 메세지 로직을, 실패 경우에 실패 메세지 로직을 타도록 따로 작성한다.

아래의 경우 성공인 경우를 하나의 IF 구문으로 묶고 실패의 경우는 따로 묶지 않고 처리했다.


*   BDC OPTION & RUN BDC
    CLEAR LS_OPT.
    LS_OPT-DISMODE  = 'N'.
    LS_OPT-UPDMODE  = 'S'.
    CLEAR: LT_MSG[], LS_MSG, LS_RETURN, LV_LAST_INDEX, LV_MSG.
    CALL TRANSACTION 'MM01' USING GT_BDC
                            OPTIONS FROM LS_OPT
                            MESSAGES INTO LT_MSG.
                            
*   성공 메세지 처리
*   MESSAGE: SUCCEED
    SORT LT_MSG BY MSGTYP MSGID MSGNR.
    READ TABLE LT_MSG WITH KEY MSGTYP = 'S'
                               MSGID  = 'M3'
                               MSGNR  = '800'
                      BINARY SEARCH
                      TRANSPORTING NO FIELDS.

    IF SY-SUBRC EQ 0.

      LS_RETURN-MATNR   = IS_INFO-MATERIAL.
      LS_RETURN-TYPE    = 'S'.
      LS_RETURN-MESSAGE = LV_MSG.

*     CHECK CREATED VIEW
      PERFORM GET_MARA USING IS_INFO-MATERIAL
                       CHANGING LV_PSTAT.

      CLEAR: LV_RESULT.
      PERFORM GET_VIEW USING LV_PSTAT
                             LV_RESULT.

      LS_RETURN-RESULT_VIEW  = LV_RESULT.
      APPEND LS_RETURN TO ET_RETURN.
      CLEAR: GT_BDC[], GS_BDC, LV_VIEW, LV_RESULT.
      CONTINUE.
    ENDIF.
    
*   실패 메세지 처리
*   MESSAGE: FAIL
    CLEAR: LV_LAST_INDEX.
    DESCRIBE TABLE LT_MSG LINES LV_LAST_INDEX.
    LOOP AT LT_MSG INTO LS_MSG.
      LV_MSG_INDEX = SY-TABIX.
      MESSAGE ID LS_MSG-MSGID TYPE   LS_MSG-MSGTYP
                              NUMBER LS_MSG-MSGNR
                              WITH   LS_MSG-MSGV1
                                     LS_MSG-MSGV2
                                     LS_MSG-MSGV3
                                     LS_MSG-MSGV4
                              INTO   LV_MSG .

      "SPECIFIC MESSAGE
      IF LS_MSG-MSGTYP NE 'S'.
        LS_BODY-MATNR     = IS_INFO-MATERIAL.
        LS_BODY-TYPE      = 'E'." LS_MSG-MSGTYP.
        LS_BODY-MESSAGE   = LV_MSG.
        APPEND LS_BODY TO ET_RETURN_BODY.
      ENDIF.

      "FINAL MESSAGE
      IF LV_MSG_INDEX EQ LV_LAST_INDEX.

        IF LS_MSG-MSGTYP EQ 'S' OR LS_MSG-MSGTYP EQ 'W'.
          LS_MSG-MSGTYP = 'E'.
        ENDIF.
        LS_RETURN-MATNR   = IS_INFO-MATERIAL.
        LS_RETURN-TYPE    = LS_MSG-MSGTYP.
        LS_RETURN-MESSAGE = LV_MSG.
        APPEND LS_RETURN TO ET_RETURN.
      ENDIF.

    ENDLOOP.
    CLEAR: GT_BDC[], GS_BDC, LV_VIEW, LV_RESULT.