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.