当你将源代码模块化时,你将一连串的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>: 程序块
子程序的类型:
- 内部子程序
- 在被调用的同一程序中定义的子程序。
- 可以访问在 ABAP/4 主程序中声明的所有数据对象。
- 外部子程序
- 在被调用的程序之外定义的子程序。
- 需要使用
<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 个字符。
- 当你创建一个功能组或功能模块时,主程序和包含程序会自动生成。
- 功能组封装了数据。
如何创建函数组:
- 转到事务码
SE80对象浏览器。 - 在下拉菜单中选择程序。
- 写下你想创建的功能组的名称。一般来说,用户制作的功能组以 "Z "开头,例如:
<Z_FUNCTION_GROUP_NAME>。 按回车键。 - 注意,如果用户勾选了创建 头文件
TOP包含的选项,那么顶层头文件TOP包含将被默认创建。
如何创建函数模块:
-
创建一个函数组(例如
ZCAL)。 -
创建一个功能模块,设置属性,如(功能组、应用程序、短文和进程类型)并保存。
-
包含文件 "
LZCALU01"将有第一个功能模块的源代码。 -
包含文件 "
LZCALTOP"将有全局数据。 -
主程序 "
SAPLZCAL"包括:- 全局数据 包括文件 "
LZCALTOP" - 功能模块包括文件 "
LZCALUXX" - 用户定义的包含文件 "
LZCALF...", "LZCALO..." 和 "LZCALI..."
- 全局数据 包括文件 "
-
定义接口参数和异常情况
-
编写源代码
-
激活功能模块
-
测试功能模块 - 单元测试和调试
-
记录和发布一个函数模块