본문 바로가기

ABAP 프로그래밍 개념/Modulazation Technique

2-4 추가. Modularization Techniques - Program Structure : Procedure : Subroutine

Subroutine은 FORM ~ ENDFORM 사이의 구문에서 유지되며, PERFROM 구문을 통해 호출됩니다.

FORM subroutine.
...
ENDFORM.

 

USING과 CHAINGING이라는 addition을 Subroutine을 위한 Parameter Interface로 정의할 수 있씁니다. Parameter Interfcace는 개발자에게 Subroutine에게 데이터를 전달 할 수 있도록 하고,  FORM 문에서 직접 변수를 선언하여 정의됩니다 : 이 변수들은 Formal Parameter라고 불립닌다.

Formal Parameter는 PERFORM 문을 통해 유지되는 매개변수(Parameter)를 채우는데 사용됩니다. 이러한 매개변수를 Actual Parameter라고 합니다.

Parameter는 프로그램 내에서의 local data type과 ABAP Data Dictionary의 global data type 둘 다를 언급하여 정의될 수 있습니다. 정의된 Parameter는 Subroutine의 지역 변수로 존재하며, Subroutine이 호출될 때 생성되고 종료될 때 해제됩니다. 만약 Subroutine이 FORM문에 정의된 변수들을 가지고 있다고 하면, PERFORM 구문은 이 변수 각각에 순서에 맞에 값을 전달해야만 합니다.

FORM문 단계에서 나타는 Parameter 이름은 Formal Parameters라고 불리우고, PERFORM 단계에서 보여지는 Parameters들은 Actual Parameter라고 불립니다. Actual Parameter와 Formal Parameter의 수는 항상 같아야 합니다.예를 들어, 만약 Subroutine이 세 개의 Formal Parameter을 가지고 있다면, PERFORM 구문을 사용하여 Subroutine이 호출될 때, 세 개의 Actual Parameter가 전달 될 것이라고 예상할 수 있습니다. 

아래 예시를 보면, Actual Parameter f1, f2, f3가 있고 Formal Parameter인 p1, p2, p3가 있는 것을 볼 수 있습니다.

PERFORM abc USING f1 f2 f3.

FORM abc USING p1 p2 p3.

ENDFORM.

formal Paramter를 정의할 때는, Formal Type는 type이 있을수도(typed) 없을 수도(untyped) 있습니다. 만약 Formal Parmeter가 Data Type를 언급했다면, 그것은 typed formal parameter라고 불리웁니다. 반대로, Data Type을 언급하지 않았다면 untyped formal parameter라고 부를 수 있습니다. 위 코드에서 보면, 모든 Parameter들은 Untyped 입니다.

Untyped Formal Parameter가 사용될 때에는, 어떠한 유형의 Type과 길이를 Actual Parameter을 통해 Formal Parameter에게 전달 할 수 있습니다. 이와 같은 경우에, Formal Paramter는 Actual Parameter의 속성을 사용한다고 이해하면 됩니다.

예를 들어, 4-byte의 정수(intiger)를 untyped formal parameter인 p1에게 전달한다고 하면, p1은 4-byte의 intiger가 될 것입니다. 만약 Length가 3인 Character을 전달한다고 한다면, formal parameter은 CHAR3이 될 것입니다. Untyped Parameter의 Data Type와 Length는 실행동안(Runtime 중에) Actual Parameter가 전달될 때 결정될 것입니다.

Generic types이 도입된 이후에는, untyped formal paramete를 사용하는 것은 유연성이 있을 수는 있지만 더 이상 적절하지 않은 것으로 간주됩니다. Generic types은 개발자가 동적으로 Data Object의 타이핑(타입을 정하는 것)을 동적으로 할당할 수 있습니다. 해당 내용은 아래 글을 비롯하여 동적 프로그래밍 카테고리를 가면 자세하게 정리해 두었습니다.

2023.03.07 - [ABAP 프로그래밍 개념/ABAP Dynamic Programming(동적 프로그래밍)] - 1. ABAP 동적 프로그래밍 Overview

 

1. ABAP 동적 프로그래밍 Overview

소프트웨어는 어떠한 문제를 해결하기 위해 만들어지거나 유저들에게 일상의 할동에 도움을 주기 위해 만듭니다. 대부분의 경우, 문제를 사전에 알기 때문에, 어플리케이션의 설계와 개발을 당

abapta0903.tistory.com

FORM exercise using u1 type t.

ENDFORM.

위 예시는 typed parameter입니다.

Typed Parameter을 사용하여, Data Type을 정적으로 정의할 수 있습니다. Typed Parameter는 Untyped Parameter보다 더 유용한 것으로 고려됩니다. 런타임 중에 Data Type을 동적으로 결정해야 하는 경우에는 Generic types을 사용해야 합니다. 이러한 경우에는, SAP 타입을 Untyped Parameter의 사용을 지양합니다.

아래는 Typed Formal Parameter를 사용해서 작업해야 될 포인트들 입니다.

  • FORM 문의 구문은 약간 제한적이므로 elementary 유형을 사용할 때 length addition를 사용하여 길이를 정할 수 없고 데이터 유형만 FORM 문에서 지정할 수 있습니다. 이러한 이유로, SAP는 Formal Parameter를 프로그램 내에서  User-defined global Type이나 ABAP Data Dictionary에서 가져온 데이터 타입을 참조하여 형식 지정하는 것을 권장합니다.
  • Actual Parameter의 Type과 Length는 반드시 Formal Parameter와 맞는 것이 좋습니다(매칭되어야합니다). 일반적으로 데이터 유형을 다른 데이터 유형으로 전달하지 않는 것이 좋습니다.
  • 잘못된 Typed Parameter에 잘못된 Data Type과 Length를 전달하는 것은 Syntax Error를 불러일으킬 수 있습니다.
  • Typed Formal Parameter 런타임에서 데이터 타입을 결정하여 메모리를 할당할 필요가 없기 때문에 더 효율적입니다.
  • Typed Formal Parameter은 Syntax Checker(문법 검사기)가 호환되지 않는 매개변수를 전달하는 것을 방지하여 코딩 오류를 예방하는 데 도움이 됩니다.
  • Typed Formal Parameter는 또한 런타임 에러를 방지하는데 도움이 됩니다. 만약 Charater 값이 Untyped formal Parameter로 전달되어, 숫자 연산을 수행한다면, 런타임 에러가 발생할 것입니다.
  • Structure(구조체)를 전달할 때는 항상 Typed Parameter를 사용해야합니다. 만약 Structure가 Untyped Formal Parameter로 전달되었다면, 시스템이 Structure로 넘어온 Formal Parameter를 오직 프로그램 실행 때만 인지하기 때문에 정적으로 Structure의 필드에 접근하지 못할 것입니다.

Passing Parameters to Subroutines


Parameter를 Subroutine에 전달하는 방식에는 세 가지 다른 방법이 있습니다.

  • Pass By Reference : 참조에 의해 전달되는 Parameters.
  • Pass By Value : 값을 전달하는 Input Parameters
  • Pass By Value and Result : 값을 전달하는 Output Parameters

FORM 구문에서 사용되는 USING과 CHANGING additions 들은 Parameter Interface를 정의하고, 어떻게 Parameter들이 전달될지를 결정합니다. 같은 additions들은 또한 PERFORM문에서 똑같이 사용되어 Actual Parameter를 전달하는데 사용되기는 하지만 순전히 문서화 목적으로 사용됩니다. 이 경우 Prrameter가 전달되는 방식에 영향을 미치지 않습니다.

addition의 순서는 정해져 있습니다. USING이 먼저오고, CHANGING이 따라와야 합니다. 둘 중 하나만 사용해도되고 둘 다 사용해도 됩니다. 

PERFORM abc USING f1 f2 CHANGING f3.

실제 Parameter의 값이 Subroutine의 호출 이후 변경되는지 아닌지 여부에 따라 매개변수는 USING 또는 CHANGING 하에 나열됩니다. 만약, Actual Parameter가 Subroutine 호출 이후에 변한다면, 해당 Parameter는 CHANGING 하에 사용해야하고, 변하지 않는다면 USING 하에서 사용되어야 합니다.

아래 코드는 USING addition을 사용한 예시입니다.

DATA f1 TYPE c VALUE 'A'.

PERFORM abc USING f1.

FORM abc USING p1.
 WRITE p1.
ENDFORM.

 

Subroutine abc에서 Actual Parameter f1는 Formal Parameter p1으로 전달됩니다. Actual Parameter인 f1의 값이 Subroutine 호출뒤에도 바뀌지 않기 떄문에, 우리는 PERFORM 문에서 USING이란 addition을 사용합니다.

DATA f1 TYPE c VALUE 'A'.
PERFORM abc CHANGING f1.

FORM abc USING p1.
 P1 = 'B'.
ENDFORM.

위 예시는 Actual Parameter f1의 값이 A에서 B로 바뀌기 때문에 PERFORM문에서 CHANGE라는 addition을 사용해야합니다. USING"또는 CHANGING addition의 사용은 실제로 Actual Parameter가 Subroutine 내에서 사용되는지 아니면 변경되는지를 다른 개발자들이 코드를 볼 때 식별하는 데 도움을 주기 위한 것입니다. USING 대신 CHANGING을 사용하고 그 반대의 경우여도 실제 결과는 달라지지 않습니다.

 

Paramters Passed by Reference

FORM 문에서 문법은 어떻게 Parameters가 전달되는지에 달려있습니다. Parameters가 Pass by Reference로 전달될 때, Formal Parameter는 Actual Parameter과 같은 메모리 위치를 바라봅니다. 다른말로 하면, 새로운 메모리가 Formal Parameter를 위해 생성되지 않고, 대신에, Pointer가 생성되어 Actual Parameter의 메모리 위치를 가리킵니다. Parameter를 전달하는 방식은 특이 Internal Table을 전달할 때 유용한데, 데이터의 복사가 이루어지지 않고 추가적인 메모리가 사용되지 않기 때문입니다.

Parameter가 FORM 구문에서 USING 혹은 CHANGING과 함께 정의되었을 때, 디폴트로 Pass by Reference로 전달됩니다. 몇가지 예시를 확입해봅시다.

FORM abc USING p1.
ENDFORM.
FORM abc CHANGING p1.
ENDFORM.
FORM abc USING p1 CHANGING p2.
ENDFORM.

Parameter들이 Pass by Reference로 저달 될 때, Acutal Paramter의 값은 같은 메로리를 바라보기 때문에, Subroutine에서 Formal Parameter의 값이 바뀌는 순간 즉시 바뀌게됩니다. 그렇기 때문에 원 데이터(Actual Paramter의 처음 전달되는 값)이 바뀔 수 있기 때문에 주의해서 프로그래밍을 해야합니다. 프로그램 로직의 나중에 프로그램상 로직의 조건이 충족되지 않게되어서 Subroutine을 종료하고자 할 때, 원래의 데이터에 대한 변경을 되돌릴 수 없습니다.

Parameter가 Pass by Reference로 전달될 때, USING과 CHANGING이 동등하고 오로치 차이는 문서적인 관점으로서, USING은 Input Parameter(Subroutine에서 바뀌지 않는 것)로서, Chaning은 Output Parameter(Subroutine에서 바뀌는 것)로서 사용하는 것이 좋습니다.

만약 Actual Paramter의 값이 자동적으로 바뀌는 것을 원하지 않는다면, Pass By Reference가 아닌 Pass by Value를 사용해야 합니다.

Input Parameters That Pass Values

Parameter가 VALUE라는 adttion이 USING 뒤에 쓰일 때, Pass by Value로 전달됩니다.

FORM abc USING VALUE (p1)
               VALUE (p2).
ENDFORM.

FORM xyz USING VALUE (p1) CHANGING p2.
ENDFORM.

위 코드를 보면, Parameter p1과 p2는 Subroutine abc에서 Pass by Value로 전달되고 있는 반면, xyz에서는 p1은 Pass by Value로 p2는 Pass by Reference로 전달됩니다. SYNTAX에 USING addition를 한 번만 사용하고, Pass by Value으로 전달해야하는 각 Paramter 앞에는 VALUE addition를 사용합니다

Parameter가 Pass by Value로 전달될 때, Actual Paramter과 Formal Paramter는 그들의 자신들의 메모리 영역을 점유합니다. Subroutine을 호출할 때, Actual Parameter의 값은 Formal Paratmer로 전달되는데,  Actual Parameter의 원래 값의 복사한 것을 전달합니다. 만약 Formal Patameter의 값이 변했다 하더라도, Actual Paratmer에는 영향이 없습니다. 특히 큰 데이터의 Internal Table을 전달하는 것과 같은 경우, Pass by Value로 Table을 Paramter로 전달하는 것은 피하는 것이 좋습니다. 그러나, Pass by Value는 원래 값이 어떠한 경우라도 바뀌지 않기 때문에 걱정없이 Originin Data의 카피 데이터를 통해 데 작업할 수 있다는 장점이 있습니다. 

Output Parameters That Pass Values

만약 Output Parameters의 복사된 데이터와 작업하고 싶을때, CHANGING 문에 VALUE라는 addition을 붙여서 전달하면 됩니다. 이렇게 되면, 새로운 메모리가 Formal Parameter를 위해 생성되고, Actual Parameter의 실제 값은 Formal Parameter로 복사되어 전달됩니다. 그러나, Input Parameter를 Pass by Value로 전달하는 것과의 차이점은, Actual Paramter는 Subroutine 호출 이후에 바뀔 것이라는 것입니다. Formal Parameter의 내용은 ENDFORM이 실행되거나 CHECK 또는 EXIT 문으로 Subroutine이 종료될 때 Actual Parameter로 복사됩니다.

만약 Subroutine이 오류 메시지와 함께 조기 종료된다면 Actual Parameter은  그대로 유지됩니다. 이는 pass by reference의 경우와는 달리 Actual Parameter가 즉시 변경되지 않고 모든 조건이 충족될 때만 Actual Parameter 변경할 수 있도록 합니다. Paratmer를 Pass by Value를 통해 값과 결과를 전달하는 예시는 아래와 같습니다.

FORM abc CHANGING VALUE (p1)
                  VALUE (p2).
ENDFORM.

FORM xyz USING VALUE (p1)
         CHANGING VALUE (p2).
ENDFORM.

위 예에서, Paramter pr과 p2는 Subroutine abc에 Pass by Value로 전달되고 둘 다 Output Paramter 입니다. Subroutine xyz에서, p1은 Input Parameter이고 Pass by Value로 전달되고 있고 p2는 Output Parameter로 Pass by Value로 전달되고 있습니다. SYNTAX에 Changing addition를 한 번만 사용하고, Pass by Value으로 전달해야하는 각 Paramter 앞에는 VALUE addition를 사용합니다.

 

Passing Internal Table to Subroutines

Subroutine에 필드들은 전달하는 것은 쉽습니다. 그러나 Internal Table을 전달할 떄는 몇 가지 주의사항이 있습니다. Internal Table을  USING, CHANGING 구문을 사용하거나 TABLES라는 키워드를 사용하면 됩니다.

FORM abc TABLES pt_sflight.
ENDFORM.

 TABLES라는 Keyword를 사용하여 Internal Table과 그것의 Header Line(만약 Actual Parameter가 Header Line이 있는 Internal Table일 때)을 둘 다 전달할 수 있습니다. 그러나, Tables 구문은 구식이라, 추천하지 않습니다.

항상 Internal Tables를 USING이나 CHANGING 구문을 써서 전달하는 것이 좋습니다. 부가적으로 항상 Internal Table을 전달할 때는 Typed Parameter을 사용해야합니다. Syntax Check는 형식 매개변수에 LOOP나 READ같이

만약 Formal Parameter에 Internal Table에 특화된 구문인 LOOP나 READ와 같은 구문이 사용된다면, 구문 검사기에서 오류가 발생할 수 있습니다. 이것은 Untyped Formal Paramter을 사용할때 Formal Parateter을 Internal Table로 인식할 수 있는 방법이 없기 때문입니다. Formal Parameter를 Type을 가지게 하기 위해서, Formal Parameter에 Structure나 Table Type을 명시해줘야 합니다. Internal Table의 형식을 선언하는 구문은 DATA 키워드와 유사합니다. Structure을 언급할 때에는, TYPE TABLE OF 구문을 아래 예시처럼 사용합니다.

TYPES: BEGIN OF ty_makt,
        matnr type matnr,
       END OF ty_makt.
       
FORM abc USING pt_makt TYPE STANDARD TABLE OF ty_makt.

ENDFORM.

Table Type은 Internal Table을 위한 Data Type입니다. 일반적으로 Structure Type으로 Structure을 선언하는 것과 Table Type으로 Internal Table을 선언하는 것과 비슷합니다. Type라는 addition을 사용해여 Data Object가 테이블 유형으로 참조되면 Internal Table이 생성됩니다. 테이블 유형은 ABAP 프로그램 내에서 지역적으로 정의될 수도 있고, ABAP Data Dictionary에서 전역적으로 정의될 수도 있습니다. Table Type을 지역적으로 선언하기 위해선, Occurs 절을 TYPES 키워드와 함께 아래와 같이 사용합니다.

"Table Type 사용하여 INTERNAL TABLE 정의"
TYPES: BEGIN OF ty_makt,
        matnr type matnr,
       END OF ty_makt.
       
TYPES: tbty_makt TYPE ty_makt OCCURS 0.

FORM abc USING pt_makt TYPE tbty_makt.
ENDFORM.

Table Type은 Function Module과 Method에서 더 유용하며, TYPE이나 LIKE 문에 제한되어 사용되며 TABLE OF 문 사용이 허용되지 않습니다.

또한 Formal Parameter을 Like 문을 사용하여 Global하게 선언된 Internal Table을 언급하여 선언할 수도 있습니다.

TYPES: BEGIN OF ty_makt,
        matnr type matnr,
END OF ty_makt.

DATA: it_makt TYPE STANDARD TABLE OF ty_makt.

FORM abc USING pt_makt LIKE it_makt.
ENDFORM.

 

Table Types는 ABAP Data Dictionary에 전역적으로 정의될 수 있습니다. Global table Type을 만들기 위해서는 아래와 같은 단계를 따릅니다.

1. SE11을 실행시키고, Data Type 라디오 버튼을 클릭합니다. Table Type으로 사용할 이름을 입력하고 Create 버튼을 누릅니다. Table Type의 이름은 Customer Nameplace를 가져야하기 때문에, Y나 Z로 시작합니다.

2. Modal Dialog Box가 나타나면, Table Type 라디오 버튼을 선택하고 OK 버튼을 누른다.

3. 다음 화면에서, Short Text에서 간략한 설명을 입력하고, Line Type 필드에 Structure 명이나 Table 명을 입력합니다. 여기서 입력한 Structure나 Table에 따라 구성요소를 형성할 것입니다.

4. 활성화를 시키면 Table Type이 시스템 전반에 활성화 됩니다.

반응형