ABAP 内表的最佳实践

使用合适的内表类别

选择合适的表类别。对于小型表,索引或散列键可能是多余的,但对于大表,始终使用以下规则:

  • 索引访问:标准表
  • 索引访问和键访问:排序表
  • 只访问关键字:哈希表

特别是对于行数较多的表格,必须谨慎选择合适的表格类别。以下建议主要源自处理速度要求:

  • 标准表

如果主要访问类型是顺序处理或索引访问,则可以始终使用该表类别。填写标准表时,应使用 APPEND 添加行,其他访问则使用索引规范(相应语句的 INDEX 语句)。理想情况下,补充数据的过程应与其他访问数据进行分离。在进行显式排序后,还可以使用二进制搜索(BINARY SEARCH)来优化键访问(自由键),这样就可以为顺序处理(LOOP)等确定一个入口点。不过,由于采用线性搜索,如果内部表的主要访问类型是键访问,那么大型标准表(超过 100 行)就不适合作为表类。

  • 排序表

如果既需要快速键访问,又需要索引访问,还需要在填表时对行进行排序,那么这类表就很有用。此外,排序表还适用于 LOOP 循环中的部分顺序访问,其中在 WHERE 条件中指定了表键的第一部分。最后,在无法定义唯一键的情况下,具有模糊键的排序表是哈希表的唯一选择。

  • 哈希表

如果键访问是数据表的核心操作,那么这种表类就很有用。

选择适当的方式来访问表行

可以通过访问各个行(使用 READ TABLE 或表表达式)或按顺序(使用 LOOP AT)来读取内表。在这两种情况下,读取时可以通过三种方式存储内表的访问行:

  • INTO 将行复制到结构中
  • ASSIGNING 将行分配给字段符号,这使得可以直接寻址该行
  • REFERENCE INTO 创建对行的引用

表格表达式也是如此,只是根据结果的类别来选择行存储类型。

原则是:

  • 如果行类型较窄且不需修改读取的行,则使用工作区(结构)
  • 如果行类型为宽或深并且要修改读取的行,则使用字段符号
  • 如果行类型为宽或深并且要传递对读取行的引用,请使用引用

出于性能原因,最好避免循环中的行复制

细节

选择输出行为的标准一方面是处理速度,另一方面是要对读取行执行的操作:

  • 如果要修改读取行的内容,通常应使用添加 ASSIGNING 或(在表表达式的情况下)适当的结果。这允许使用值语义直接访问行,并且无需稍后进行 MODIFY 操作。
  • 如果需要对读取行的引用可以使用引用语义进行处理,则将使用添加 REFERENCE INTO 或(在表表达式的情况下)适当的结果。
  • 如果不修改读取行的内容,则可以使用这些过程中的任何一个。表的行类型对于性能非常重要。如果表行很宽或包含较深的组件(例如,字符串或其他表),则如果使用 ASSIGNINGREFERENCE INTO 而不是 INTO,读取通常会更快。它们的使用方式是选择使用两者中哪一个的决定因素。

当处理行平坦且占用空间不超过大约 1KB 的表时,使用 INTO 进行复制(至少对于 READ 语句而言)比配置动态访问所需的管理更快。对于语句 LOOP,这些成本仅产生一次,因此始终建议在一定数量的行以上使用 ASSIGNINGREFERENCE INTO。相反,如果要修改目标区域而不影响内部表,则应始终使用 INTO

不好的方式

以下源代码显示了将内表的行分配给工作区的目的,目的是修改读取的行。然而,对于此修改,需要附加语句 MODIFY,并且每次循环都会发生两个不必要的复制过程。

ABAP 复制代码
LOOP AT itab INTO wa.
   ...
   wa = ...
   MODIFY itab FROM wa.
ENDLOOP.

好的方式

以下源代码更正了上面的示例;这里,使用字段符号来直接访问以修改读取的行。不会产生不必要的复制成本。

ABAP 复制代码
LOOP AT itab ASSIGNING <fs>.
   ...
   <fs> = ...
ENDLOOP.

不要在循环中修改整个表

循环访问内表时,不要执行会修改整个表体的语句。仅逐行修改表。

除了用于编辑内表中各个行的语句之外,还可以使用其他语句来寻址和修改表的整个主体。例子:

  • 适用于整个内表的所有分配类别
  • 使用 CLEAR 或 FREE 删除整个内表
  • 目标范围内的操作,例如 SELECT INTO TABLE

您不能使用跨内部表的循环来执行对表的访问,从而一次性修改整个表主体。

对整个表体的修改访问通常会产生运行时错误,并且至少会产生不可预测的程序行为。如果可以静态检测到这一点,则当使用相关表操作时,类内以及具有可静态检测的辅助键的循环中也会发生语法错误。否则,出于兼容性原因,语法检查只会返回警告。

使用 RETURN 退出例程

仅使用 RETURN 退出方法、函数、表单等。不要使用 CHECKEXIT

不要在对话框模块和事件块中实现逻辑

相反,调用封装逻辑实现的相关类方法。

除了过程之外,还有两种类型的处理块。但是,它们没有参数接口,并且不允许声明本地数据:(AT SELECTION-SCREENGET 是例外,但不应被利用):

  • 对话模块:对话模块使用语句 MODULE 引入,并使用语句 ENDMODULE 结束。这些模块形成了经典 dynpro 和相关 ABAP 程序之间的功能接口。它们是从 dynpro 流逻辑内部调用的。
  • 事件块:事件块由相应的关键字引入,并由下一个处理块隐式结束。当相关事件发生时,ABAP 运行时环境会触发事件块的处理。

事件块用于:

  • 加载程序(LOAD-OF-PROGRAM)
  • 报告可执行程序(带逻辑数据库)处理过程中发生的事件(初始化、开始选择、获取、结束选择)
  • 选择屏幕事件(AT SELECTION-SCREEN ...)
  • 经典列表处理的列表事件(AT LINE-SELECTION、AT USER-COMMAND)

原则: 不要在对话框模块和事件块中实现逻辑

由于无法在对话框模块和事件块中声明本地数据,因此您无法实现任何有用的程序逻辑。因此,对话框模块和事件块------只要它们仍然是必要的------应该只包含一个方法调用。如果您一致使用 ABAP 对象,则仅需要以下元素:

  • 在使用类池以外的程序类型的情况下,将 LOAD-OF-PROGRAMINITIALIZATION 作为程序构造函数
  • 处理经典 dynpros 和选择屏幕时的对话框模块和 AT SELECTION-SCREEN
  • 用于后台处理的可执行程序中的 START-OF-SELECTION 为了提高可读性,您应该始终显式指定该语句(尽管在许多情况下它是可选的)
  • 尽管在语法上是可能的,但您不应在程序中多次指定事件块

Note:在函数组中使用 LOAD-OF-PROGRAM 基本上与在全局类中使用静态构造函数相同。在可执行程序中,如果需要评估使用 SUBMIT 传递的任何参数,则可以使用 INITIALIZATION 代替。

例子

以下源代码显示了包 SABAP_DEMOS_CAR_RENTAL_DYNPRO 中功能组 DEMO_CR_CAR_RENTAL_SCREENS 的 PAI 模块。可以使用事务 DEMO_CR_CAR_RENTAL 调用此包中的屏幕。这些对话框模块遵循上述规则。它们不包含自己的实现。他们调用函数组的本地类的方法。

ABAP 复制代码
MODULE cancel INPUT.
  screen_handler=>cancel( ).
ENDMODULE.

MODULE user_command_0100 INPUT.
  screen_handler=>user_command_0100( ).
ENDMODULE.

MODULE customers_mark INPUT.
  customer_table=>mark( ).
ENDMODULE.

MODULE reservations_mark INPUT.
  reservation_table=>mark( ).
ENDMODULE.

仅在特殊情况下使用宏

尽可能避免使用宏。宏有几个缺点:

  • 无法调试;
  • 没有语法检查;
  • 隐式调用接口;
  • 没有接口参数类型检查。

为隐式调用的消息创建锚点

当您隐式传递消息属性(类、数字、参数)时,例如通过函数或方法调用,或者使用变量,使用锚点让消息可以在使用位置列表中搜索。

可以通过以下方式完成(因为它是在标准中完成的):

ABAP 复制代码
IF 1 = 2. 
    MESSAGE i123(abc) ... . 
ENDIF.

或者:

scss 复制代码
MESSAGE i123(abc) ... INTO sy-msgli. "and then use sy-msg* fields to pass the message attributes
相关推荐
IT_陈寒4 小时前
闭包陷阱让我加了两天班,JavaScript你真行
前端·人工智能·后端
易协同低代码5 小时前
通达OA核心类库TD类深度解析
后端
Gopher_HBo5 小时前
Go语言学习笔记(十八)Gin处理Session
后端
谭光志6 小时前
工具塞满上下文窗口怎么办?深度拆解 AI Agent Tool Search 按需加载实现原理
前端·后端·ai编程
她说..6 小时前
Java 默认值设置方式
java·开发语言·后端·springboot
foggyprojects6 小时前
从0开始,一句话启动AI DataAgent
后端·数据分析·ai编程
郡杰6 小时前
一些基础和问题解决
后端
陈随易7 小时前
前端项目部署只要30秒
前端·后端·程序员
YIAN7 小时前
从零手写文件读取 MCP 服务:一文吃透 Model Context Protocol 全链路通信原理
前端·后端·mcp
Imchendiana7 小时前
《狂人日记NO.9》— 前后端一把梭,我的全栈实录
前端·后端