SAP ABAP 系统里的标准实现,有时会发现下面这种代码:
IF 1 = 0.
然后把逻辑写在这个永远都不可能执行到的 IF 分支里。比如下图这个 SAP CRM 里的标准类 CL_CRM_MDG_BP_CRGRP:
我查看了一下,这个类创建于 2009 年。
这个写法有什么作用?
我们把视野放开阔一点,注意到这行 IF 语句的下一行,即是将 Message Class 消息类 CRM_MDG_CORE 里编号为 034 的消息,通过 add_message 方法,显示在 WebClient UI 界面上。
我们使用事务码 SE91,定位到编号为 034 的这条消息,点击工具栏的 Where Used List 按钮,想查询这条消息到底被哪些 ABAP 类和程序所使用到:
从查询的结果来看,一目了然。原来,针对 ABAP Message 进行的 Cross Reference 即 Where Used List 查询,只能检测到那些通过 MESSAGE 关键字抛出的消息,即下图查询结果里这些包裹在 IF 1 = 0 分支里的 MESSAGE 语句。
然而,MESSAGE 一旦执行,在不同的执行上下文,抛出不同类型的消息,其表现行为都有所差异。
因为我们讨论的代码在 WebClient UI 运行环境下执行,显然不需要 MESSAGE 语句像在 SAPGUI 环境下,执行时弹出一个对话框,因此我们将 MESSAGE e034(crm_mdg_core) 放在永远不可能进入的 IF 1 = 0 分支内,起到的作用是,让 ABAP Message Text 的 Cross Reference 即 Where Used List 功能,能够顺利捕捉到这条消息的使用情况,同时又不让这段代码真的被执行。这算是一个非功能性编程的例子吧。
我当时把这个案例,发在了 SAP 社区上,引起了大家的热烈讨论。
有朋友给出了另一种替代方案,使用下列语句:
MESSAGE e034(crm_mdg_core) INTO lv_message.
这条语句将 CRM_MDG_CORE 里编号为 034 的文本内容,写入变量 lv_message 之中。虽然引入了一个随后根本不会被读取的变量 lv_message, 但是确实消除了会令有些人费解的 IF 1 = 0 分支。
ABAP Extended check 会对这种定义了变量但却又没有读取它的行为提出抱怨(warning),但好在可以通过 Pragma ##NEEDED 来屏蔽。