首页 > 其他分享 >SAP 某 ABAP 系统标准类中仅有 5.4% 公有属性被 READ-ONLY 修饰,原因竟然是…

SAP 某 ABAP 系统标准类中仅有 5.4% 公有属性被 READ-ONLY 修饰,原因竟然是…

时间:2024-08-10 18:59:16浏览次数:12  
标签:READ 类中仅 ABAP iv ONLY test 属性

笔者之前的文章被很多人误解的 ABAP 关键字:READ-ONLY 发布之后,有朋友询问,SAP 标准实现里,对这个 READ-ONLY 使用的场景多吗?

其实这个问题我们可以自己找到答案。

思路是选择一个 SAP 系统,统计出类的总数,这些类总共定义了多少个属性,其中有多少属性,使用了 READ-ONLY 来修饰。

首先打开 SE80 的 Repository Information System,这里仅能通过类属性的名称进行统计。

但我们的需求是,根据类公有属性经过 READ-ONLY 修饰与否来统计,所以这条路走不通。

下图展示了 SE80 中的 Repository Information System,仅能通过类属性的名称进行查询。

那么还是直接找表吧。类属性的名称和 READ-ONLY 标志位,肯定是存储在后台某张数据库表里的。

笔者本公众号过去大量的文章,通过很多例子,反复介绍了如何自行查找存储了指定信息的数据库表。

通过文章里介绍的技巧,我们找到了数据库表 SEOCOMPODF.

这张表的 CLSNAME,CMPNAME 和 ATTRDONLY 字段,分别存储了类的名称,类属性的名称,以及类属性是否被 READ-ONLY 修饰的状态信息。

笔者的 SAP CRM 系统上,总共有 260 万个类属性(包含 SAP 标准实现和 Z 实现)。

其中 READ-ONLY 属性有 9 万 5 千个,占总数的 3.6% 左右。

当然我们可以把统计范围再缩小一点:只统计 SAP 标准类里的 Public 属性,看其中到底有多少,启用了 READ-ONLY.

在类名称 CLSNAME 的选择条件里,将那些通过 Y 或者 Z 开头的类过滤掉。

Exposure 字段统计条件为 2,代表 Public 属性。

在笔者系统里,总共有 175 万个公有属性。

其中 9 万 4 千个公有属性被 READ-ONLY 修饰,占总数 5.4% 左右。

这个统计数据充分说明,SAP 自身也是严格按照 Clean ABAP 编程规范里的规则,慎用 READ-ONLY 来进行开发的。

SAP 建议慎用 READ-ONLY 的原因,在笔者前一篇文章已经详细论述过,本文不再赘述。

被很多人误解的 ABAP 关键字:READ-ONLY

ABAP 和类公有属性的 READ-ONLY 相关的,还有另一个概念:修改保护(Change protection),有时也称写保护(Write Protection).

通过实际的例子来介绍修改保护的概念。

下面的代码可以通过编译,但是执行时,会遇到运行时错误:

MOVE_TO_LIT_NOTALLOWED_NODATA
 
FORM read_only USING iv_i TYPE int4.
  WRITE:/ iv_i.

  iv_i = 2.
ENDFORM.

START-OF-SELECTION.

PERFORM read_only USING 1.

错误消息:

A new value is to be assigned to the field, although this field is entirely or partly protected against changes.

大意是 subroutine 的输入参数 iv_i 是被修改保护的,而其实现体内的代码,试图对这个被保护的变量赋值,因此产生了运行时错误。

在 ABAP 调试器里,能清楚看到输入参数 iv_i,被标注了 Read Only 的 Checkbox.

Subroutine 已经是一种被废弃的语法,不推荐再使用。

那么我们把上述代码移植到 ABAP 类里面,结果又如何呢?

下面代码第 12 行,试图在类的方法里,修改输入参数的值:

REPORT zbook.

CLASS lcl_test DEFINITION.
  PUBLIC SECTION.
    CLASS-METHODS: test IMPORTING iv_i TYPE int4.
ENDCLASS.

CLASS lcl_test IMPLEMENTATION.
  METHOD: test.
    WRITE:/ iv_i.

    iv_i = 45.
  ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
  lcl_test=>test( iv_i = 4 ).

这段代码无法通过编译,遇到错误消息:

the field iv_i cannot be modified.

如果把上图第 12 行代码注释掉,就可以通过编译,成功激活代码。

在调试器里,可以看到输入参数的 READ-ONLY Flag 被勾上了。

看来面向对象的编程范式确实比 Subroutine 健壮很多,可以从语法检查层面规避很多问题。

如果给输入参数 iv_i 添加另一个 VALUE 关键字进行修饰,如下图图例 1 的位置所示,在运行时我们发现,该输入参数的 READ-ONLY 标志位,已经被清除了。

这样一来,在方法内部,可以对这个输入参数进行赋值了。

VALUE 关键字其实蕴含了另一个关于 ABAP 方法调用时,参数传递方式的知识点。

用 VALUE 关键字修饰输入参数,意思就是参数传递采取传值方式进行。

下图第 18 行的实际输入参数 lv_input,在调用 test 方法时,该参数的实际值 4,被传递进 test 方法内,拷贝给 test 的形式参数 iv_input.

因此在 test 方法内部,第 11 行的 iv_i = 45, 修改的是形式参数 iv_i 的值,从拷贝进来的 4 修改成 45,对实际参数 lv_input 没有任何影响,其值仍然为 4 不变。

而如果去掉 VALUE, 参数传递采取 ABAP 默认的引用传递,此时形式参数 iv_i 和实际输入参数 lv_input 具有同一个引用,而 ABAP 输入参数是具有修改保护的,因此在引用传递的前提下,方法内试图输入参数 iv_i 的值,会遇到上面提到的语法错误:the field iv_i cannot be modified.

ABAP 方法和函数调用的参数传递,默认都是引用传递。但是在 RFC 函数的参数声明里,必须使用值传递方式。

希望本文介绍的 READ-ONLY 和修改保护的知识点,能够帮助大家弥补上相关的知识漏洞,感谢阅读。

标签:READ,类中仅,ABAP,iv,ONLY,test,属性
From: https://blog.csdn.net/m0_55213370/article/details/141094678

相关文章

  • [Java并发]ThreadLocal补充
    ThreadLocal缺点及解决方案每个Thread上都有一个threadLocals属性,它是一个ThreadLocalMap,里面存放着一个Entry数组,key是ThreadLocal类型的弱引用,value是对用的值。所有的操作都是基于这个ThreadLocalMap操作的。但是它有一个局限性,就是不能在父子线程之间传递。即在子线程中无......
  • SQL Server数据库Owner导致事务复制log reader job无法启动的解决办法
    问题场景SQLServer事务复制在正常创建发布和订阅之后,logreaderJob启动异常,出现“Theprocesscouldnotexecute‘sp_replcmds’onxxx”等异常日志导致代理服务无法正常启动。 异常现象参考下图,异常日志如下Errormessages:Theprocesscouldnotexecute‘sp_re......
  • SpreadJS 个人学习及项目遇到的一些问题的总结
    最近公司有SpreadJS的部分,刚接触挺迷茫的,因为这个文档有点不清晰,有些属性啥的,看到跟没看一样,他没有那种效果图例说明,属性说的就很简单,看了大半天感觉没看出来啥,等开始做的时候就各种问题,感谢有同事替我们负重前行,趟过了很多的坑,这导致比预期入手好很多,目前只是算简单的上手,所以就......
  • 解决端口号占用问题:Spring Boot报错,Web server failed to start. Port 8080 was alrea
    报错信息:Webserverfailedtostart.Port8080wasalreadyinuse.报错原因:端口被占用解决方法:解决方法一:修改端口修改配置文件,加上参数:server.port=8014或者在application.yml文件中添加server:port:8014在访问时,替换对应的端口号即可解决方法二:关闭占用端口的......
  • 解决Spring报错:Failed to read candidate component class: file [ ]; nested exceptio
    使用IDEA建立一个很基础的Spring项目时,之前用xml方式,写bean标签一直正常使用,改用注解方式后发现报错,显示:Exceptioninthread"XXX"org.springframework.beans.factory.BeanDefinitionStoreException:Failedtoreadcandidatecomponentclass:file[XXX.class];nestedexc......
  • ThreadLocal
    为什么多线程需要加锁1.ThreadLocal的介绍从Java官方文档中的描述:ThreadLocal类用来提供线程内部的局部变量。这种变量子在多线程环境下访问(通过get和set方法)时能保证各个线程的变量相对独立于其他线程内的变量,ThreadLocal实例通常来说都是privatestatic类型的,用于关联......
  • Thread、ThreadPool、Task之间的联系
    1、ThreadPool线程池一个应用程序最多只能有一个线程池。线程池是一种多线程处理形式,通过QueueUserWorkItem()将任务添加到队列中,然后创建线程(后台线程,又称工作者线程)自动启动这些任务来处理。其中,最小线程数即核心线程数(corePoolSize)是线程池中长期保持的线程数,即使它们处于闲置......
  • LLM-文心一言:connectTimeout , readTimeout
    在网络编程和HTTP客户端库(如ApacheHttpClient、OkHttp、Retrofit等)中,connectTimeout和readTimeout是两个重要的超时设置,它们用于控制网络请求的行为,以提高应用的健壮性和用户体验。connectTimeout(连接超时)connectTimeout指的是客户端尝试与服务器建立TCP连接时等待的最长时......
  • 错误处理和 threading.Thread() 问题
    我对Python比较陌生,最初我按照我喜欢的方式进行错误处理。我想使用PySimpleGUI添加进度条,经过一些研究发现我需要使用线程。一旦我实现了线程,错误处理就不再像我想要的那样工作,而且我似乎不知道如何修复它。我将提供进度条之前和之后的代码,但是之后的代码没有任何错误处理。......
  • MySQL this is incompatible with sql_mode=only_full_group_by-错误解决
    mysql执行groupby时遇到下面提示:SELECTlistisnotinGROUPBYclauseandcontainsnonaggregatedcolumn'crm.b.id'whichisnotfunctionallydependentoncolumnsinGROUPBYclause;thisisincompatiblewithsql_mode=only_full_group_by原因:在sql执行时,出现该原......