ABAP代码规范
ABAP代码规范
命名
1. 使用描述性名称
正例:DATA customizing_entries TYPE STANDARD TABLE ...
反例:DATA iso3166tab TYPE STANDARD TABLE...
2. 优先使用解决方案域和问题域术语
在任何情况下,请勿尝试组成自己的语言。
3. 使用复数
正例:DATA countries TYPE STANDARD TABLE ...
反例:DATA country TYPE STANDARD TABLE ...
4. 使用易读的名称
宁可使用detection_object_types
也不实用 dobjt
.
5. 杜绝完全不规范的缩写,避免望文不知义
反例:cust
??? "customizing", "customer", or "custom"?
6. 在各处使用相同的缩写
例如,始终将“检测对象类型”缩写为dobjt,
而不是混合dotype
,detobjtype
等
7. 类使用名词,方法使用动词
8. 用is_
和has
之类的动词开始布尔方法
9.避免使用干扰词data,info,object
等
10. 鼓励您摆脱所有编码前缀
例如,result = a + b.
而不是rv_result = iv_a + iv_b.
语法
1. 面向对象优先于过程编程
2. 偏爱功能性而非程序语言构造
" MOVE 'A' TO variable.
DATA(variable) = 'A'.
" ADD 1 TO index.
index += 1. " 版本 >= 7.54
“index = index + 1. " 版本 < 7.54
" LOOP AT input INTO DATA(row).
" INSERT row-text INTO TABLE result.
" ENDLOOP.
result = VALUE #( FOR row IN input ( row-text ) ).
" READ TABLE value_pairs INTO DATA(line) WITH KEY name = 'A'.
DATA(line) = value #( value_pairs[ name = 'A' ] optional ).
" READ TABLE value_pairs TRANSPORTING NO FIELDS WITH KEY name = 'A'.
" DATA(exists) = xsdbool( sy-subrc = 0 ).
DATA(exists) = xsdbool( line_exists( value_pairs[ name = 'A' ] ) ).
IF line_exists( value_pairs[ name = 'A' ] ).
" CREATE OBJECT object TYPE /dirty/my_class.
DATA(object) = NEW /clean/my_class( ).
3. 在SQL
中使用@
区分程序变量和数据库列
SELECT *
FROM spfli
WHERE carrid = @carrid AND
connid = @connid
INTO TABLE @itab.
4. 在适当的地方使用设计模式
常量
1. 使用常量代替魔术数字
正例:IF abap_type = cl_abap_typedescr=>typekind_date.
反例:IF abap_type = 'D'.
2.优先于枚举类而不是常量接口
CLASS /clean/message_severity DEFINITION PUBLIC ABSTRACT FINAL.
PUBLIC SECTION.
CONSTANTS:
warning TYPE symsgty VALUE 'W',
error TYPE symsgty VALUE 'E'.
ENDCLASS.
"or
CLASS /clean/message_severity DEFINITION PUBLIC CREATE PRIVATE FINAL.
PUBLIC SECTION.
CLASS-DATA:
warning TYPE REF TO /clean/message_severity READ-ONLY,
error TYPE REF TO /clean/message_severity READ-ONLY.
" ...
ENDCLASS.
"反例
INTERFACE /dirty/common_constants.
CONSTANTS:
warning TYPE symsgty VALUE 'W',
transitional TYPE i VALUE 1,
error TYPE symsgty VALUE 'E',
persisted TYPE i VALUE 2.
ENDINTERFACE.
3.如果不使用枚举类,则将常量分组
CONSTANTS:
BEGIN OF message_severity,
warning TYPE symsgty VALUE 'W',
error TYPE symsgty VALUE 'E',
END OF message_severity,
BEGIN OF message_lifespan,
transitional TYPE i VALUE 1,
persisted TYPE i VALUE 2,
END OF message_lifespan.
变量
1. 优先选择内联而不是预先声明
DATA(name) = 'something'.
"不要在可选分支中声明内联:
IF has_entries = abap_true.
DATA(value) = 1.
ELSE.
value = 2.
ENDIF.
"反例:
DATA name TYPE seoclsname.
name = 'something'.
2. 优先选择REF TO
而不是 FIELD-SYMBOL
This section is being challenged.
"1
LOOP AT components REFERENCE INTO DATA(component).
"2
LOOP AT components ASSIGNING FIELD-SYMBOL(<component>).
除非你需要使用以下:
ASSIGN generic->* TO FIELD-SYMBOL(<generic>).
ASSIGN COMPONENT name OF STRUCTURE structure TO FIELD-SYMBOL(<component>).
ASSIGN (class_name)=>(static_member) TO FIELD-SYMBOL(<member>).
3. 结构赋值
structure-type = 'A'.
structure-id = '4711'.
or even better
structure = VALUE #( type = 'A'
id = '4711' ).
表
1. 使用正确的表格类型
通常,将HASHED
表用于大型表,这些大型表仅一步就被填充,从不修改,并且经常通过键读取。
通常,将SORTED
表用于需要始终进行排序,逐位填充或需要修改,并且经常通过一个或多个完整键或部分键或按特定顺序进行处理的大型表。
将STANDARD
表用于较小的表(其中索引产生的收益多于收益)和“数组”(在 其中您根本不关心行的顺序,或者要完全按照附加的顺序处理它们)使用。另外,如果需要对表的不同访问,例如通过SORT和BINARY SEARCH进行索引访问和排序访问。
2.避免使用DEFAULT KEY
反例:DATA itab TYPE STANDARD TABLE OF row_type WITH DEFAULT KEY.
SORT
和DELETE ADJACENT
语句将求助于内部表的主键,如果使用DEFAULT KEY
,则可能会导致非常意外的结果
正例:明确指定关键组件 ...WITH NON-UNIQUE KEY comp1 comp2.
正例:如果根本不需要密钥,使用EMPTY KEY
:...WITH EMPTY KEY.
注意:带有EMPTY KEY(没有显式排序字段)的内部表上的SORT根本不会排序
3.优先使用INSERT INTO TABLE
而不是 APPEND TO
INSERT VALUE #( ... ) INTO TABLE itab.
仅当您要以类似数组的方式使用STANDARD表时,并且要强调添加的条目应为最后一行时,才使用APPEND TO
4.优先使用 LINE_EXISTS
而不是 READ TABLE
or LOOP AT
去判断值是否存在
IF line_exists( my_table[ key = 'A' ] ).
"反例
READ TABLE my_table TRANSPORTING NO FIELDS WITH KEY key = 'A'.
IF sy-subrc = 0.
"反例
LOOP AT my_table REFERENCE INTO DATA(line) WHERE key = 'A'.
line_exists = abap_true.
EXIT.
ENDLOOP.
5. 避免不必要的表读取
TRY.
DATA(row) = my_table[ key = input ].
CATCH cx_sy_itab_line_not_found.
RAISE EXCEPTION NEW /clean/my_data_not_found( ).
ENDTRY.
" anti-pattern
"IF NOT line_exists( my_table[ key = input ] ).
" RAISE EXCEPTION NEW /clean/my_data_not_found( ).
"ENDTRY.
"DATA(row) = my_table[ key = input ].
字符串
1. 使用 ` 来定义文字
CONSTANTS some_constant TYPE string VALUE `ABC`.
DATA(some_string) = `ABC`. " --> TYPE string
" anti-pattern
DATA some_string TYPE string.
some_string = 'ABC'.
" anti-pattern
DATA(some_string) = |ABC|.
2. 使用|
来动态连接字符串
DATA(message) = |Received HTTP code { status_code } with message { text }|.
" anti-pattern
DATA(message) = `Received an unexpected HTTP ` && status_code && ` with message ` && text.
布尔值
1.使用XSDBOOL
设置布尔变量
DATA(has_entries) = xsdbool( line IS NOT INITIAL ).
" anti-pattern
IF line IS INITIAL.
has_entries = abap_false.
ELSE.
has_entries = abap_true.
ENDIF.
条件
1. 优先选择IS NOT
而不是NOT IS
IF variable IS NOT INITIAL.
2. 保持较低的嵌套深度
MESSAGE
自定义消息
定义消息类统一处理提示消息
T-Code SE91 创建消息类
REPORT XX NO STANDARD PAGE HEADING MESSAGE-ID ZYC.
代码: MESSAGE E000 WITH sy-datum.
系统消息
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
INTO msgtext
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
内外格式转换
lv_matnr = |{gt_mat-matnr ALPHA = OUT}|.
lv_matnr = |{gt_mat-matnr ALPHA = IN}|.
Note:
DATA(lv_var) = |{ LS_SELECTED_ROW-VGBEL ALPHA = IN }|. " lv_var 前面可能会存在空格