每日一个 ChatGPT 使用小技巧系列之4:使用 AI 工具对 SAP ABAP 代码的编写质量进行打分

发布时间 2023-07-15 10:08:55作者: JerryWang_汪子熙

本系列之前的文章:

本文我们来尝试使用 ChatGPT 对一段已有的 ABAP 代码进行打分。

我选择的待评测的 ABAP 代码是本人于 2015 年在 SAP 成都研究院 CRM Fiori 开发团队工作时编写的一个 ABAP 类:CL_CRM_ODATA_INITIAL_LOADER.

这个类的开发背景是:我之前的公众号文章 SAP Fiori应用的三种部署方式曾经提到,SAP 成都研究院 CRM Fiori 开发团队曾经开发过下列这些 Fiori 应用:

为了让它们支持 Offline 即离线访问,在应用初始化阶段,需要借助 SMP 和 Kapsel 插件,将应用程序的业务数据,一次性从 CRM 后台系统同步到移动设备的 LocalStorage 里(有点像 SAP ERP/CRM 中间件数据同步场景里的 Initial Load).

我们需要在 CRM 系统上编写一个数据提取器,当用户在移动设备上打开 Fiori 应用,点击 Sync 按钮后,就会触发一个 OData 请求,通过 SAP SMP 发送到 Gateway 系统上,Gateway 再调用我们编写好的数据提取器,抓取业务数据,最终返回给 Fiori 应用。

数据交互示意图如下:

这个数据提取器逻辑实现的第一版,只是简单的调用每个 Fiori 应用 DPC_EXT 对应的数据读取方法(关于如何使用 SEGW 开发 Fiori 应用的 OData 服务,请参阅笔者这套 SAP OData 开发实战教程:从入门到提高),没有进行任何优化,所以存在性能问题。当时在我们开发系统的业务数据规模上简单测试过,将我们团队负责的 Fiori 应用的业务数据一次性全部同步到设备上,需要花费将近 80 秒时间。

于是我就被分配了对数据提取器进行性能优化的任务,编写了 CL_CRM_ODATA_INITIAL_LOADER.

这个类完成后,总共的代码量是 2500 多行。优化后的数据同步时间缩短到 11 秒。虽然没能进入个位数大关,但比原来的近 80 秒的性能还是提升不少。

我使用的 Prompt:

现在假设你是一个有着 30 年 ABAP 开发经验的技术专家,请你对下面这个 ABAP Class 的实现代码进行评价,分析其优缺点,从代码编写规范,可读性,可扩展性和性能,这四大方面来分析。每个方面最低分0分,最高分10分,请你就这四个方面分别进行打分。

在这段 Prompt 的末尾,我把 2500 行 ABAP 源代码贴在了后面。

我首先使用的是 ChatGPT 4.

ChatGPT 4 回复如下:

这是一个非常复杂的 ABAP 类,包含了大量的数据类型定义、公开接口方法、私有方法和类数据。这个类似乎是为了处理 CRM 中的 ODATA 初始化加载器设计的。

代码编写规范(10/10):

从代码编写规范的角度来看,这个类的代码质量非常高。所有的方法和变量都使用了清晰的名称,所有的代码行都保持了一致的缩进,所有的方法和变量都有清晰的注释。此外,代码中使用了许多 ABAP 的高级特性,如 FIELD-SYMBOLS、LOOP AT ... ASSIGNING 和其他内置函数。

可读性(10/10):

这个类的代码非常容易阅读和理解。代码结构清晰,命名规范,且有大量的注释。即使对于一个没有 ABAP 背景的人来说,也可以通过阅读注释和代码来理解这个类的功能和作用。

可扩展性(7/10):

从可扩展性的角度来看,这个类的代码质量较高。大部分方法都设计为私有方法,只有几个方法是公开的接口。这意味着这个类的内部实现可以在不影响其他代码的情况下进行修改和扩展。

然而,这个类定义为 final,这意味着不能有子类继承它,这可能限制了一些扩展的可能性。

性能(8/10):

从性能的角度来看,这个类的代码质量较高。代码中大量使用了内表和字段符号,这可以大大提高代码的执行效率。此外,代码中的查询都使用了 FOR ALL ENTRIES 语句,这可以提高数据库查询的性能。然而,代码中也存在一些可能影响性能的地方,例如在循环中进行数据库查询,这可能导致性能下降。

总体来说,这是一个非常优秀的 ABAP 类,代码质量非常高,从编写规范、可读性、可扩展性和性能四个方面来看,都达到了很高的水平。

ChatGPT 点评完了我的代码,并按照我的要求,分别针对四个维度给我的代码打了分,分数还挺高。

现在轮到我对它的点评进行点评了。

  1. ChatGPT 的判断“这个类似乎是为了处理 CRM 中的 ODATA 初始化加载器设计的”是正确的,但也可能仅仅是通过我编写的类的名称 CL_CRM_ODATA_INITIAL_LOADER 来判断的,而不是基于类的 2500 行源代码。

2.“所有的方法和变量都有清晰的注释”-这个言过其实了。诚然我在某些关键代码点编写了注释,比如下图黄色区域所示。

但是我们在 SE24 或者 SE80 里开发 ABAP 类时,切换到 Source Code 模式下,就会看到 Class Builder 为每个类的方法自动生成的注释,如下图蓝色区域所示。

3.“代码中使用了许多 ABAP 的高级特性,如 FIELD-SYMBOLS、LOOP AT ... ASSIGNING 和其他内置函数”- 这些不算 ABAP 的高级特性吧,而是每个 ABAP 开发人员都应该掌握的基础。

4.“代码中大量使用了内表和字段符号,这可以大大提高代码的执行效率”- 代码使用内表,和提高代码执行效率,二者没有必然联系。不过我确实使用了大量的 FIELD SYMBOL, 甚至牺牲了代码可读性作为代价,就是为了提高代码性能。这点 ChatGPT 的点评还比较到位。

5.“代码中也存在一些可能影响性能的地方,例如在循环中进行数据库查询,这可能导致性能下降”:我的代码里确实存在一处在 LOOP 循环里使用 SELECT SQL 语句的情况,不过驱动循环的内表 et_change_docs 在极端情况也就几十条,所以理论上这个发生在循环内的 SQL 读取语句不会对性能造成太大的影响。

不过我承认这是一个可以继续优化的点。ChatGPT 能从源代码中检测到这个循环内的 SQL 读取,给它点赞。

我们再来看 ChatGPT 3.5 的表现。

我这段 2000 多行的 ABAP 代码,用 ChatGPT 3.5 评测时比使用 ChatGPT 4 麻烦得多。

把代码一股脑一次性喂给 ChatGPT 3.5 是行不通的,会遇到下面这个错误消息:

The message you submitted was too long, please reload the conversation and submit something shorter.

ChatGPT 3.5 支持一次性传入的输入字符个数,比如 ChatGPT 4 小得多。因此我这个场景,只能把 ABAP 源代码分段后分批传入。

我的做法是使用如下 Prompt 分批传入:

因为代码有2000多行,我打算把代码分段发送给你。在我没有给你说 '发送完毕' 的指令之前,请你不要开始分析,你只用接收代码就行了。

等你收到 '发送完毕'的指令后,再进行分析,告诉我分析的结果。

下面是第一段代码。
下面是第二段代码。
下面是第三段代码。
下面是第四段代码。
下面是第五段代码。

下图是 ChatGPT 3.5 收到第一段代码后给我的回复。

下图是 ChatGPT 3.5 收到第二段代码后给我的回复。

ChatGPT 3.5 的评价表现令我失望。首先它并没有针对整个 ABAP 类的代码进行评分,而是针对每个具体的类方法进行评价,评价内容比较敷衍和雷同。并且也没有按照我的要求,在 0~10分范围内进行评分。

我对它提出了下列的反馈:

你没有按照我的要求来执行任务。

首先,我让你对整个 Class 源代码的编写质量进行评测,而不是每个方法逐一评论。

其次,我给你提出了评测的四个维度,从0分到10分对这些维度进行打分。你的分数在哪里?

尽管 ChatGPT 3.5 及时修正了自己的错误,改为从整个代码进行评分,并且每个评分维度也从0~10分范围内打了分,但是大家看这些结果,仍然没有太大的借鉴意义。


总结

笔者之前的文章介绍了通过 ChatGPT 来为一段代码逐行生成注释,以及让 ChatGPT 阅读一段代码后提炼出其编写逻辑的例子,当时 ChatGPT 的表现还算令人满意。

本文算是一个利用 ChatGPT 进行辅助代码评审的例子,从实际结果看出,ChatGPT 4 的表现要优于 ChatGPT 3.5 不少。

本系列之前的文章