ABAP開發(fā)規(guī)范
目錄
1 ABAP對象命名規(guī)范 6
1.1 開發(fā)類 6
1.2 程序名 6
1.3 數(shù)據(jù)字典 7
1.3.1 表/結(jié)構(gòu)/數(shù)據(jù)元素/域7
1.3.2 表類型 7
1.3.3 范圍表類型 7
1.3.4 搜索幫助 7
1.3.5 鎖對象 7
1.4 函數(shù)組及函數(shù)模塊 8
1.4.1 函數(shù)組 8
1.4.2 函數(shù)模塊 8
1.5 BADI實施 8
1.6 消息類 9
1.7 類 9
1.8 SMARTFORM 9
1.9 自定義權(quán)限對象 9
1.10 Enhancement project9
1.11 Web Service命名9
1.12 Proxy 命名 10
2 通用ABAP代碼規(guī)范 11
2.1 代碼格式 11
2.1.1 Pretty Printer11
2.1.2 Spacing 11
2.1.3 代碼行 12
2.1.4 代碼注釋 13
2.2 程序變量 14
2.2.1 變量使用說明 14
2.2.2 命名規(guī)范 14
2.2.3 常量 15
2.2.4 全局變量 17
2.2.5 內(nèi)表/結(jié)構(gòu) 18
2.2.6 文本變量 20
2.3 常用語句格式 21
2.3.1 Message 21
2.3.2 Call function21
2.3.3 Perform 22
2.3.4 Select 22
2.3.5 IF 23
2.3.6 CHECK 24
2.3.7 LOOP 25
2.3.8 READ 25
2.3.9 WHILE 25
2.3.10 DO 26
2.3.11 CASE 26
2.3.12 CONCATENATE27
3 報表程序規(guī)范 29
3.1 程序結(jié)構(gòu) 29
3.1.1 數(shù)據(jù)初始化子程序31
3.1.2 數(shù)據(jù)存取子程序 32
3.1.3 數(shù)據(jù)處理子程序 32
3.1.4 數(shù)據(jù)組合子程序 33
3.1.5 數(shù)據(jù)輸出子程序 35
4 子程序規(guī)范 36
4.1 模塊化代碼 36
4.2 參數(shù) 37
4.2.1 參數(shù)命名 37
4.2.2 參數(shù)類型 37
4.2.3 Table參數(shù) 37
4.2.4 參數(shù)個數(shù)要求 38
4.2.5 參數(shù)對齊 40
4.3 子程序結(jié)構(gòu) 40
4.4 Perform語句 41
4.5 子程序注釋 42
5 功能模塊規(guī)范 43
5.1 函數(shù)模塊結(jié)構(gòu) 43
5.2 函數(shù)返回值 43
5.3 函數(shù)調(diào)用 43
6 屏幕對話程序規(guī)范 45
6.1 屏幕邏輯流結(jié)構(gòu) 45
6.2 PAI/PBO/POV 模塊46
6.2.1 User-command模塊47
7 BADI增強規(guī)范 49
8 CMOD增強規(guī)范 51
9 BTE增強規(guī)范 52
10 程序性能相關(guān)代碼規(guī)范 53
10.1 SQL語句 53
10.2 內(nèi)表操作 58
10.3 其他語句 66
10.3.1 CASE語句 66
10.3.2 WHILE語句67
10.3.3 比較語句 67
附錄 68
1.1 SAP業(yè)務(wù)模塊命名表68
1.2 數(shù)據(jù)字典對象類型命名表68
版本控制
版本
更改日期
更改人
更改內(nèi)容
1.0.
2011/XX/XX
創(chuàng)建文檔
ABAP對象命名規(guī)范
開發(fā)類
Z<XX>_<Short text>
<XX>-業(yè)務(wù)模塊,見附錄1
<Short text>-簡短描述,英文
程序名
Z<XXY>_<Short text>
<XX>-業(yè)務(wù)模塊,見附錄1
<Y>-程序類型代碼
<Short text>-簡短描述,英文
<Y>
程序類型代碼
R
報表程序
P
對話程序
F
FORM/SMARTFORM打印程序
B
后臺作業(yè)程序
I
公共Include程序
注:用于特定程序的include程序按以下方式命名:<主程序名>_<Xnn>, nn-兩位流水碼
<X>
include類型
F
子程序
I
PAI
O
PBO
數(shù)據(jù)字典
表/結(jié)構(gòu)/數(shù)據(jù)元素/域
Z<TXX>_<Short text>
<T>-數(shù)據(jù)字典對象類型,參見附表2
<XX>-業(yè)務(wù)模塊,見附錄1
<Short text>-簡短描述,英文
表類型
[Z_]<structure >_T
[Z_]-如果< structure >名稱以Z開頭,則可省略
<structure>-使用的結(jié)構(gòu)名
范圍表類型
[Z_]<dataelement>_T
[Z_]-如果<dataelement>名稱以Z開頭,則可省略
<dataelement>-使用的數(shù)據(jù)元素名
搜索幫助
Z<XX>_SH_<Short text>
<XX>-業(yè)務(wù)模塊,見附錄1
<Short text>-簡短描述,英文
鎖對象
E[Z] <tablename>
[Z]-如果<tablename>名稱以Z開頭,則可省略
<tablename>-表名
函數(shù)組及函數(shù)模塊
函數(shù)組
Z<XX>_<nn>
<XX>-業(yè)務(wù)模塊,見附錄1
<nn>-兩位流水碼
函數(shù)模塊
<FunctionGroup>_<Short text>
<FunctionGroup>-函數(shù)模塊所在的函數(shù)組名
< Short text >-函數(shù)基本功能的短文本
BADI實施
a) Custom Business Add-in
Z<XX>_BADI_< Short text >
<XX>-業(yè)務(wù)模塊,見附錄1
< Short text >-BADI 定義的名稱
b) Custom Business Add-in Implementation
Z<XX>_BADIM_< Short text >
<XX>-業(yè)務(wù)模塊,見附錄1
< Short text >-BADI 定義的名稱
c) SAP Business Add-in Implementation
Z<XX>_IMPL_< Short text >
<XX>-業(yè)務(wù)模塊,見附錄1
< Short text >-BADI 定義的名稱
d) SAP BADI Method
< Short text >-自由定義,但有意義,簡單描述該方法實現(xiàn)的功能
消息類
Z<XX>_<nn>
<XX>-業(yè)務(wù)模塊,見附錄1
< Short text >-簡短描述,英文
類
Z<XX>_<Short text>
<XX>-業(yè)務(wù)模塊,見附錄1
<Short text>-簡短描述,英文
SMARTFORM
[Z]<Reportname>_<Short text>
[Z]-如果<Reportname>名稱以Z開頭,則可省略
<Short text>-簡短描述,英文
自定義權(quán)限對象
Z<XX>_<Short text>
<XX>-業(yè)務(wù)模塊,見附錄1
<Short text>-簡短描述,英文
Enhancement project
Z<XX><nnnn>
<XX>-業(yè)務(wù)模塊,見附錄1
<nnnn>-四位流水碼
Web Service命名
ZWS<XX>_<Short text>
<XX>-業(yè)務(wù)模塊,見附錄1
<Short text>-簡短描述,英文
Proxy 命名
Z<XX>_<Short text>
<XX>-業(yè)務(wù)模塊,見附錄1
<Short text>-簡短描述,英文
通用ABAP代碼規(guī)范
代碼格式
Pretty Printer
所有程序代碼應(yīng)使用pretty printer功能進行規(guī)范,包含:代碼縮進;關(guān)鍵字大寫,其余小寫。
Unacceptable:
form f_list_output.
data: wa_output type ty_output.
if i_output[] is initial.
message e101(zcs01).
endif.
loop at i_output into wa_output.
write: / wa_output-equnr.
endloop.
endform.
Acceptable:
FORM f_list_output.
DATA: wa_output TYPE ty_output. 'work area for output
IF i_output[] IS INITIAL.
MESSAGE e101(zcs01). 'error no data
ENDIF.
LOOP AT i_output INTO wa_output.
WRITE: / wa_output-equnr.
ENDLOOP.
ENDFORM. 'f_list_output
Spacing
在代碼行中按照代碼塊適當(dāng)增加空行,以增加代碼的可讀性:
Unacceptable:
form sub_display_print_document tables pi_ropbel type ty_tab_opbel.
data: l_type type c. “print type
data: lw_opbel type ty_opbel. “Loop work area
l_type = c_print_document.
format color col_blue on.
write: / text-h01. “'Print documents (click to view)'.
format color off.
if not pi_ropbel[] is initial.
loop at pi_opbel_disp into lw_opbel_disp.
write: / lw_opbel-partner.
endloop.
endif.
clear l_type.
endform. ' display_print_document
Acceptable:
FORM sub_display_print_document TABLES pi_ropbel TYPE ty_tab_opbel.
DATA: l_type TYPE c. 'print type
DATA: lw_opbel TYPE ty_opbel. 'Loop work area
l_type = c_print_document.
FORMAT COLOR COL_GROUP ON.
WRITE: / text-h01. ''Print documents (click to view)'.
FORMAT COLOR OFF.
IF NOT pi_ropbel[] IS INITIAL.
LOOP AT pi_opbel_disp INTO lw_opbel_disp.
WRITE: / lw_opbel-partner.
ENDLOOP.
ENDIF.
CLEAR l_type.
ENDFORM. ' display_print_document
代碼行
每一行代碼僅允許有一個語句
Unacceptable:
Sort i_tab1 by contract. Sort i_tab2 by anlage.
Clear: lwa_tab1, lwa_tab2.
Acceptable:
Sort i_tab1 by contract.
Sort i_tab2 by anlage.
Clear: lwa_tab1, “Clear work areas for processing
lwa_tab2. “them in the loop.
代碼注釋
代碼行中的注釋,應(yīng)該與代碼行對齊。
Unacceptable:
form f_output_data.
*Print the headings
perform f_write_column_heading.
*** Loop at output table
Loop at i_output into w_output.
*Check if the document is reverse.
If w_output-reverse = c_reversed“Reversed state
and w_output-simulated = c_unsimluated. ”simulated
Endif.
Endloop.
Endform.
Acceptable:
form f_output_data.
* Print the headings
perform f_write_column_heading.
* Loop at output table
Loop at i_output into w_output.
* Check if the document is reverse.
If w_output-reverse = c_reversed “Reversed state
and w_output-simulated = c_unsimluated. ”simulated
Endif.
Endloop.
Endform.
程序變量
變量使用說明
基本原則:程序中盡量減少全局變量的使用,如無必要均應(yīng)使用局部變量,以保證程序中各代碼段的相對獨立性。全局變量一般用于:跨子程序使用的內(nèi)表、常量、屏幕變量等。
變量聲明:局部變量聲明語句必需放在子程序的開始位置;不允許在一行代碼中定義兩個或以上的變量;在同一個data語句中的所有變量,應(yīng)該讓變量名對齊、type〔like〕對齊。
變量使用:原則上每個變量僅為一種用途使用,盡量避免一個變量被當(dāng)作不同的含義重復(fù)使用。
Unacceptable:
data: l_cnt type i, l_txt_prefix(10) type c.
data : l_curr_div like eanl-sparte.
Acceptable:
data: l_prefix(3) type c. “Prefix of operand
l_cnt type i, “Count of material docs.
l_curr_div like eanl-sparte. “Current division
命名規(guī)范
變量:<A><B>_<description>
<A>-代表變量的使用范圍
<B>-代表變量類別
<A>
使用范圍
G
全局變量
L
局部變量
C
全局常量
I
形式參數(shù)-傳入
E
形式參數(shù)-傳出
<B>
變量類別
V
簡單變量
T
內(nèi)表變量
S
結(jié)構(gòu)變量
F
flag
R
range
類型:TY_<description>
Example:
TYPES: BEGIN OF ty_po_header,
Ebeln TYPE ekko-ebeln,“PO NUMBER
Lifnr TYPE ekko-lifnr,“VENDOR ID
END OF ty_po_header.
CONSTANTS: BEGIN OF cs_po_type,
normal TYPE ekko-bsart VALUE ‘PO1’,
special TYPE ekko-bsart VALUE ‘PO2’,
END OF cs_po_type.
DATA: gt_po_header TYPE TABLE OF ty_po_header,
Gs_po_header TYPE ty_po_header.
DATA: gf_error(1) TYPE c,
Gv_datum TYPE sy-datum.
常量
常量組
如果程序中定義了一組相關(guān)的常量(如下例),必須要要注意常量的命名。
Example:
Constants:
C_periodic_mr_reason like eablg-ablesgr value ‘01’,
C_check_mr_reason like eablg-ablesgr value ‘10’.
(以上命名方式是不符合要求的)
常量組的命名方式必須采用以下兩種方式之一:
定義為結(jié)構(gòu),結(jié)構(gòu)中包含所有相關(guān)常量:
Example:
constants: begin of cx_mrr
periodic like eablg-ablesgr value ‘01’, “Periodic
check like eablg-ablesgr value ‘10’, “Check
End of cx_mrr.
這種常量的使用和普通的結(jié)構(gòu)用法相同:
lwa_eablg-ablesgr = cx_mrr-periodic
使用相同的前綴:
Example:
constants:
c_mrr_periodic like eablg-ablesgr value ‘01’,
c_mrr_check like eablg-ablesgr value ‘10’.
constants:
c_fi_doc_inv(2) type c value ‘IN’,
c_fi_doc_secdep(2) type c value ‘SD’.
常量名稱
常量命名時不應(yīng)該使用常量值作為其名稱的一部分,而應(yīng)該使用常量值所代表的業(yè)務(wù)含義或者是其在程序中的用途。
Unacceptable:
constants:
c_9(2) type c value ‘9’,
c_one(1) type c value ‘1’.
Acceptable:
constants:
c_status_cleared(2) type c value ‘9’,
c_status_active(1) type c value ‘1’.
常量聲明
所有的常量均應(yīng)定義為程序中的全局變量,不允許在子程序中定義局部常量。
全局變量
最小化全局變量的使用
為了使程序代碼模塊化,降低各模塊之間的耦合度,必須盡量減少程序中使用的全局變量,如無必要盡量使用局部變量。
以下類型的變量可以定義為全局變量:
內(nèi)表(跨子程序使用)
計數(shù)器
標(biāo)識
常量(必須定義為全局)
結(jié)構(gòu)
范圍變量
類型定義(必須定義為全局)
以下類型的變量不能定義為全局變量:
工作區(qū)(如果需要,工作區(qū)應(yīng)該定義為子程序參數(shù)進行傳遞)
變量組定義為結(jié)構(gòu)
如果需要使用一組相關(guān)的全局變量,建議定義成一個全局的結(jié)構(gòu),而不是分別定義每個變量。
Unacceptable:
data: g_cnt_billdocs type i,
g_cnt_invoices type i,
g_cnt_contracts type i.
Acceptable:
types: begin of ty_cnt,
billdocs type i,“Number of billing documents
invoices type i,“Number of unsimulated invoices
contracts type i.“Number of related contracts
end of ty_cnt.
...
data: x_cnt type ty_cnt. “Structure to keep track of counters
使用包含(include)
如果程序中定義全局變量的代碼超過100行(包括全局變量、類型、常量以及相關(guān)的注釋),必須單獨建立一個include,將所有的變量聲明語句從主程序中剝離出來,放到該包含程序中。
內(nèi)表/結(jié)構(gòu)
內(nèi)表定義
使用類型聲明內(nèi)表
內(nèi)表的定義必須使用表類型。
Unacceptable:
data: begin of i_mrtab occurs 0,
ablbelnr like eabl-ablbelnr,
adatsoll like eabl-adatsoll,
ablstat like eabl-ablstat,
end of i_mrtab.
Acceptable:
types: begin of ty_mrtab,
ablbelnr like eabl-ablbelnr,“MR Doc number
adatsoll like eabl-adatsoll,“Schedule MR Date
ablstat like eabl-ablstat,“MR Status
end of ty_mrtab.
types: ty_tab_mrtab type ty_mrtab occurs 0.
...
data: i_mrtab type ty_tab_mrtab.
對齊與注釋
結(jié)構(gòu)類型中定義的字段必須要按以下格式對齊;如果使用標(biāo)準(zhǔn)表字段,則字段名應(yīng)該和標(biāo)準(zhǔn)表字段一致;結(jié)構(gòu)類型中的字段后都應(yīng)該有相應(yīng)的文本注釋。
Unacceptable:
types: begin of ty_mrtab,
mrdoc like eabl-ablbelnr,
date like eabl-adatsoll,
ablstat like eabl-ablstat,
end of ty_mrtab.
Acceptable:
(注意:字段對齊,字段名稱與表字段一致,字段后應(yīng)該有文本注釋)
types: begin of ty_mrtab,
ablbelnr like eabl-ablbelnr,“MR Doc number
adatsoll like eabl-adatsoll,“Schedule MR Date
ablstat like eabl-ablstat,“MR Status
end of ty_mrtab.
抬頭行(Header Line)
定義內(nèi)表時不能使用with header line定義其默認工作區(qū),工作區(qū)必須在各個子程序中單獨定義為局部變量。
Unacceptable:
data: i_mrtab type ty_tab_mrtab with header line.
Acceptable:
Form f_process_mr_data.
data: lwa_mr type ty_mrtab.“work area for i_mrtab
loop at i_mrtab into lwa_mr.
...
endloop.
Endform.
工作區(qū)
工作區(qū)不能定義為全局變量而應(yīng)該在各個子程序中定義為局部變量使用。如果必須在子程序間傳遞工作區(qū)內(nèi)容,則應(yīng)該為相關(guān)子程序定義形式參數(shù)來實現(xiàn)。
Form f_process_mr_data.
data: lwa_mr type ty_mrtab.“work area for i_mrtab
loop at i_mrtab into lwa_mr.
...
perform f_validate_mr using lwa_mr.
...
endloop.
Endform.
文本變量
所有文本均應(yīng)定位為文本元素(text element);如果不是必須,不允許在程序中使用文本硬代碼或者將文本定義為常量來使用。
Unacceptable:
write: ‘Purchase’.
Acceptable:
write: text-c01.“Purchase
定位文本元素時應(yīng)該使用合適的前綴;以下作為參考,可根據(jù)實際需要進行擴展。
Prefix
Description
Example
H
Header text
text-H01
C
Column heading
text-C01
E
Error text
text-E08
W
Warning text
text-W03
I
Information text
text-I19
S
Summary text
text-S02
常用語句格式
Message
Message語句應(yīng)該使用以下格式:
Message <message type>(<message class>) with <variable 1> <variable 2> etc.
Example:
message e304(ZCS01) with w_data-anlage w_data-device.
Call function
函數(shù)調(diào)用語句中,如果有不使用的參數(shù),請將這些行刪除而不要將這些行注釋在代碼中。同時,請注意所有的參數(shù)必須在代碼中對齊。
Unacceptable:
CALL FUNCTION 'BAPI_IDENTIFICATIONDETAILS_GET'
EXPORTING
BUSINESSPARTNER = W_EBILL_CA-GPART
TABLES
* IDENTIFICATIONDETAIL = I_BAPIBUS1006_ID_DETAILS
RETURN = I_BAPIRET2.
Acceptable:
CALL FUNCTION 'BAPI_IDENTIFICATIONDETAILS_GET'
EXPORTING
BUSINESSPARTNER = W_EBILL_CA-GPART
TABLES
RETURN = I_BAPIRET2.
(請注意,這里的所有參數(shù)都工整地對齊)
Perform
使用perform語句調(diào)用子程序時,參數(shù)必須要對齊,且每一個參數(shù)單獨一行,同時perform 語句及使用的參數(shù)必須有相應(yīng)的注釋。
Unacceptable:
perform f_delete_unused_bill_orders tables i_billorders using l_date.
Acceptable:
* Use the standard function to delete unused billing orders from the list
* in I_BILLORDERS
perform f_delete_unused_bill_orders tables i_billorders “Bill order list
using l_date.“Input date
Select
Select 語句結(jié)構(gòu)
Select語句必須使用以下示例中的結(jié)構(gòu):
Example 1:
SELECT logiknr 'logical device no.
equnr 'equipment number
bis 'to date
INTO wa_dev
FROM egerh
WHERE equnr EQ l_equip_no 'equipment number
AND bis GE p_rundate 'date ranges are in
AND ab LE p_rundate. 'todays date.
每一個字段必須分行列出,且對齊
每一個選取的字段必須有注釋
“AND” 關(guān)鍵字必須分行列出,且對齊
“EQ”, “GE” 等操作符必須對齊
不要使用“<>”, “=” 等操作符, 而應(yīng)該使用 “NE”, “EQ”, “GT’, “LT” 等相同含義的操作符
Example2:
SELECT ekpo~ebeln 'po number
ekpo~ebelp 'po item
ekbe~belnr 'invoice
INTO TABLE gt_ekbe
FROM ekko
INNER JOIN ekpo
ON ekko~ebeln EQ ekpo~ebeln
INNER JOIN ekbe
ON ekpo~ebeln EQ ekbe~ebeln
AND ekpo~ebelp EQ ekbe~ebelp
WHERE ekko~lifnr EQ iv_lifnr 'Vendor Number
AND ( ekko~bsart EQ cs_po_type-normal OR 'PO Normal type
ekko~bsart EQ cs_po_type-special ) 'PO Special type
AND ekbe~vgabe EQ cv_vgabe_invoice. 'invoice type
一般情況下不要使用表的別名,除非某個表在select語句中使用了兩次以上
Inner joins 必須按以上格式對齊
Select語句中的關(guān)鍵字必須按以上格式對齊
語句中的復(fù)雜條件語句必須按以上格式書寫
Select語句返回值
每一個select語句后面必須有相應(yīng)的語句檢查狀態(tài)變量SY-SUBRC。如果確實不需要檢查,那么必須有相應(yīng)的注釋說明原因。
IF
IF語句的結(jié)構(gòu)和對齊方式如下例:
Example:
IF w_tab-field1 EQ l_field1 AND
w_tab-field2 EQ l_field2 OR
( w_tab-field3 LE l_field3 AND
w_tab-field4 GE l_field4 ).
...
ENDIF.
(請注意語句中變量、操作符以及AND/OR的對齊方式)
CHECK
CHECK語句的結(jié)構(gòu)和對齊方式如下例:
Example:
CHECK w_tab1 IS NOT INITIAL AND
w_tab2 IS NOT INITIAL.
在可能的情況下,盡量使用CHECK語句從而避免IF語句的多層嵌套:
Example:
Unacceptable
LOOP AT gt_itab INTO ls_itab.
IF a EQ b.
IF c EQ d.
IF e EQ f.
......
ENDIF.
ELSE.
......
ENDIF.
ELSE.
CONTINUE.
ENDIF.
ENDLOOP.
Acceptable
LOOP AT gt_itab INTO ls_itab.
CHECK a EQ b.
IF c EQ d.
IF e EQ f.
......
ENDIF.
ELSE.
......
ENDIF.
ENDLOOP.
LOOP
LOOP語句的結(jié)構(gòu)和對齊方式如下例:
Example:
LOOP AT i_tab INTO w_tab WHERE value LE l_field
AND flag EQ space.
...
ENDLOOP.
(請注意以上變量和關(guān)鍵字的對齊方式)
READ
READ語句的結(jié)構(gòu)和對齊方式如下例:
Example:
READ TABLE i_tab WITH KEY key1 = l_key1_value
key2 = l_key2_value
TRANSPORTING NO FIELDS
BINARY SEARCH.
(請注意以上變量和關(guān)鍵字的對齊方式)
WHILE
WHILE語句的結(jié)構(gòu)和對齊方式如下例:
Example:
WHILE l_index1 LE l_index2
AND l_index3 GE l_index4.
...
ENDWHILE.
(請注意以上變量和關(guān)鍵字的對齊方式)
DO
DO語句的結(jié)構(gòu)和對齊方式如下例:
Example:
do l_count times
...
enddo.
CASE
CASE語句的結(jié)構(gòu)和對齊方式如下例:
Example:
case wa_discon-status.
when c_discstat_complete.
...
when c_discstat_inprogress.
...
when c_discstat_start or c_discstat_onhold.
...
endcase.
如果IF..ELSE語句中比較的變量相同,那么應(yīng)該始終使用CASE語句而不是IF語句。在每個WHEN代碼區(qū)域中,不允許包含復(fù)雜的業(yè)務(wù)邏輯處理,而應(yīng)該將這些業(yè)務(wù)邏輯的處理封裝到子程序中,通過perform 語句調(diào)用。
Unacceptable
case wa_discon-status.
when c_discstat_complete.
loop at i_disconn into w_disc.
if w_disc-ab < g_sysdate.
...
endif.
read table i_tab with key field = w_disc-vkont.
...
endloop.
when ...
...
endcase.
Acceptable
case wa_discon-status.
when c_discstat_complete.
perform f_check_disconn_data.
when ...
...
endcase.
form f_check_disconn_data.
loop at i_disconn into w_disc.
if w_disc-ab < g_sysdate.
...
endif.
read table i_tab with key field = w_disc-vkont.
...
endloop.
endform.
CONCATENATE
CONCATENATE語句的結(jié)構(gòu)和對齊方式如下例:
Example:
CONCATENATE l_title 'bp salutation (mr./mrs. etc)
l_firstname 'bp first name
l_lastname 'bp last name
INTO l_output_field
SEPARATED BY l_separator.
(請注意以上變量和關(guān)鍵字的對齊方式,以及相應(yīng)的注釋)
報表程序規(guī)范
程序結(jié)構(gòu)
所有可執(zhí)行程序應(yīng)該具有以下類似結(jié)構(gòu):
*&---------------------------------------------------------------------*
*& Report
*&---------------------------------------------------------------------*
*&---------------------------------------------------------------------*
*& Responsibility
*&---------------------------------------------------------------------*
* Program Name:
* Date written:
* Author's name:
* Last update:
* Program title:
* Project Name:
* Version:
*&---------------------------------------------------------------------*
* Description: (Incl. Related Function Area and System)
*&---------------------------------------------------------------------*
*
*&---------------------------------------------------------------------*
* Change History
*&---------------------------------------------------------------------*
* Date | Programmer | Corr. # | Description
* | | |
* | | |
*&---------------------------------------------------------------------*
REPORT MESSAGE-ID xx NO STANDARD PAGE HEADING LINE-SIZE 150.
TABLES:
*&---------------------------------------------------------------------*
* TYPES
*&---------------------------------------------------------------------*
*&---------------------------------------------------------------------*
* CONSTANTS
*&---------------------------------------------------------------------*
*&---------------------------------------------------------------------*
* GLOBAL DATA
*&---------------------------------------------------------------------*
*&---------------------------------------------------------------------*
* GLOBAL INTERNAL TABLES
*&---------------------------------------------------------------------*
*&---------------------------------------------------------------------*
* GLOBAL RANGES
*&---------------------------------------------------------------------*
*&---------------------------------------------------------------------*
* SELECTION-SCREEN
*&---------------------------------------------------------------------*
*&---------------------------------------------------------------------*
* GLOBAL MACROS
*&---------------------------------------------------------------------*
*&---------------------------------------------------------------------*
* EVENTS BEFORE MAIN PROGRAM
*&---------------------------------------------------------------------*
*INITIALIZATION.
*AT SELECTION-SCREEN OUTPUT.
*AT SELECTION-SCREEN ON VALUE-REQUEST FOR.
*AT SELECTION-SCREEN.
*TOP-OF-PAGE.
*&---------------------------------------------------------------------*
*
* MAIN PROGRAM
*
*----------------------------------------------------------------------*
START-OF-SELECTION.
* Initialize data
PERFORM frm_initialize_data.
* Process input data (for inbound interfaces)
PERFORM frm_process_input_data.
* Select data from database
PERFORM frm_select_data.
* Process selected data
PERFORM frm_process_data.
END-OF-SELECTION.
* Combine results from the processing (may not be necessary)
PERFORM frm_combine_data.
* Output result to file or spool/screen
PERFORM frm_output_data.
程序框架應(yīng)該符合以下的層次結(jié)構(gòu),也就是說每個子程序應(yīng)該把其中的邏輯打散到更小的子程序中,以使子程序的邏輯簡單化,增加代碼的可重用性和可靠性。
Example:
典型的程序?qū)哟谓Y(jié)構(gòu)如下:
|__perform f_select_data
| |
| |__ perform f_select_device_data.
| ||
| | |__ perform f_select_equi
| ||
| ||__ perform f_select_egerh
| ||
| ||__ perform f_select_egers
| |
| |__ perform f_select_inst_data.
|
|__ perform f_process_data
| |
| |__ perform f_process_mru_data.
| |
| |__ perform f_process_device_data.
|
|__ perform f_output_data.
數(shù)據(jù)初始化子程序
數(shù)據(jù)初始化子程序主要用于數(shù)據(jù)讀取、處理所需的初始化操作,比如初始化range變量、系統(tǒng)變量、全局變量等。如果需要對多個range變量進行初始化,那么需要將它們分別放到各自的子程序中處理。
Example:
form f_initialize_data.
* Initialize system fields
perform f_init_data_sysfields.
* Initialize ranges
perform f_init_data_ranges.
endform f_initialize_data.
form f_init_data_sysfields.
g_sysdate = sy-datum.
g_sysuname = sy-uname.
endform
form f_init_data_ranges.
r_divisions = c_range_search_eq. “c_range_search_eq = ‘IEQ’
r_division-low = c_div_elec.
append r_division.
endform
數(shù)據(jù)存取子程序
此子程序作為數(shù)據(jù)存取的唯一入口,通過perform來調(diào)用各個select子程序。所有的數(shù)據(jù)存取語句(select)都應(yīng)該包含在相應(yīng)的select子程序中;通常情況下,一個select語句應(yīng)該包含在一個獨立的子程序中。
Example:
form f_select_data.
* Get MRUs
perform f_select_mru.
* Get Installations.
perform f_select_inst.
Endform.
form f_select_mru.
* Get all MRUs
Select ableinh
Into i_mrus
From te422
Where adatsoll in s_adatsoll.
endform.
form f_select_inst.
Check i_mrus[] is not initial.
* Get all installations
Select anlage
Into i_insts
From eanlh
For all entries in i_mrus
Where ableinh = i_mrus-anlage.
endform.
數(shù)據(jù)處理子程序
該子程序應(yīng)該是處理數(shù)據(jù)的唯一入口,所有邏輯處理的子程序應(yīng)該通過該子程序來調(diào)用。
Example:
form f_process_data.
* Process MRUs
perform f_process_mru.
* Process Installation Data
perform f_process_inst.
Endform.
form f_process_mru.
* Process MRUs that start with ‘M*’
perform f_process_mru_main.
* Process All other MRUs that don’t start with ‘M*’
perform f_process_mrus_sub.
endform.
form f_process_inst.
...
endform.
數(shù)據(jù)組合子程序
該子程序僅用于將F_PROCESS*處理的結(jié)果組合成最終的輸出結(jié)構(gòu)。
該子程序不是必需的。
Example:
form f_combine_data.
Loop at i_inst into w_inst.
Read table i_easts with key anlage = w_inst-anlage
Binary search.
....
w_output-anlage = w_inst-anlage.
w_output-device = w_easts-device.
Append w_output to i_output.
Endloop.
Endform.
數(shù)據(jù)輸出子程序
該子程序僅用于輸出結(jié)果。所有相關(guān)的數(shù)據(jù)處理邏輯不應(yīng)該出現(xiàn)在該子程序中,而應(yīng)該出現(xiàn)在F_PROCESS* 子程序中。該子程序的作用只是用于格式化輸出。
Example:
form f_output_data.
* Output data
perform f_write_column_heading.
format color col_red.
Loop at i_output into w_output.
write at: /g_col1 w_output-anlage“installation
g_col2 w_output-device. “device
Endloop.
form color off.
Endform.
子程序規(guī)范
子程序是代碼模塊化的非常好的一種方法。
模塊化代碼
使用子程序的主要目的是使程序代碼模塊化。程序中使用的公共代碼應(yīng)該轉(zhuǎn)換為子程序,而不是在每個地方使用代碼拷貝。
Example:
Assume the following declarations
types: begin of ty_devmr,
equnr like eabl-equnr,“Equipment number
adatsoll like eabl-adatsoll,“Schedule MR Date
flag type c,“Indicate old MR or not
end of ty_devmr.
types: ty_tab_devmr type ty_devmr occurs 0.
data: i_devmr1 type ty_tabmr.
data: i_devmr2 type ty_tabmr.
Unacceptable:
Form f_check_device_lists
...
loop at i_devmr1 assigning <fs_mr> where adatsoll < g_sysdate.
<fs_mr>-flag = c_true.
endloop.
loop at i_devmr2 assigning <fs_mr> where adatsoll < g_sysdate.
<fs_mr>-flag = c_true.
endloop.
...
Endform.
Acceptable:
Form f_check_device_lists
...
perform f_check_single_dev_list tables i_devmr1.
perform f_check_single_dev_list tables i_devmr2.
...
Endform.
Form f_check_single_dev_list tables pi_devlist type ty_tab_devmr.
* Loop at the list of input devices and set the flag.
loop at pi_devlist assigning <fs_mr> where adatsoll < g_sysdate.
<fs_mr>-flag = c_true.
endloop.
Endform.
參數(shù)
參數(shù)命名
子程序參數(shù)命名參考2.2.2變量命名規(guī)范。
參數(shù)類型
所有傳入子程序的參數(shù)都必須指定參數(shù)類型。
Unacceptable:
Form f_process_billdoc using pwa_billdoc.
...
Endform.
Acceptable:
Form f_process_billdoc using pwa_billdoc type ty_billdoc.
...
Endform.
Table參數(shù)
通常情況下,數(shù)據(jù)量大的內(nèi)表應(yīng)該定義為全局變量而不應(yīng)該通過參數(shù)來傳遞。而對于數(shù)據(jù)量小的內(nèi)表,有時候則是通過子程序參數(shù)來傳遞(程序員應(yīng)該在這一點上合理把握)。參數(shù)類型通常情況下使用type而不是structure來定義。
Unacceptable:
Form f_process_billdoc tables pi_docs structure i_docs.
...
Endform.
Acceptable:
Form f_process_billdoc tables pi_docs type ty_tab_doclist.
...
Endform.
參數(shù)個數(shù)要求
當(dāng)有大量的有關(guān)聯(lián)的簡單變量需要傳入時,最好是采用以下方式之一:
創(chuàng)建一個公用的結(jié)構(gòu),以結(jié)構(gòu)的方式傳入?yún)?shù)
通過小的內(nèi)表來傳入值
使用range變量來傳入值
程序員應(yīng)該合理判斷采用哪種方式更合適。
Unacceptable:
...
perform f_process_date using l_date1
l_date2
l_datecheck_a
l_date3
l_date4
l_datecheck_b.
...
Form f_process_date using l_startdate_a like sy-datum
l_enddate_a like sy-datum
l_datecheck_a type c
l_startdate_b like sy-datum
l_enddate_b like sy-datum
l_datecheck_b type c.
...
if l_startdate_a < sy-datum
and l_enddate_a > sy-datum
and l_datecheck_a = c_true
and l_startdate_b < sy-datum
and l_enddate_b> sy-datum
and l_datecheck_b = c_true.
...
Endif.
...
Endform.
Acceptable:
...
types: begin of ty_date,
start like sy-datum,“Start Date
end like sy-dateum, “End Date
check type c, “Date check flag
end of ty_date.
...
* lwa_date1 and lwa_date2 are of type ty_date and contain the
* the required dates.
perform f_process_date using lwa_date1
lwa_date2.
...
Form f_process_date using pwa_date1 type ty_date
pwa_date2 type ty_date.
if pwa_date1-start < sy-datum
and pwa_date1-end > sy-datum
and pwa_date1-check = c_true
and pwa_date2-start < sy-datum
and pwa_date2-end > sy-datum
and pwa_date2-check = c-true.
...
Endif.
Endform.
參數(shù)對齊
子程序使用的形式變量必須按照以下格式對齊。
Unacceptable:
Form f_process_date tables pi_tab type ty_tab_tab
using l_date like sy-datum
l_datecheck type c.
...
Endform.
Acceptable:
Form f_process_date tables pi_tab type ty_tab_tab
using l_date like sy-datum
l_datecheck type c.
...
Endform.
子程序結(jié)構(gòu)
每一個子程序應(yīng)該只包含一個邏輯功能塊,如果需要多個邏輯塊,那么該子程序應(yīng)該拆分為多個子程序。
每一個select語句應(yīng)該有一個單獨的子程序(關(guān)系非常緊密的多個select語句可以放到一個子程序中)
如果子程序中包含兩個以上的連續(xù)loop語句,那么應(yīng)該把它們拆分到不同的子程序中
如果一個子程序中包含的代碼行超過100,那么應(yīng)該把該子程序拆分成多個子程序
Unacceptable:
Form f_process_data.
Loop at i_movein into w_movein.
...
Endloop.
Loop at i_inst into w_inst.
...
Endloop.
Endform.
Acceptable:
Form f_process_data.
* Process the move-in records
Perform f_process_movein.
* Process the installation records
Perform f_process_insts.
Endform.
Form f_process_movein.
Loop at i_movein into w_movein.
...
Endloop.
Endform.
Form f_process_inst.
Loop at i_inst into w_inst.
...
Endloop.
Endform.
Perform語句
使用perform語句調(diào)用子程序時,傳遞的參數(shù)必須對齊且注釋;每一個參數(shù)應(yīng)該分行列出。
Unacceptable:
perform f_delete_unused_bill_orders tables i_billorders using l_date.
Acceptable:
* Use the standard function to delete unused billing orders from the list
* in I_BILLORDERS
perform f_delete_unused_bill_orders tables i_billorders “Bill order list
using l_date. “Input date
子程序注釋
所有的子程序必須包含注釋以說明子程序的功能以及輸入輸出參數(shù)的含義。
Example:
*&---------------------------------------------------------------------*
*& Form F_CONV_DATE
*----------------------------------------------------------------------*
* This is used to convert the date in the yyyymmdd format into the *
* the text string: dd.mm.yyyy format. *
*----------------------------------------------------------------------*
* --> p_inp_date = The original date in the yyyymmdd format *
* <-- p_out_date = The date in the dd.mm.yyyy format. *
*----------------------------------------------------------------------*
form f_conv_dat using p_inp_date like sy-datum
p_out_date(10) type c.
Endform.
功能模塊規(guī)范
函數(shù)模塊結(jié)構(gòu)
函數(shù)模塊的主要代碼區(qū)域(FUNCTION和ENDFUNCTION之間) 不能包含復(fù)雜的邏輯:
只能包含子程序或其他函數(shù)的調(diào)用語句
可以包含簡單的 IF, CASE, LOOP 等語句
所有的復(fù)雜的邏輯處理(包含select)必須定義為子程序中,放入相應(yīng)的函數(shù)模塊包含程序中
如果函數(shù)模塊中全部的代碼(包含注釋文本)不超過100行,那么可以例外
函數(shù)返回值
函數(shù)調(diào)用后必須檢查相應(yīng)的返回狀態(tài)變量SY-SUBRC,如果確實不需要檢查,應(yīng)該說明原因。
函數(shù)調(diào)用
調(diào)用函數(shù)模塊時,如果有不使用的IMPORTING/EXPORTING/TABLE參數(shù),請刪除相應(yīng)的注釋行。
同時,所有的參數(shù)必須格式對齊。
Unacceptable:
CALL FUNCTION 'BAPI_IDENTIFICATIONDETAILS_GET'
EXPORTING
BUSINESSPARTNER = W_EBILL_CA-GPART
TABLES
* IDENTIFICATIONDETAIL = I_BAPIBUS1006_ID_DETAILS
RETURN = I_BAPIRET2.
Acceptable:
CALL FUNCTION 'BAPI_IDENTIFICATIONDETAILS_GET'
EXPORTING
BUSINESSPARTNER = W_EBILL_CA-GPART
TABLES
RETURN = I_BAPIRET2.
(Please note, that all the fields are aligned neatly)
屏幕對話程序規(guī)范
屏幕邏輯流結(jié)構(gòu)
所有自定義的主屏幕邏輯流均需定義為以下類似結(jié)構(gòu);子屏幕不應(yīng)包含:TOOLBAR、 USER-COMMAND和EXIT-COMMAND幾個部分
PROCESS BEFORE OUTPUT.
* Set toolbar and titlebar
MODULE status_xxxx. “xxxx-screen number
* Set output attribute for screen fields
MODULE dynpro_fields_xxxx. “xxxx-screen number
* move data from program to screen fields
MODULE dynpro_data_out_xxxx. “xxxx-screen number
* Table control loop
LOOP AT gt_tab INTO gs_tab WITH CONTROL tc_xxxx CURSOR tc_xxxx-current_line.
* Set output attribute of table control fields
MODULE dynpro_fields_tc_xxxx.
* move data from program to table control fields
MODULE dynpro_data_out_tc_xxxx.
ENDLOOP.
PROCESS AFTER INPUT.
* Process EXIT-COMMAND
MODULE exit_command_xxxx AT EXIT-COMMAND. “xxxx-screen number
* check input validation of screen fields
CHAIN.
FIELD: a,
b.
MODULE dynpro_data_check_<w>_xxxx ON CHAIN-REQUEST. “<w>-meaning words
ENDCHAIN.
* move data from screen fields to program
CHAIN.
FIELD: a,
b,
c.
MODULE dynpro_data_in_xxxx ON CHAIN-REQUEST. “xxxx-screen number
ENDCHAIN.
* Table control loop
LOOP AT gt_tab.
* check input validation of table control fields
CHAIN.
FIELD: c,
d.
MODULE dynpro_data_check_<w>_tc_xxxx ON CHAIN-REQUEST.“<w>-meaning words
ENDCHAIN.
* move data from table control fields to program
CHAIN.
FIELD: c,
d,
e.
MODULE dynpro_data_in_tc_xxxx ON CHAIN-REQUEST.
ENDCHAIN.
ENDLOOP.
* Process USER-COMMAND
MODULE user_command_xxxx. “xxxx-screen number
PROCESS ON VALUE-REQUEST.
* Process f4 for screen field a
FIELD a MODULE dynpro_f4_a_xxxx. “xxxx-screen number
PAI/PBO/POV 模塊
所有屏幕模塊必須包含以下類似結(jié)構(gòu)
MODULE <module_name> [INPUT|OUTPUT].
* Call subroutine of each special module
PERFORM f_<module_name>_[pai|pbo|pov].
ENDMODULE.
在〔MODULE…..ENDMODULE〕中不允許有任何邏輯處理語句,更不能定義任何類型的變量,只允許使用PERFORM語句調(diào)用特定的子程序。所有相關(guān)的業(yè)務(wù)邏輯只能包含在該子程序或其調(diào)用的下層子程序中.
Example:
Unacceptable:
MODULE dynpro_data_out_0100 OUTPUT.
ekko-ebeln = gs_ekko-ebeln.
ekko-lifnr = gs_ekko-lifnr.
SELECT SINGLE name1 INTO dynpro_name1 FROM lfa1 WHERE lifnr = ekko-lifnr.
ENDMODULE.
Acceptable:
MODULE dynpro_data_out_0100 OUTPUT.
PERFORM f_dynpro_data_out_0100_pbo.
ENDMODULE.
FORM f_dynpro_data_out_0100_pbo.
ekko-ebeln = gs_ekko-ebeln.
ekko-lifnr = gs_ekko-lifnr.
SELECT SINGLE name1 INTO dynpro_name1 FROM lfa1 WHERE lifnr = ekko-lifnr.
ENDFORM.
User-command模塊
這個模塊只能用于處理除EXIT-COMMAND以外的所有用戶按鈕操作; 在該模塊調(diào)用的子程序中,只允許使用CASE判斷屏幕觸發(fā)的按鈕事件,任何業(yè)務(wù)邏輯語句均需要包含在相應(yīng)的子程序中。相應(yīng)子程序應(yīng)按照以下規(guī)則命名:
Frm_fcode_<okcode>_<dynnr>
<okcode>-按鈕名稱
<dynnr>-屏幕號
所有屏幕事件代碼均使用全局變量ok_code接收,同時必須定義全局變量ok_save,在user_command模塊中按照以下方式來處理
EXAMPLE:
form f_user_command_0100_pai.
OK_SAVE = OK_CODE.
CLEAR OK_CODE.
CASE OK_SAVE.
WHEN ‘ADD’. “add data line
perform f_fcode_add_0100.
WHEN ‘SAVE’. “save data
perform f_fcode_save_0100.
WHEN OTHERS.
ENDCASE.
Endform.
BADI增強規(guī)范
實施BADI增強需按照以下步驟實現(xiàn):
Step
Description
1
在SE19中創(chuàng)建客BADI實施:命名參考本文檔“1.5 BADI實施命名規(guī)范”
2
在相應(yīng)的BADI實施類中,增加自定義方法,所有業(yè)務(wù)邏輯的處理均應(yīng)包含在自定義方法中:Z<XX>_<BADI_METH>_<nn>;
3
在BADI實施標(biāo)準(zhǔn)方法中使用call method調(diào)用相應(yīng)的自定義業(yè)務(wù)處理方法
注意:在BADI實施模塊的標(biāo)準(zhǔn)方法中,不能有復(fù)雜的業(yè)務(wù)邏輯
Example:
Unacceptable:
METHOD if_ex_ac_document~change_initial.
LOOP AT im_document-item INTO w_item.
w_ebeln = w_item-ebeln.
w_ebelp = w_item-ebelp.
CHECK w_ebeln IS NOT INITIAL AND w_ebelp IS NOT INITIAL.
SELECT SINGLE * FROM ekpo
WHERE ebeln EQ w_ebeln
AND ebelp EQ w_ebelp.
......
ENDLOOP.
ENDMETHOD. 'if_ex_ac_document~change_initial
Acceptable:
METHOD if_ex_ac_document~change_initial.
* Change document data
CALL METHOD ZSG1_CHANGE_INITIAL_01
EXPORTING
IM_DOCUMENT = IM_DOCUMENT
IMPORTING
EX_DOCUMENT = EX_DOCUMENT.
ENDMETHOD. 'if_ex_ac_document~change_initial
METHOD ZSG1_CHANGE_INITIAL_01
* Get data from purchasing order
CALL METHOD ZFILL_DOC_ITEM_WITH_PO_ITEM.
EXPORTING
IM_DOCUMENT = IM_DOCUMENT
IMPORTING
EX_DOCUMENT = EX_DOCUMENT.
* Other enhancement data
CALL METHOD ZFILL_DOC_ITEM_WITH_CUSTOM_DATA
EXPORTING
IM_DOCUMENT = IM_DOCUMENT
IMPORTING
EX_DOCUMENT = EX_DOCUMENT.
ENDMETHOD. 'ZSG1_CHANGE_INITIAL_01
METHOD ZFILL_DOC_ITEM_WITH_PO_ITEM
* Get data from purchasing order
LOOP AT im_document-item INTO w_item.
w_ebeln = w_item-ebeln.
w_ebelp = w_item-ebelp.
CHECK w_ebeln IS NOT INITIAL AND w_ebelp IS NOT INITIAL.
SELECT SINGLE * FROM ekpo
WHERE ebeln EQ w_ebeln
AND ebelp EQ w_ebelp.
......
ENDLOOP.
ENDMETHOD. 'ZFILL_DOC_ITEM_WITH_PO_ITEM.
CMOD增強規(guī)范
CMOD中的增強用戶出口包含一個函數(shù)模塊 (EXIT_*) 和一個可以客戶化修改的include程序。該include程序中不允許包含任何邏輯!
為了實施一個增強,應(yīng)該將用戶出口函數(shù)模塊 (EXIT_*) 拷貝為一個用戶函數(shù)模塊(按命名規(guī)范命名z*),所有的邏輯處理應(yīng)該包含在這個拷貝出的函數(shù)模塊中;而出口inlucde程序,僅需要調(diào)用該函數(shù)的語句。
例如,假定有一個用戶出口 EXIT_SAPLES55_001,它包含一個inlcude程序ZXSAPL02;那么應(yīng)該按照以下步驟來實施這個增強出口:
Step
Description
1
在CMOD中創(chuàng)建一個項目,包含所需的增強
2
拷貝用戶出口函數(shù)模塊EXIT_SAPLES55_001為一個用戶函數(shù) 模塊 (例如,新的函數(shù)模塊名為ZISCS_EXITES55_COBJ)
3
在函數(shù)模塊ZISCS_EXITES55_COBJ中加入所需的增強邏輯
4
在inlude文件ZXSAPL02中調(diào)用函數(shù)模塊ZISCS_EXITES55_COBJ,并傳遞函數(shù)模塊EXIT_SAPLES55_001的所有參數(shù)
如果需要在用戶出口中增加一塊全新的邏輯,那么應(yīng)該拷貝出新的函數(shù)模塊來實現(xiàn)。
BTE增強規(guī)范
所有BTE的開發(fā)均必須在客戶定制范圍內(nèi)實現(xiàn),不允許對SAP標(biāo)準(zhǔn)應(yīng)用的BTE做任何更改;實施BTE增強需按照以下步驟實現(xiàn):
Step
Description
1
在FIBF中創(chuàng)建客戶定制產(chǎn)品PROD:Z<XX>_<nnn>,如:ZFIN_001
2
拷貝相應(yīng)BTE函數(shù)模版到自定義函數(shù)模塊:<PROD>_<event>_<desc>,如:ZFIN_001_1030_FIDOC_SAVE
3
在函數(shù)模塊ZFIN_001_1030_FIDOC_SAVE中增加相應(yīng)的邏輯,函數(shù)中的代碼必須符合本文檔中“功能模塊規(guī)范“要求
4
在FIBF相應(yīng)P/S Module或Process Module中客戶產(chǎn)品部分指定:事件、產(chǎn)品、函數(shù)模塊,如:00001030 | ZFIN_001 | ZFIN_001_1030_FIDOC_SAVE
程序性能相關(guān)代碼規(guī)范
SQL語句
始終把條件放在where子句中而不要使用check語句來檢查,這樣數(shù)據(jù)庫系統(tǒng)可以使用索引(如果可能),同時這樣可以大大降低網(wǎng)絡(luò)負載。
Example:
Unacceptable:
SELECT * FROM SBOOK INTO SBOOK_WA.
CHECK: SBOOK_WA-CARRID = 'LH' AND
SBOOK_WA-CONNID = '0400'.
ENDSELECT.
acceptable:
SELECT * FROM SBOOK INTO SBOOK_WA
WHERE CARRID = 'LH' AND
CONNID = '0400'.
ENDSELECT.
如果需要檢查表或視圖是否有滿足某條件的記錄存在,請使用Select ... Up To 1 Rows 語句,而不要使用帶Exit的Select-Endselect-loop語句。如果條件中包含所有的主鍵字段,則應(yīng)該使用Select Single語句。Select Single語句僅需要與數(shù)據(jù)庫通信一次,而 Select-Endselect則需要兩次。
Example:
Unacceptable:
SELECT * FROM SBOOK INTO SBOOK_WA
WHERE CARRID = 'LH'.
EXIT.
ENDSELECT.
acceptable:
SELECT * FROM SBOOK INTO SBOOK_WA
UP TO 1 ROWS
WHERE CARRID = 'LH'.
ENDSELECT.
如果想查詢最大值、最小值、總和、平均值或者條目數(shù),則應(yīng)該使用統(tǒng)計函數(shù);這樣可以大大降低網(wǎng)絡(luò)負載。
Example:
Unacceptable:
DATA: MAX_MSGNR type t100-msgnr.
MAX_MSGNR = '000'.
SELECT * FROM T100 INTO T100_WA
WHERE SPRSL = 'D' AND
ARBGB = '00'.
CHECK: T100_WA-MSGNR > MAX_MSGNR.
MAX_MSGNR = T100_WA-MSGNR.
ENDSELECT.
acceptable:
DATA: MAX_MSGNR type t100-msgnr.
SELECT MAX( MSGNR ) FROM T100 INTO max_msgnr
WHERE SPRSL = 'D' AND
ARBGB = '00'.
如果僅需讀取表或視圖中的個別字段,那么應(yīng)該使用select列表而不要使用Select * ;這樣可以大大降低網(wǎng)絡(luò)負載。
Example:
Unacceptable:
SELECT * FROM DD01L INTO DD01L_WA
WHERE DOMNAME LIKE 'CHAR%'
AND AS4LOCAL = 'A'.
ENDSELECT.
acceptable:
SELECT DOMNAME FROM DD01L
INTO DD01L_WA-DOMNAME
WHERE DOMNAME LIKE 'CHAR%'
AND AS4LOCAL = 'A'.
ENDSELECT.
更新數(shù)據(jù)庫時,盡可能使用列更新而不要使用單行更新。這樣可以大大降低網(wǎng)絡(luò)負載。
Example:
Unacceptable:
SELECT * FROM SFLIGHT INTO SFLIGHT_WA.
SFLIGHT_WA-SEATSOCC =
SFLIGHT_WA-SEATSOCC - 1.
UPDATE SFLIGHT FROM SFLIGHT_WA.
ENDSELECT.
acceptable:
UPDATE SFLIGHT
SET SEATSOCC = SEATSOCC - 1.
對于經(jīng)常使用的select語句,盡量使用索引。在select語句的where子句中,盡量使用通過AND連接的索引字段,這樣數(shù)據(jù)庫總是會使用索引。注意:過于復(fù)雜的where子句對于數(shù)據(jù)庫系統(tǒng)語句優(yōu)化器來說都是不利于處理的。
Example:
Unacceptable:
SELECT * FROM SBOOK CLIENT SPECIFIED INTO SBOOK_WA
WHERE CARRID = 'LH'
AND CONNID = '0400'.
ENDSELECT.
acceptable:
SELECT * FROM SBOOK CLIENT SPECIFIED INTO SBOOK_WA
WHERE MANDT IN ( SELECT MANDT FROM T000 )
AND CARRID = 'LH'
AND CONNID = '0400'.
ENDSELECT.
對于經(jīng)常使用的只讀表,盡量使用SAP緩存??梢源蟠蠼档途W(wǎng)絡(luò)負載。
Example:
Unacceptable:
SELECT SINGLE * FROM T100 INTO T100_WA
BYPASSING BUFFER
WHERE SPRSL = 'D'
AND ARBGB = '00'
AND MSGNR = '999'.
acceptable:
SELECT SINGLE * FROM T100 INTO T100_WA
WHERE SPRSL = 'D'
AND ARBGB = '00'
AND MSGNR = '999'.
一般情況下使用Into Table總是會快于Select循環(huán)中使用Append 語句
Example:
Unacceptable:
DATA T006_WA TYPE T006.
CLEAR X006.
SELECT * FROM T006 INTO T006_WA.
APPEND T006_WA TO X006.
ENDSELECT.
acceptable:
SELECT * FROM T006 INTO TABLE X006.
更新數(shù)據(jù)庫表時,盡可能使用數(shù)組操作而不要使用單行操作。應(yīng)用程序和數(shù)據(jù)庫系統(tǒng)頻繁通信會造成大量的系統(tǒng)負載。
Example:
Unacceptable:
LOOP AT TAB INTO TAB_WA.
INSERT INTO CUSTOMERS VALUES TAB_WA.
ENDLOOP.
acceptable:
INSERT CUSTOMERS FROM TABLE TAB.
如果選擇的數(shù)據(jù)只處理一次,那么應(yīng)該使用Select-Endselect循環(huán),二不要使用Into Table把數(shù)據(jù)收集到內(nèi)表中再處理;內(nèi)表處理會占用更多的空間。
Example:
Unacceptable:
SELECT * FROM T006
INTO TABLE X006.
LOOP AT X006 INTO X006_WA.
ENDLOOP.
acceptable:
SELECT * FROM T006 INTO X006_WA.
ENDSELECT.
如果要處理表連接,應(yīng)該使用視圖而不要使用嵌套的select語句;這樣可以有效的降低網(wǎng)絡(luò)負載。
Example:
Unacceptable:
SELECT * FROM DD01L INTO DD01L_WA
WHERE DOMNAME LIKE 'CHAR%'
AND AS4LOCAL = 'A'.
SELECT SINGLE * FROM DD01T INTO DD01T_WA
WHERE DOMNAME = DD01L_WA-DOMNAME
AND AS4LOCAL = 'A'
AND AS4VERS = DD01L_WA-AS4VERS
AND DDLANGUAGE = SY-LANGU.
ENDSELECT.
acceptable:
SELECT * FROM DD01V INTO DD01V_WA
WHERE DOMNAME LIKE 'CHAR%'
AND DDLANGUAGE = SY-LANGU.
ENDSELECT.
如果要從幾個邏輯關(guān)聯(lián)的表中讀取數(shù)據(jù),應(yīng)該使用表連接而不要使用嵌套的select語句;這樣可以有效的降低網(wǎng)絡(luò)負載。
Example:
Unacceptable:
SELECT * FROM SPFLI INTO SPFLI_WA.
SELECT * FROM SFLIGHT INTO SFLIGHT_WA
WHERE CARRID = SPFLI_WA-CARRID
AND CONNID = SPFLI_WA-CONNID.
ENDSELECT.
ENDSELECT.
acceptable:
SELECT * INTO WA
FROM SPFLI AS P INNER JOIN SFLIGHT AS F
ON P~CARRID = F~CARRID AND
P~CONNID = F~CONNID.
ENDSELECT.
通常情況下嵌套的Select 循環(huán)或者FOR ALL ENTRIES 都可以通過子查詢來實現(xiàn);子查詢可以有效的降低網(wǎng)絡(luò)負載。
Example:
Unacceptable:
SELECT * FROM SPFLI
INTO TABLE T_SPFLI
WHERE CITYFROM = 'FRANKFURT'
AND CITYTO = 'NEW YORK'.
SELECT * FROM SFLIGHT AS F
INTO SFLIGHT_WA
FOR ALL ENTRIES IN T_SPFLI
WHERE SEATSOCC < F~SEATSMAX
AND CARRID = T_SPFLI-CARRID
AND CONNID = T_SPFLI-CONNID
AND FLDATE BETWEEN '19990101' AND '19990331'.
ENDSELECT.
acceptable:
SELECT * FROM SFLIGHT AS F INTO SFLIGHT_WA
WHERE SEATSOCC < F~SEATSMAX
AND EXISTS ( SELECT * FROM SPFLI
WHERE CARRID = F~CARRID
AND CONNID = F~CONNID
AND CITYFROM = 'FRANKFURT'
AND CITYTO = 'NEW YORK' )
AND FLDATE BETWEEN '19990101' AND '19990331'.
ENDSELECT.
內(nèi)表操作
如果內(nèi)表的記錄條數(shù)很多(>20),那么對全表進行線性查詢是非常費時的。應(yīng)該盡量使內(nèi)表排序,并使用二分法搜索,或者使用SORTED TABLE。假如內(nèi)表含有n條記錄,線性搜索執(zhí)行時間為O( n ) ,而二分法執(zhí)行時間僅為O( log2( n ) )。
Example:
Unacceptable:
* Entries: 1000, Line width: 100
* Key width: 20
* The READ ends with SY-SUBRC=4
READ TABLE ITAB INTO WA
WITH KEY K = 'X'.
acceptable:
* Entries: 1000, Line width: 100
* Key width: 20
* The READ ends with SY-SUBRC=4
READ TABLE ITAB INTO WA
WITH KEY K = 'X'
BINARY SEARCH.
如果需要使用不同的關(guān)鍵字重復(fù)讀取內(nèi)表,那么應(yīng)該在代碼中保存相應(yīng)的次級索引。有了次級索引就可以使用二分法搜索加上一個索引讀取來替代線性搜索。
Example:
Unacceptable:
* Entries: 1000, Line width: 100
* Key width: 20
* The READ locates the 500th entry.
READ TABLE ITAB INTO WA
WITH KEY DATE = SY-DATUM.
IF SY-SUBRC = 0.
' ...
ENDIF.
acceptable:
* Entries: 1000, Line width: 100
* Key width: 20
* The READ locates the 500th entry.
READ TABLE SEC_IDX INTO SEC_IDX_WA
WITH KEY DATE = SY-DATUM
BINARY SEARCH.
IF SY-SUBRC = 0.
READ TABLE ITAB INTO WA
INDEX SEC_IDX_WA-INDX.
' ...
ENDIF.
LOOP ... WHERE比LOOP/CHECK性能更好,因為LOOP ... WHERE由內(nèi)部來判斷指定的條件。同所有的邏輯表達式一樣,如果操作數(shù)的類型相同,則性能會更好。 可能的情況下,使用FROM i1且(或者)TO i2可以進一步提高性能。
Example:
Unacceptable:
* Entries: 1000, Line width: 500
* Key width: 20
* 5 entries of which match the key condition
LOOP AT ITAB INTO WA.
CHECK WA-K = 'X'.
' ...
ENDLOOP.
acceptable:
* Entries: 1000, Line width: 500
* Key width: 20
* 5 entries of which match the key condition
LOOP AT ITAB INTO WA WHERE K = 'X'.
' ...
ENDLOOP.
排序表中的記錄通過二分法來定位,執(zhí)行的時間依賴于表中記錄數(shù)(O (log n))。而哈希表中記錄通過哈希算法來定位,執(zhí)行的時間始終是固定的(O (1)), 而與表的大小無關(guān)。 哈希表適用于單條記錄的讀取,而排序表則適用于符合部分條件的順序的表循環(huán)操作。
Example:
Unacceptable:
* Entries: 1000
* Line width: 100, key width: 20
* STAB is a unique sorted table, 250 entries are read
DO 250 TIMES.
N = 4 * SY-INDEX.
READ TABLE STAB INTO WA WITH TABLE KEY K = N.
IF SY-SUBRC = 0.
' ...
ENDIF.
ENDDO.
acceptable:
* Entries: 1000
* Line width: 100, key width: 20
* HTAB is a hased table, 250 entries are read
DO 250 TIMES.
N = 4 * SY-INDEX.
READ TABLE HTAB INTO WA WITH TABLE KEY K = N.
IF SY-SUBRC = 0.
' ...
ENDIF.
ENDDO.
哈希表為單條記錄讀取而優(yōu)化,記錄之間沒有特定的順序關(guān)系。因此對哈希表進行部分鍵值的順序讀取,其性能是沒有優(yōu)化的,而是每一條記錄都要檢查是否符合條件(即全表搜索)。排序表則是按照主鍵進行升序排列的。如果查詢條件是這樣的格式'k1 = v1 AND ... AND kn = vn'(k1 .. kn與表主鍵的左邊部分匹配),那么表的讀取是被核心代碼優(yōu)化的,因此只會訪問符合條件的記錄,而不是全表搜索。
Example:
Unacceptable:
* Entries: 10000, Line width: 100
* key width: 60, Subkey width: 20
* HTAB is a hashed table, 2000 entries are read
* Key fields: K, DATA
LOOP AT HTAB INTO WA WHERE K = SUBKEY.
' ...
ENDLOOP.
acceptable:
* Entries: 10000, Line width: 100
* key width: 60, Subkey width: 20
* STAB is a sorted table, 2000 entries are read
* Key fields: K, DATA
LOOP AT STAB INTO WA WHERE K = SUBKEY.
' ...
ENDLOOP.
使用MODIFY語句更新內(nèi)表時,使用' TRANSPORTING f1 f2 ...'可以提高執(zhí)行的效率;特別是表行越長越明顯。
Example:
Unacceptable:
* Line width: 500
* The complete line is moved.
WA-DATE = SY-DATUM.
MODIFY ITAB FROM WA INDEX 1.
acceptable:
* Line width: 500
* Only the 8 bytes of the selected
* component are moved.
WA-DATE = SY-DATUM.
MODIFY ITAB FROM WA INDEX 1 TRANSPORTING DATE.
使用'LOOP ... ASSIGNING ...'直接存取內(nèi)表行,可以大大提高內(nèi)表記錄的更新速度。
Example:
Not preferred:
* Entries: 100 (outer table), 20 (inner table)
* The entries to be modified: 50
* Actually, only the component FLAG is updated.
* However, the complete lines are moved.
LOOP AT ITAB INTO WA.
I = SY-TABIX MOD 2.
IF I = 0.
WA-FLAG = 'X'.
MODIFY ITAB FROM WA.
ENDIF.
ENDLOOP.
Preferred:
* Entries: 100 (outer table), 20 (inner table)
* Entries to be modified: 50
* The component FLAG is updated directly.
LOOP AT ITAB ASSIGNING <WA>.
I = SY-TABIX MOD 2.
IF I = 0.
<WA>-FLAG = 'X'.
ENDIF.
ENDLOOP.
使用從下到上的策略來填充內(nèi)表,那么系統(tǒng)開銷會根據(jù)數(shù)據(jù)結(jié)構(gòu)的層次成倍的增加。因為每一個下層內(nèi)表的數(shù)據(jù)都需要移動到它們的上層數(shù)據(jù)結(jié)構(gòu)中。相反,使用從上到下的策略填充內(nèi)表,先填充外層內(nèi)表,然后使用'LOOP ... ASSIGNING'直接填充內(nèi)層內(nèi)表,這樣內(nèi)層內(nèi)表的數(shù)據(jù)只需要移動一次就可以了。
Example:
Not preferred:
* Entries: 50 (outer table), 10 (inner tables)
* Line width: 500 (outer), 4 (inner)
DO 50 TIMES.
CLEAR WA.
DO 10 TIMES.
APPEND N TO WA-INTTAB.
ADD 1 TO N.
ENDDO.
APPEND WA TO ITAB.
ENDDO.
Preferred:
* Entries: 50 (outer table), 10 (inner tables)
* Line width: 500 (outer), 4 (inner)
DO 50 TIMES.
APPEND INITIAL LINE TO ITAB.
ENDDO.
LOOP AT ITAB ASSIGNING <F>.
DO 10 TIMES.
APPEND N TO <F>-INTTAB.
ADD 1 TO N.
ENDDO.
ENDLOOP.
如果需要匯總表記錄,那么請使用COLLECT語句 !
Example:
Unacceptable:
* TAB1: 1000 entries, Line width: 32
* 500 entries have different keys
LOOP AT ITAB1 INTO WA1.
READ TABLE ITAB2 INTO WA2 WITH KEY K = WA1-K BINARY SEARCH.
IF SY-SUBRC = 0.
ADD: WA1-VAL1 TO WA2-VAL1,
WA1-VAL2 TO WA2-VAL2.
MODIFY ITAB2 FROM WA2 INDEX SY-TABIX TRANSPORTING VAL1 VAL2.
ELSE.
INSERT WA1 INTO ITAB2 INDEX SY-TABIX.
ENDIF.
ENDLOOP.
acceptable:
* TAB1: 1000 entries, Line width: 32
* 500 entries have different keys
LOOP AT ITAB1 INTO WA.
COLLECT WA INTO ITAB2.
ENDLOOP.
SORT ITAB2 BY K.
如果要將一個表的記錄追加到另一個表中,請使用'APPEND LINES OF itab1 TO itab2' .
Example:
Unacceptable:
* Entries: 500 (ITAB1), 500 (ITAB2)
* Line width: 500
* ITAB1 is appended line by line to ITAB2.
LOOP AT ITAB1 INTO WA.
APPEND WA TO ITAB2.
ENDLOOP.
acceptable:
* Entries: 500 (ITAB1), 500 (ITAB2)
* Line width: 500
* ITAB1 is appended in one step to ITAB2.
APPEND LINES OF ITAB1 TO ITAB2.
復(fù)制內(nèi)表可以像其他數(shù)據(jù)類型一樣使用MOVE語句。
Example:
Unacceptable:
* Entries: 100, Line width 100
REFRESH ITAB2.
LOOP AT ITAB1 INTO WA.
APPEND WA TO ITAB2.
ENDLOOP.
acceptable:
* Entries: 100, Line width 100
ITAB2[] = ITAB1[].
對于sort語句,請指定排序的字段。
Example:
Unacceptable:
* Entries: 100, Line width: 500
* Key width: 492
SORT ITAB.
acceptable:
* Entries: 100, Line width: 500
* Key width: 20
SORT ITAB BY K.
其他語句
CASE語句
CASE 相對于IF語句更清晰易讀,性能也稍好一些。
Example:
Unacceptable:
DATA C TYPE C.
IF C = 'A'. WRITE '1'.
ELSEIF C = 'B'. WRITE '2'.
ELSEIF C = 'C'. WRITE '3'.
ELSEIF C = 'D'. WRITE '4'.
ELSEIF C = 'E'. WRITE '5'.
ELSEIF C = 'F'. WRITE '6'.
ELSEIF C = 'G'. WRITE '7'.
ELSEIF C = 'H'. WRITE '8'.
ENDIF.
acceptable:
DATA C TYPE C.
CASE C.
WHEN 'A'. WRITE '1'.
WHEN 'B'. WRITE '2'.
WHEN 'C'. WRITE '3'.
WHEN 'D'. WRITE '4'.
WHEN 'E'. WRITE '5'.
WHEN 'F'. WRITE '6'.
WHEN 'G'. WRITE '7'.
WHEN 'H'. WRITE '8'.
ENDCASE.
WHILE語句
如果可以使用WHILE語句來替換DO EXIT語句,那么請使用WHILE語句,因為WHILE語句更易讀且性能也要好一些。
Example:
Unacceptable:
DATA C TYPE C. DATA I TYPE I.
I = 0.
DO.
IF C NE SPACE. EXIT. ENDIF.
ADD 1 TO I.
IF I GT 10. C = 'X'. ENDIF.
ENDDO.
Acceptable:
DATA C TYPE C. DATA I TYPE I.
I = 0.
WHILE C = SPACE.
ADD 1 TO I.
IF I GT 10. C = 'X'. ENDIF.
ENDWHILE.
比較語句
比較語句中的兩操作數(shù)盡量使用相同的數(shù)據(jù)類型,比如字符與字符的比較性能比字符與數(shù)字的比較更好。
Example:
Unacceptable:
DATA C(8) TYPE C.
IF 12345678 = C.
ENDIF.
Acceptable:
DATA C(8) TYPE C.
IF '12345678' = C.
ENDIF.
附錄
SAP業(yè)務(wù)模塊命名表
<XX>
業(yè)務(wù)模塊
FIN
財務(wù)模塊
MM
物資管理模塊
SD
銷售分銷模塊
PS
項目管理模塊
PM
設(shè)備管理模塊
QM
質(zhì)檢模塊
OM
運行模塊
HR
人資模塊
BC
基礎(chǔ)模塊
CA
跨模塊應(yīng)用
SRM
SRM系統(tǒng)
數(shù)據(jù)字典對象類型命名表
<T>
類型
T
透明表
S
結(jié)構(gòu)
E
數(shù)據(jù)元素
D
域
程序類型命名表
<Y>
程序類型代碼
R
報表程序
P
對話程序
F
FORM/SMARTFORM打印程序
B
后臺作業(yè)程序
I
公共Include程序
本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請
點擊舉報。