SAP 模块化:宏,子例程和函数模块

473 阅读5分钟

当你将源代码模块化时,你将一连串的ABAP语句放在一个模块中。然后,不要把所有的语句放在你的主程序中,你只需调用该模块。当程序被生成时,模块化单元中的源代码被视为实际存在于主程序中。

模块化的要求:

  • 改善程序的结构
  • 易于阅读代码
  • 易于维护代码
  • 避免冗余,促进代码重用

在 SAP ABAP 中的各种模块化技术

  • 使用宏
  • 使用包含文件
  • 子程序
  • 函数模块

现在,让我们详细了解一下每一个模块:

ABAP 宏

如果你想在一个程序中多次重复使用同一组语句,你可以把它们包含在一个宏中。

你只能在定义宏的程序中使用它,而且只能在其定义之后的程序行中调用它。

宏对长计算或复杂的 WRITE 语句很有用。

语法:

DEFINE <macro_name>

'Macro Statements

END-OF-DEFINITION

宏可以使用参数 &N,其中 N=1,2,3...

例如:

DATA: number1 TYPE I VALUE 1.

DEFINE increment.

    ADD 1 to &1.

    WRITE &1.

END-OF-DEFINITION.

Increment number1.

WRITE number1.

包含程序

包含程序只用于源代码的模块化,没有参数接口。

包含程序允许你在不同的程序中使用相同的源代码。如果你有冗长的数据声明,想在不同的程序中使用,它们就会很有用。

Include <include program Name>

请注意:

  • 包含的程序不能调用自己
  • 包含程序必须包含完整的语句
INCLUDE ZILX0004.

WRITE: / 'User', SY-UNAME,/ 'Date', SY-DATUM.

================================

PROGRAM ZRPM0001.

INCLUDE ZILX0004.

子程序

子程序是你可以在任何 ABAP 程序中定义的程序,也可以从任何程序中调用。子程序通常在内部调用,也就是说,它们包含本地经常使用的代码或算法的部分。如果你希望一个函数在整个系统中可重复使用,请使用一个函数模块。

语法结果如下:

FORM <Subroutine> [<pass>].

    <Statement block>.

ENDFORM.

这里面的:

  • <Subroutine> = 子程序的名称
  • <pass> = 被传递的参数
  • <Statement block>: 程序块

子程序的类型:

  1. 内部子程序
  • 在被调用的同一程序中定义的子程序。
  • 可以访问在 ABAP/4 主程序中声明的所有数据对象。
  1. 外部子程序
  • 在被调用的程序之外定义的子程序。
  • 需要使用 <pass> 选项或在内存的共同部分声明数据对象。

调用子程序

内部子程序:

PERFORM <subroutine> [<pass>]

<subroutine> = 子程序的名称

<pass> = 被传递的参数

在主程序中声明的数据是自动可用的。

外部子程序:

PERFORM <subroutine>(<Program>) [<pass>].

PERFORM <subroutine> (<Program>) [<pass>] [IF FOUND].

PERFORM (<subroutine>) IN PROGRAM  (<Program>) [<pass>] [IF FOUND].

PERFORM <index> OF <subroutine1> <subroutine2> <subroutine3> [<pass>].
  • 在子程序中允许嵌套调用(即在 FORM... ENDFORM 中的 PERFORM )。
  • 递归调用也是可能的。
  • 要定义本地数据,请在 FORM 之后使用 DATA 语句。每次进入子程序,数据都会被重新创建(有一个初始值),并在最后(从堆栈)释放。
  • 要定义在子程序中使用的全局数据,请在 FORM 之后使用 LOCAL 语句。这些值在你进入子程序时被保存,然后在结束时被释放(从堆栈中)。

函数模块

函数功能模块是一种可重用的子程序,可以从其他 ABAP 程序中调用。它可以接受输入参数并返回输出参数。它们通常用于在 SAP 系统中执行常见的业务逻辑。

功能模块是任何人都可以使用的通用 ABAP/4 例程。事实上,有大量的标准函数模块可用。

功能模块被组织成功能组:逻辑上相关函数的集合。一个功能模块总是属于一个功能组。

语法:

FUNCTION <function module>

    <Statements>

ENDFUNCTION.

与功能模块相关的重要信息

  • 管理员
  • 导入 Import /改变 Changing /导出 Export 参数。
  • 表参数 Table/异常参数 Exceptions。
  • 文档 Documention
  • 源代码 - L<fgrp>U01 .<fgrp> 是功能组
  • 全局数据 - L<fgrp>TOP .功能组的全局数据- 可在功能组的各个功能模块中访问。
  • 主程序 - SAPL<fgrp> .包含了该功能组的所有包含文件的列表

调用函数模块:

调用一个功能模块

要调用一个函数模块,使用 CALL FUNCTION 语句:

CALL FUNCTION <module>

[EXPORTING  f1 = a 1.... f n = a n]

[IMPORTING  f1 = a 1.... f n = a n]

[CHANGING   f1 = a 1.... f n = a n]

[TABLES     f1 = a 1.... f n = a n]

[EXCEPTIONS e1 = r 1.... e n = r n [ERROR_MESSAGE = r E]    

[OTHERS = ro]].

函数组

功能组是功能模块的容器。事实上,有大量的标准函数组。一个功能组中的所有功能模块都可以访问该组的全局数据。

像可执行程序(类型 1 )和模块池(类型 M )一样,功能组可以包含屏幕、选择屏幕和列表。

  • 功能组不能被执行。
  • 一个功能组的名称最多可以有 26 个字符。
  • 当你创建一个功能组或功能模块时,主程序和包含程序会自动生成。
  • 功能组封装了数据。

如何创建函数组:

  1. 转到事务码 SE80 对象浏览器。
  2. 在下拉菜单中选择程序。
  3. 写下你想创建的功能组的名称。一般来说,用户制作的功能组以 "Z "开头,例如:<Z_FUNCTION_GROUP_NAME> 。 按回车键。
  4. 注意,如果用户勾选了创建 头文件 TOP 包含的选项,那么顶层头文件 TOP 包含将被默认创建。

如何创建函数模块:

  1. 创建一个函数组(例如 ZCAL)。

  2. 创建一个功能模块,设置属性,如(功能组、应用程序、短文和进程类型)并保存。

  3. 包含文件 "LZCALU01 "将有第一个功能模块的源代码。

  4. 包含文件 "LZCALTOP "将有全局数据。

  5. 主程序 "SAPLZCAL "包括:

    • 全局数据 包括文件 "LZCALTOP"
    • 功能模块包括文件 "LZCALUXX"
    • 用户定义的包含文件 "LZCALF...", "LZCALO..." 和 "LZCALI..."
  6. 定义接口参数和异常情况

  7. 编写源代码

  8. 激活功能模块

  9. 测试功能模块 - 单元测试和调试

  10. 记录和发布一个函数模块