寫具備良好風格的ABAP代碼

編程風格是一個經久不衰的話題,你們所公認的事實是:一個良好的編程風格會帶來不少的好處。而對於「良好」的標準,則衆說紛紜,莫衷一是。編程風格在ABAP程序中固然也有着重要的意義,由於不多看到專門針對ABAP編程風格的討論,我決定把我知道的事情總結出來,以拋磚引玉。歡迎看到這篇文章的朋友回覆討論。html

 

2018.01.11更新:本文中提到的大部份內容能夠經過Code Inspector進行檢查,Github上面的一個開源檢查項目abapOpenChecks提供了至關全面的檢查,強烈建議讀者使用。相關文檔地址:http://docs.abapopenchecks.org/checks/程序員

 

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

原創內容,轉載請註明數據庫

1,大寫與小寫

如咱們所知,ABAP是一種大小寫不敏感的語言。這天然會引發一個問題:使用大寫仍是小寫?SAP給出的ABAP編輯器爲咱們提供了4種選項:編程

  • (所有)大寫
  • (所有)小寫
  • (關鍵字)大寫
  • (關鍵字)小寫

選擇(關鍵字)大寫,讓代碼的其他部分保持小寫,在我看來是一個極爲天然的選擇。理由是,一)閱讀大寫字母組成的文本比閱讀小寫字母組成的文本要難。二)程序的讀者一般會對關鍵字極爲熟悉(即便不熟悉,也有文檔可看),而做者本人以外的讀者,對做者寫出的非關鍵字不太可能熟悉。這兩個理由使得,相比關鍵字,咱們更須要讓代碼的非關鍵字保持良好的可讀性。所以,非關鍵字的小寫是一種必然的選擇。在此基礎上,讓關鍵字保持大寫,能夠幫助咱們區分關鍵字和非關鍵字。固然,因爲關鍵字高亮的功能的存在,也能夠不經過大小寫區別它們,因此(所有)小寫一樣是一種可行的選項,部分SAP標準代碼也是這樣的風格。api

某些開發者會告訴新人:代碼最好所有大寫,這樣能夠避免本身不小些將大寫參數設定爲小寫(ABAP中不少字符參數是大寫的)。然而,因爲上述的緣由,這是一件很糟糕的事情。字符的值的大小寫和代碼的大小寫徹底是兩碼事,由於這種理由放棄代碼的可讀性,是不成立的。編輯器

2,縮進

聽說不少程序員常年爲了縮進的問題爭論不休,ABAP開發者在這方面是幸福的,由於SE38的代碼編輯器提供了自動縮進的功能,這使得只要點擊「格式優化」,全部人的代碼會獲得一樣的縮進...ide

我尚未使用過新的編輯器——ABAP Development Tools for Eclipse。也許在這個新的IDE普及以後,人們會對ABAP的縮進產生新的見解。工具

3,表達式vs關鍵字

ABAP是一門包含有大量關鍵字的語言。SAP彷佛意識到了關鍵字過多帶來的不便,在嘗試着在近期的更新中引入更多表達式的寫法。post

表達式的寫法比關鍵字更加簡潔、可讀,推薦儘可能使用表達式代替關鍵字,好比:

"實例化對象

 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 10 ROWS ORDER BY carrid.

TRY.
    DATA(ls_sflight) = itab[ 2 ].   "推薦的寫法
  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 2. "不推薦的寫法 IF sy-subrc <> 0. 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編輯器中的視覺效果

 

如圖,80個字符已經稍稍超出了編輯器核心區域的邊界(雖然遠未達到ABAP支持的單行最大長度——255字符)。若是隻是打開單個編輯器窗口的話,這種長度還能夠接受,但若是要並排打開2個窗口,一部分代碼也許會沒法直接顯示。

此外,在SAP自身的代碼比較工具中,過長的單行內容是沒法直接展現的:

過長的單行代碼不能一次展現

這種狀況下,須要點擊工具欄中的按鈕換頁:,很是不利於閱讀。若是能有意限制單行代碼的長度,就能夠避免處於這種不利的狀況。

7,帶表頭的內表

也許每一個ABAP初學者學習的第同樣東西都是內表,而學習內表時要學會的首要事項就是工做區、帶表頭的內表與不帶表頭的內表的區別....會有教程告訴他們用OCCURS關鍵字聲明一個帶表頭的內表,

DATA: BEGIN OF lt_numbers OCCURS 0,
        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

相關文章
相關標籤/搜索