RPGLE中GOTO和EXSR有什么重要区别
这两个操作代码都会导致代码的执行跳转到过程中的不同点,但它们有一些差异。GOTO
是两者中更简单的,作为一个无条件的跳转命令,本质上是"去这里并开始执行那里的任何东西"。这是编程语言中最古老的命令之一,它的使用在今天通常不受欢迎。 1970年代"结构化编程"哲学的目标之一是用概念上更高的结构取代GOTO
,这些结构更好地描述了程序员的意图是什么,并且通过阅读它更容易理解该意图。您可以在此处找到列出的替换操作代码。
EXSR
是执行子例程的命令。虽然 RPG 没有将其列为结构化编程操作,但它旨在实现提高代码清晰度、减少错误和最小化代码重复的相同目标。它就像一个GOTO
,因为您无条件地跳转到新的代码段,但该段代码是过程或程序中的命名子例程。 无论您是只想更清楚地命名代码部分,还是希望从多个位置调用一个部分,或者是否要利用相关的操作代码LEAVESR
,这都很有用,这是一种简单的方法,可以在您到达ENDSR
之前退出子例程并返回到您在EXSR
之后执行的代码部分。GOTO
也可以通过使用两个标签来做到这一点,用TAG
操作标记,但它通常不太清楚,你必须维护一个标签列表来保持你跳来跳去的方式。
值得注意的是,结构化操作代码可以做的任何事情都可以通过GOTO
来完成,但这并不能使以这种方式编写代码成为一个好主意。更高的命令是为了方便人们而发明的,而不是为了方便计算机。 原则上,它们应该编译成非常相似的机器代码,但在记录程序员的思维过程和意图方面存在巨大差异。
还值得注意的是,RPG有两个不同级别的子例程,而大多数编程语言只有一个。子例程存在于过程或程序中,更类似于GOTO
或结构化编程操作。它没有可以传递给它的参数或作用域为它的变量。
过程更像是在其他编程语言中可以找到的函数和子例程。它可以有本地范围的变量(很有用,所以你不必记住手动清除它们),它可以传递参数(很有用,所以你不必在主程序中声明那么多临时变量),它可以返回一个值(变量或数据结构),以便你可以将一个值传递回你的主程序。这些都使过程成为更灵活的选项,并促进更好的代码重用,但我发现了调试它们的一些缺点。RPG 调试工具(如DUMP
操作)只有在过程中调用转储时才会正确显示变量的值。 这不适用于将所有错误都由一个程序范围的*PSSR
子例程收集的编码样式。您必须更多地利用MONITOR
操作,或者在每个过程中放置一个带有DUMP
的*PSSR
。此外,虽然 RPG 将错误传递到调用堆栈到调用过程,类似于许多编程语言,但基本的 RPG 语言没有为代码提供内置工具来抛出错误,这对于过程有效传达故障通常很有用。我使用从 IBM RPG 异常和错误处理红皮书中学到的ThrowError
过程。如果正确应用这些技术,它们可以生成健壮的代码,但它确实使过程比子例程更难编码,特别是对于初学者或简单程序。我建议先掌握子例程和其他结构化编程结构,然后再转到过程。
正如我在对他的回答的评论中提到的,@Mike有一个非常好的答案,但让我提供一个不同的结论。如今,大多数学习RPG的人已经知道如何使用与ILE过程非常相似的结构进行编程。RPG的子套路和GOTO是过去时代的遗物。不要尝试使用它们。它们仅依靠全局变量与程序的其余部分进行通信。这种做法降低了代码的可重用性,并且可以说是可读性,因为程序中任何位置的任何例程都可能导致任何给定子例程失败。像 *INZSR 和 *PSSR 这样的魔术子例程是随编译器的心血来潮调用的,是的,我知道它们何时被调用,但我不能显式调用它们,使错误处理充其量是神秘的。
最佳做法是使用**free
编写现代 RPG 代码,省去循环,仅使用子过程进行代码重用。魔术子例程甚至无法在此环境中工作,因为循环未编译。子过程可以执行子例程可以执行的所有操作,甚至更多。它们提供局部变量、静态变量,如有必要,可以使用全局变量。它们具有参数和返回值。它们通过消除对全局变量的需求使程序更加模块化,这也使它们更具可读性,因为它们不再需要受到程序其他部分代码的影响。
所以不,如果你能帮助它,不要使用 EXSR 或 GOTO。更喜欢 CALLP,您的程序将更像您习惯的那样工作,除非您在现有程序中遇到它们,否则您不必担心旧的过时操作码。