编程风格是一个经久不衰的话题,大家所公认的事实是:一个良好的编程风格会带来很多的好处。而对于“良好”的标准,则众说纷纭,莫衷一是。编程风格在ABAP程序中当然也有着重要的意义,因为很少看到专门针对ABAP编程风格的讨论,我决定把我知道的事情总结出来,以抛砖引玉。欢迎看到这篇文章的朋友回复讨论。

2018.01.11更新:本文中提到的大部分内容可以通过Code Inspector进行检查,Github上面的一个开源检查项目abapOpenChecks提供了相当全面的检查,强烈建议读者使用。相关文档地址:http://docs.abapopenchecks.org/checks/

本文链接:http://www.cnblogs.com/hhelibeb/p/6814045.html

原创内容,转载请注明

1,大写与小写

如我们所知,ABAP是一种大小写不敏感的语言。这自然会引起一个问题:使用大写还是小写?SAP给出的ABAP编辑器为我们提供了4种选项:

  • (全部)大写
  • (全部)小写
  • (关键字)大写
  • (关键字)小写

选择(关键字)大写,让代码的其余部分保持小写,在我看来是一个极为自然的选择。理由是,一)阅读大写字母组成的文本比阅读小写字母组成的文本要难。二)程序的读者通常会对关键字极为熟悉(即使不熟悉,也有文档可看),而作者本人之外的读者,对作者写出的非关键字不太可能熟悉。这两个理由使得,相比关键字,我们更需要让代码的非关键字保持良好的可读性。因此,非关键字的小写是一种必然的选择。在此基础上,让关键字保持大写,可以帮助我们区分关键字和非关键字。当然,由于关键字高亮的功能的存在,也可以不通过大小写区别它们,所以(全部)小写同样是一种可行的选项,部分SAP标准代码也是这样的风格。

某些开发者会告诉新人:代码最好全部大写,这样可以避免自己不小些将大写参数设定为小写(ABAP中很多字符参数是大写的)。然而,由于上述的原因,这是一件很糟糕的事情。字符的值的大小写和代码的大小写完全是两码事,因为这种理由放弃代码的可读性,是不成立的。

2,缩进

据说很多程序员常年为了缩进的问题争论不休,ABAP开发者在这方面是幸福的,因为SE38的代码编辑器提供了自动缩进的功能,这使得只要点击“格式优化”,所有人的代码会得到同样的缩进...

我还没有使用过新的编辑器——ABAP Development Tools for Eclipse。也许在这个新的IDE普及之后,人们会对ABAP的缩进产生新的看法。

3,表达式vs关键字

ABAP是一门包含有大量关键字的语言。SAP似乎意识到了关键字过多带来的不便,在尝试着在近期的更新中引入更多表达式的写法。

表达式的写法比关键字更加简洁、可读,推荐尽量使用表达式代替关键字,比如:

"实例化对象

 DATA(e_receiver) = NEW event_receiver( )."推荐的写法

 DATA e_receiver TYPE REF TO event_receiver. "不推荐的写法
CREATE OBJECT e_receiver.
*调用方法(可以看到,传统的写法居然要5行...)
val = object->method( parameter = a ) "建议的写法 CALL METHOD object->method "不建议的写法
EXPORTING
parameter = a
RECIEVING
return = val.
*访问内表
SELECT * INTO TABLE @DATA(itab) FROM sflight
UP TO ROWS ORDER BY carrid. TRY.
DATA(ls_sflight) = itab[ ]. "推荐的写法
CATCH cx_sy_itab_line_not_found. ENDTRY. DATA(ls_sflight) = value #( itab[ 2 ] optional ). "更推荐的写法 ,value表达式可以自动捕捉异常 DATA ls_sflight TYPE sflight.
READ itab INTO ls INDEX . "不推荐的写法
IF sy-subrc <> . ENDIF.

有关更多表达式写法的例子可以参考这个博客:ABAP 7.4新特性,或者ABAP Objects,以及SAP的官方文档。

4,Open SQL

如果要从一个数据库表中取得它自身的两个字段比较后的到的条目,ABAP的新手可能会这样写:

SELECT carrid connid fldate seatsocc seatsmax
FROM sflight
INTO TABLE sflight_tab
WHERE seatsmax < sflight-seatsocc.

而有经验的/看过文档的人知道上面的代码会报错,正确的写法是这样:

SELECT carrid connid fldate seatsocc seatsmax
FROM sflight
INTO TABLE sflight_tab
WHERE seatsmax < sflight~seatsocc.

区别就在与-和~。

不过第一种写法在某些情况下也是可以运行的,如果程序中有这样的声明的话:

DATA:
BEGIN OF sflight,
carrid TYPE sflight-carrid,
connid TYPE sflight-connid,
fldate TYPE sflight-fldate,
seatsocc TYPE sflight-seatsocc,
seatsmax TYPE sflight-seatsmax,
END OF sflight,
sflight_tab LIKE STANDARD TABLE OF sflight WITH EMPTY KEY.

此时程序也可以运行,不过比较不会发生在数据库字段之间,而是会以本地定义的结构sflight中的seatsocc作为条件。

要避免这类混淆的发生,可以使用转义字符@,加在SQL语句中的Host Variables前面。

如果是想比较数据库内的字段的话:

SELECT carrid, connid, fldate, seatsocc, seatsmax
FROM sflight
WHERE seatsmax < sflight~seatsocc
INTO TABLE @sflight_tab.

而如果是想要以ABAP程序内的值作为条件的话,就要在它的前面也加上@:

SELECT carrid, connid, fldate, seatsocc, seatsmax
FROM sflight
WHERE seatsmax < @sflight-seatsocc
INTO TABLE @sflight_tab.

这样就不会混淆了~

(注:本节的内容来自一篇英文博客:Why the new Open SQL Syntax is Better

此外,在S4/HANA中,SAP推荐将更多的计算内容放到数据库中。为了实现这一目的,现在Open SQL具有CASE表达式、字符串表达式、CAST、CTE等多种新功能。我们应该尝试使用它们。

5,命名法

ABAP程序通常使用一系列前缀来为变量命名,比如:

LT_ = Local internal table

LS_ = Local structure(work area)

LR_ = Local reference

GT_ = Global internal table

GS_ = Global structure(work_area)

GR_ = Global reference

这样做是有好处的,一方面,通常的ABAP编辑器不具备自动提示类型的功能,合理前缀可以降低阅读代码的心智负担;另一方面,如上一节所述,如果为变量取一个和数据类型/数据库字段完全相同的名字,会在某些情况下产生意外的混淆。比如:

DATA s1 LIKE sflight.
DATA s2 TYPE sflight.
"以上这段代码会声明两个相同的结构s1, s2 DATA sflight TYPE i. DATA s1 LIKE sflight.
DATA s2 TYPE sflight.
"如果声明过一个名为sflight的i类型变量,则使用like的语句会声明一个i类型的s1,使用type的语句会声明一个有着sflight行类型的结构s2..

但是前缀的滥用也会导致很多问题,合理的ABAP代码中应该尽量避免多余的变量名前缀。

比如

  • l_carrid(较好)
  • lv_carrid(较差)

使用lv/gv的前缀来表示本地变量/全局变量,是一个比较不明智的做法。因为,一个变量是值这种事情通常是无需说明的。v可以被当作默认值省略,而lt/lc则有意义。

同样的,为form命名时也不应当存在这种无意义的前缀:

  • get_price(正确)
  • frm_get_price(错误)

因为通常来说,form的使用是通过PERFORM关键字来实现的:

PERFORM get_price.

这时,get_price显然不可能是form之外的任何存在。使用frm_这样的前缀,不能带来任何理解上的帮助,只会增加代码阅读的难度。

2019.07.23更新:

QQ群里有群友质疑:lv_是通行的命名前缀,l_会带来混淆,让开发者感到困惑。

在这里回应下,首先,这种命名方式并不是笔者的发明,

sap的很多代码中的变量会用l_或m_作为前缀,比如我们最常用的cl_gui_alv_grid中的一些成员变量的前缀就是m_。笔只是认同这种办法的合理性。

在命名中,前缀后面的东西比前缀重要很多,所以要尽可能降低前缀的复杂性,避免浪费读写代码的时间。使用l_而非lv_可能会稍微增加命名上的复杂性,但是如果开发者可以在一开始掌握一个稍微复杂点的规则,也许可以在后面省更多力气。

6,单行长度

有种观点认为,单行的代码长度不应超过80个字符。大体上,对于ABAP代码而言,我同意这个观点。

如图,80个字符已经稍稍超出了编辑器核心区域的边界(虽然远未达到ABAP支持的单行最大长度——255字符)。如果只是打开单个编辑器窗口的话,这种长度还可以接受,但如果要并排打开2个窗口,一部分代码也许会无法直接显示。

此外,在SAP自身的代码比较工具中,过长的单行内容是无法直接展示的:

这种情况下,需要点击工具栏中的按钮换页:,非常不利于阅读。如果能有意限制单行代码的长度,就可以避免处于这种不利的情况。

7,带表头的内表

也许每个ABAP初学者学习的第一样东西都是内表,而学习内表时要学会的首要事项就是工作区、带表头的内表与不带表头的内表的区别....会有教程告诉他们用OCCURS关键字声明一个带表头的内表,

DATA: BEGIN OF lt_numbers OCCURS ,
num1 TYPE i,
num2 TYPE i,
END OF lt_numbers.

或者这样,使用WITH HEADER LINE,

DATA: lt_sflight TYPE STANDARD TABLE OF sflight WITH HEADER LINE.

如果这样做的话,声明得到的内表就会代表两样东西,比如,lt_sflight实际上代表着作为表头的结构lt_sflight、和内表本身lt_sflight[],至于在具体的代码中它到底代表哪个,只能由语境和开发者的意图决定...

这种奇怪的特性似乎是为了开发人员的方便而设计的,但在生产实践上,它使得开发者极易不慎将一个名称代表的两个实体混用,从而写出有bug的代码。SAP在意识到自己的错误之后,把这两种声明方式标记为过时的语法,并且在OO模式下,会在语法检查中提示这一点。

然而,为了兼容旧有的程序,在report和function group等类型的程序中,人们依然可以使用这两种方式声明带表头的内表。很多古老的ABAP教程也大量地使用了它们。以至于不少新人无意识地把它们当作声明内表的合理方式。听说某些公司在规范中禁止了它们的使用,在2017年的现在,我认为这是一项非常合理的举措,用同一个名字代表两样不同的东西本来就是很不好的事情。为了让书写者不至于混淆、为了让读者更好的理解代码,请放弃带表头的内表。与之类似的tables关键字,也应避免使用。

参考: ABAP Programming Guidelines

    BEST PRACTICE GUIDELINES FOR DEVELOPMENT – USEFUL TIPS FOR ABAP DEVELOPMENT

   

写具有良好风格的ABAP代码的更多相关文章

  1. 写出gradle风格的groovy代码

    写出gradle风格的groovy代码 我们先来看一段gradle中的代码: buildscript { repositories { jcenter() } dependencies { class ...

  2. PyTorch最佳实践,怎样才能写出一手风格优美的代码

    [摘要] PyTorch是最优秀的深度学习框架之一,它简单优雅,非常适合入门.本文将介绍PyTorch的最佳实践和代码风格都是怎样的. 虽然这是一个非官方的 PyTorch 指南,但本文总结了一年多使 ...

  3. Scala 深入浅出实战经典 第51讲:Scala中链式调用风格的实现代码实战及其在Spark中应用

    王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-64讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...

  4. [label][翻译][JavaScript-Translation]七个步骤让你写出更好的JavaScript代码

    7 steps to better JavaScript 原文链接: http://www.creativebloq.com/netmag/7-steps-better-javascript-5141 ...

  5. 使用Visual Studio Code编写和激活ABAP代码 (上)

    猪年春节后的第一篇,Jerry祝各位猪年大吉! 2019年的六分之一马上就快过完了,不知道大家在新的一年是否给自己定了新的小目标呢?这里Jerry先预祝大家到2019年年底的时候,在年初制定的小目标都 ...

  6. 如何使用事务码SMICM分析ABAP代码发起的HTTP请求的错误ICM_HTTP_SSL_PEER_CERT_UNTRUSTED

    当我用CL_HTTP_CLIENT往一个外网的url发请求时,遇到错误:ICM_HTTP_SSL_PEER_CERT_UNTRUSTED 错误是从这段ABAP代码里抛出来的: CALL METHOD ...

  7. 一段让人瑟瑟发抖的ABAP代码

    昨天11月1日是万圣节,Jerry在继续忙着调研SAP Commerce Cloud里的产品主数据管理.晚上回家到SAP国外的社交媒体上一看,好热闹啊.国外的SAP从业者们纷纷以各种各样的方式庆祝万圣 ...

  8. [置顶] 自己写代码生成器之生成Dal层代码(获取数据库所有表名称)

    自己写代码生成器之生成Dal层代码(获取数据库所有表名称) --得到数据库birthday所有表名称 select name from sysobjects where [type]='U' --se ...

  9. 用ABAP代码读取S/4HANA生产订单工序明细

    在S/4HANA事务码CO03显示的Production Order里,我希望用ABAP代码显示出该订单的operation(工序)ID,描述和状态Status,如下图所示: 很简单的几行ABAP代码 ...

随机推荐

  1. GitHub开源:升讯威ADO.NET增强组件 sheng.ADO.NET.Plus V1.3

    GitHub: https://github.com/iccb1013/sheng.ADO.NET.Plus 早前分享过,当时没有把代码上传到Github,只是通过邮件的形式分享给了部分需要的朋友,最 ...

  2. fastjson升级版本遇到的问题

    前面的话: 有关阿里的fastjson升级时遇到的问题,链接如下 https://github.com/alibaba/fastjson/wiki/enable_autotype 我要说的,是我碰到这 ...

  3. UIImageView帧动画相关属性和方法

    @property(nonatomic,copy) NSArray *animationImages; 需要播放的序列帧图片数组(里面都是UIImage对象,会按顺序显示里面的图片) @propert ...

  4. css3动画图片波纹效果

    这里的图片很有特点,下面有演示图片样式 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" &quo ...

  5. 持续集成:TestNG组织如何测试用例

    持续集成:TestNG组织如何测试用例   poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大家咨询qq:90 ...

  6. Android中启动页ViewPager和ViewFlipper带指示器

    版权声明:本文为博主原创文章,未经博主允许不得转载.   目录(?)[+]   首先我们来分析一下,想要实现启动页的功能,大家第一个想到的就是使用ViewPager,使用ViewPager确实是一种比 ...

  7. 1.Redis 的安装

    一.Redis 介绍 Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种语言的API. 作为Key-value型数据库,Red ...

  8. 原型链、prototype、_proto_那些事

    一.概念 1.Prototype:每一个构造函数都有一个原型对象,这个对象就是Prototype.这个构造函数如何找到他的原型对象呢?每个构造函数都会有一个prototype属性,指向它的原型对象. ...

  9. JavaEE开发之Spring中的条件注解组合注解与元注解

    上篇博客我们详细的聊了<JavaEE开发之Spring中的多线程编程以及任务定时器详解>,本篇博客我们就来聊聊条件注解@Conditional以及组合条件.条件注解说简单点就是根据特定的条 ...

  10. macos系统下共语言gopath变量的设置

    一.问题 在macos下安装golang开发环境,想更改gopath路径,通过export GOPATH=/Volume/E/go 在vscode中通过go env命令查看GOPATH还是原始默认的, ...