ABAP 最佳实践:风格和指南

编写干净、令人愉快的代码的基本方法

Use Pretty-Printer

在设置中设置 Pretty-Printer 并在每次保存代码时运行它。

在项目指南中设置相同的 Pretty-Printer 设置,以避免同一系统中出现不同的格式。

使用命名约定

为您创建的每个代码或字典对象选择命名规则。使用它可以避免混淆。

此外,您可以设置代码检查器来检查命名约定。

使用 snake_case 命名法

在单词之间使用下划线命名变量、方法、类等,例如lo_table_container->get_sorted_table_data()。它是 ABAP 的标准约定。

使用一致的编码风格

如果某个语句有多种拼写,请选择其中一种拼写,并在整个开发工作中一致使用它。最好选择最准确反映该语句语义的拼写。

ABAP 中有许多替代语言结构,例如 (=、<>、>=等) 与 (EQ、NE、GE等)、数据声明、操作等。

选择一种替代方案(Alternative Language Constructs)并在开发过程中持续使用它。

替代语言结构是可以用不同方式编写的语句的一部分。造成这种情况的原因之一是该语言不断有新的发展。通常,出于向下兼容性的原因,会引入新的编码并保留旧的编码格式。

  • 如果您可以从一系列关系运算符(= 或 EQ、> 或 GT、< 或 LT、>= 或 GE、<= 或 LE)中进行选择,我们建议您选择一种运算符类型并在以下上下文中坚持使用:一个程序。带有 =、< 和 > 字符的变体被认为更现代,但也重载了这些字符。由两个字母组成的关系运算符与其他没有替代形式的关系运算符(例如 CO、CN 等)匹配得更好。
  • 与相同的布尔运算符 NOT相比,关系运算符 BETWEEN、IN、IS ASSIGNED、IS BOUND、IS INSTANCE OF、IS INITIAL 和 IS SUPPLIED 的附加 NOT 是更好的选择,可以提高可读性。例如,表达式 a IS NOT INITIAL 比逻辑上相同的表达式 NOT a IS INITIAL 更容易。这对应于比较表达式的定义,其中 a <> b 比 NOT a = b 更直观。
  • 声明性语句 DATA 和 TYPES 的 LENGTH len 相加优于括号 (len) 中指定的长度。然后,这与 CREATE DATA ... LENGTH 中使用的拼写相匹配。除此之外,很容易将带括号的形式误认为是动态标记。只有动态令牌才应使用此形式。
  • FIND 和 REPLACE 语句中的可选子句 SUBSTRING 可以与可选子句 REGEX 进行更明确的区分。
  • 在 Open SQL 中,逗号分隔的列表优于不带逗号的列表。使用逗号作为分隔符是在列表中使用表达式的前提。主机变量应始终由转义字符 @ 指示。
  • 在语句 EXPORT 和 IMPORT 的参数列表中,使用等号 (=) 而不是添加 FROM 或 TO。然后,该拼写将与其他调用(例如方法、函数模块和转换)中的参数列表中使用的拼写相匹配。
  • 始终使用语义上相同的加法 ACTUAL LENGTH,而不是语句 READ DATASET 的加法 LENGTH。这使得与类似添加 MAXIMUM LENGTH 的区别更加清晰。最后两个示例是向语言中添加新内容的典型方式,同时出于向下兼容性的原因保留旧拼写(以缩写形式)。

不好的习惯:

erlang 复制代码
DATA text TYPE string.
...
FIND '...' IN text.
...
FIND REGEX '...' IN text.
...
FIND SUBSTRING '...' IN text.
...

上面的源代码显示了 FIND 语句在程序中如何不一致地使用。第一个和第三个 FIND 语句是具有相同含义的替代拼写。

下面的源代码显示了与上例相同的语句,但拼写一致。这用清晰的语法表达了搜索子串和搜索正则表达式之间的语义区别。

ABAP 复制代码
DATA text TYPE string.
...
FIND SUBSTRING '...' IN text.
...
FIND REGEX '...' IN text.
...
FIND SUBSTRING '...' IN text.
...

避免过时的语句

原则:不要在新开发项目中使用过时的语言元素。我们还建议在新概念出现时逐步将其转换为新概念。

ABAP 中的一些语句已经过时了。其中一些已被弃用,一些只是用新操作数替换。如果存在更新的替代方案,请尽量避免使用过时的语句。

ABAP 是一种不断发展的编程语言。自 30 多年前问世以来,ABAP 程序不断推陈出新,与此同时,ABAP 语言也在不断进步。ABAP 语言的发展要么是对现有语言属性的扩展,以实现新功能,要么是用更先进的概念取代现有功能。用新的语言元素取代现有的语言元素通常会使现有的语言元素变得多余或过时。ABAP 语言发展最突出的例子仍然是 ABAP 对象的实现。

在 ABAP 语言方面,SAP 承诺执行严格的向下兼容性政策。一方面,这意味着例如为 3.0 版编写的 ABAP 程序可以在 7.0 版或更高版本的 AS ABAP 上执行(前提是使用非 Unicode 系统)。另一方面,这也会产生以下影响:

  • 在此之前,经验丰富的开发人员很少有动力去打破旧习惯,接触新概念。唯一的例外是在向 Unicode 系统转换时,ABAP 程序必须转换为 ABAP 语言版本标准 ABAP(Unicode),其语法规则略有不同。
  • ABAP 初学者会被同一任务的众多选项所迷惑。在有疑问的地方,旧程序会被用作模板,而过时的概念则会被使用。

较新的语言元素总是较好的语言元素。过时的语言元素只是出于向下兼容的考虑。只有当存在更强大的替代语句或语言元素被认定为容易出错(即导致不安全和不稳健的编程)时,才会将语句或语句附加声明为过时的语言元素。因此,如果使用过时的语言元素,就无法确保编程的安全性和稳健性,这也是新开发项目不应使用过时语言元素的原因。 如果使用 ABAP Objects,语法中的大部分过时语句和添加内容都已被禁止。因此,除其他原因外,我们强烈建议使用 ABAP Objects。在 ABAP 对象之外,即在仍然允许的情况下,您必须确保没有使用过时的语言元素。过时的语言元素概述了过时的语句和语句添加。

不好的习惯:

下面的源代码显示了一个使用过时语言元素的任务的解决方案。如果子串不在单词的末尾,程序应该用一个新字符串 new 替换文本中所有出现的子串。

ABAP 复制代码
FORM bad_example USING    substring TYPE csequence  
                          new       TYPE csequence  
                 CHANGING text      TYPE csequence.  
  DATA: pattern TYPE string,  
        subrc   TYPE sy-subrc.  
  CONCATENATE '*' substring INTO pattern.  
  SEARCH text FOR pattern.  
  IF sy-subrc <> 0.  
    CLEAR subrc.  
    WHILE subrc = 0.  
      REPLACE substring WITH new INTO text.  
      subrc = sy-subrc.  
    ENDWHILE.  
  ENDIF.  
ENDFORM.

在上述源代码中,除了使用 FORM - ENDFORM 进行模块化外,语句 SEARCHREPLACE 的使用变体已经过时。此外,还提供了字符串操作符 && 来替代 CONCATENATE

良好的规范: 以下源代码执行的任务与上文相同,但使用了最新的可用语言元素。

ABAP 复制代码
METHOD good_example.
  FIND REGEX substring && `\b` IN text.
  IF sy-subrc <> 0.
    REPLACE ALL OCCURRENCES OF substring IN text WITH new.
  ENDIF.
ENDMETHOD.

子程序将被方法取代。FIND 与使用字符串操作符 && 组成的正则表达式一起使用,使得辅助变量变得多余。WHILE 循环被替换为 REPLACE ALL OCCURRENCES,这意味着无需使用其他辅助变量,控制流被转移到 ABAP 运行时环境中。后者提高了执行速度,并有助于限制最大嵌套深度。

根据上述规则,在程序单元中出现了新旧概念并存的问题。语法中只有一个地方对此有明确规定,即在处理块中使用经典异常概念和基于类的异常概念时。否则,在程序部分中,过时的语言元素可以直接与新的语言元素相邻。在这种情况下,我们建议在上下文中尽可能保持使用的一致性,也就是说,不要为同一目的并行使用不同的语句,如 FIND 和 SEARCH。

但是,这并不意味着在对现有程序进行增强时,为了保持一致性而使用过时的语言元素,只是因为它们已经存在。相反,这正是将整个过程转换为相应的新语言元素的最佳时机。通过使用单元测试来涵盖要更改的程序,可以确保在转换过程中不会出现令人不快的意外情况。

相关推荐
新知图书40 分钟前
Rust编程与项目实战-模块std::thread(之一)
开发语言·后端·rust
盛夏绽放1 小时前
Node.js 和 Socket.IO 实现实时通信
前端·后端·websocket·node.js
Ares-Wang1 小时前
Asp.net Core Hosted Service(托管服务) Timer (定时任务)
后端·asp.net
Rverdoser2 小时前
RabbitMQ的基本概念和入门
开发语言·后端·ruby
Tech Synapse3 小时前
Java根据前端返回的字段名进行查询数据的方法
java·开发语言·后端
.生产的驴3 小时前
SpringCloud OpenFeign用户转发在请求头中添加用户信息 微服务内部调用
spring boot·后端·spring·spring cloud·微服务·架构
微信-since811923 小时前
[ruby on rails] 安装docker
后端·docker·ruby on rails
代码吐槽菌5 小时前
基于SSM的毕业论文管理系统【附源码】
java·开发语言·数据库·后端·ssm
豌豆花下猫6 小时前
Python 潮流周刊#78:async/await 是糟糕的设计(摘要)
后端·python·ai
YMWM_6 小时前
第一章 Go语言简介
开发语言·后端·golang