最近有粉絲在後臺給我留言,說新知識太多,“學不動了”。所謂溫故而知新,今天我們就來重溫下ABAP裡的Code Inspector的用法。
2015年6月,我在SAP社群上寫了一篇部落格,介紹了ABAP Code Inspector裡一些大家不常用的功能,在2016年SAP社群改版,所有文章閱讀量清零之後,到現在仍然有17000多的點選量。
https://blogs.sap.com/2015/06...
本文是Jerry英文部落格翻譯成中文的濃縮版,並且假定讀者都知道如何使用SCI這個事務碼。對ABAP Code Inspector還不熟悉的朋友,可以查閱我另一篇講述其用法的部落格:
A Small tip to get all transparent tables used in ABAP code
我們可以在ABAP Code Inspector的檢查變體(Check Variant)裡,根據自己的需要靈活地選擇對ABAP程式碼進行哪種型別的掃描動作。
下圖是一個例子,意思是對ABAP程式碼中所有對資料庫表產生了讀寫訪問之處,進行"Table Names from SELECT Statements"的掃描。該掃描的具體行為,可以點選藍底白色的感嘆號圖片,以獲得幫助文件。下圖這個例子裡勾取的選項,意思是檢查被訪問的資料庫表,在SE11的ABAP欄位裡的Technical Settings是否正確被維護了,比如表的快取型別是否設定正確。
Performance Check
Select-Statement can be transformed. X% of fields used - 檢查內表欄位的使用率
假設我們使用SELECT * 從一張表裡讀取資料到ABAP內表,然後在後續程式碼中只使用到了A個欄位,而讀取的表在SE11裡總共有B個欄位,那麼A除以B的結果越小,說明讀出來的內表欄位使用率越低。
也就是說,你或許該考慮只SELECT真正需要的欄位來替代SELECT *? 只需要在上圖設定裡維護一個最低閥值,當Code Inspector掃描程式碼時,一旦檢測到使用率低於維護的閥值就會報錯。上圖的20意思是20%.
Search DB Operations in loops across modularization units
Jerry 2007年剛加入SAP開始學習ABAP程式設計時,前輩們就告誡過我,不要在LOOP裡使用SELECT語句,這樣會極大影響程式碼的效能。
上圖是透過Code Inspector掃描出來的一個例子,在雙重LOOP迴圈裡使用SELECT讀取資料庫表CRMD_DPP_HI_BLCK.
Nested Loops - 巢狀迴圈的檢測
儘管當應用程式碼裡巢狀迴圈的迴圈次數不大時,對程式碼執行的絕對時間沒有太大影響——然而編寫具有至少指數級時間複雜度的程式碼,在任何上下文裡都不是一個好的程式設計習慣。
這個設定能夠幫助我們快速找到所有的巢狀迴圈。
Copy current table row for LOOP AT
找出所有LOOP AT ... INTO之處,理論上這些地方都可以用LOOP AT ... REFERENCE INTO或者ASSIGNING <fs>替換。當內表的行結構體欄位很多時,使用後兩種方式可以獲得一些效能的提升。
Low-Perform. Parameter Transfers - 檢測所有引數傳遞使用"Pass by Value"之處
Jerry關注了很多技術公眾號,發現引數傳遞的"傳引用"和"傳值"這兩種方式的辨析,至今仍然是很多網際網路公司的面試題之一。
這個選項可以讓您指定針對何種型別的引數進行引數傳遞方式的掃描:
在ABAP裡理論上採用引用傳遞的方式進行引數傳遞,效能上總是優於值傳遞,具體效能會提高多少,依賴於具體傳遞的引數型別,無法一概而論。
Security Check – Dynamic and Client-Specific accesses in SELECT - 動態SQL語句的檢測
符合下列正規化的動態SQL會被掃描出來:
Dynamic table accesses: SELECT * FROM (dbtab) WHERE …
Dynamic WHERE conditions: SELECT * FROM dbtab WHERE (where_cond)
Accesses to certain tables: SELECT * FROM dbtab WHERE …
Client-specific accesses: SELECT * FROM dbtab FROM WA … CLIENT SPECIFIED …
這個選項並不是禁止您使用動態SQL語句——事實上SAP應用的持久層裡有大量的動態SQL語句的使用例子——而是提醒您別忘記了進行SQL隱碼攻擊的預防措施:一旦掃描出來,如果有使用者輸入參與了這些動態SQL語句的拼接,那就別忘記看看上下文有沒有使用CL_ABAP_DYN_PRG對使用者輸入進行處理。
Search for APPEND and INSERT … INDEX in SORTED Tables
檢測所有在有序內表上施加了APPEND操作的地方。有了這個掃描選項,能夠幫助您避免下圖第13行這種型別的執行時錯誤。
Check of SY-SUBRC Handing - ABAP關鍵字呼叫後系統變數sy-subrc的檢測
Jerry至今仍清楚地記得,十多年前上研究生課程《UNIX環境高階程式設計》時,老師不斷地強調在進行系統呼叫之後一定要檢查返回值並進行相應的錯誤處理。在Jerry看來,錯誤檢測和處理是每一位程式設計人員都應該具備的基本素養。
對應到ABAP裡,就意味著每次呼叫ABAP的關鍵字完成某項操作後,都必須檢查sy-subrc的值來確認這次操作是否成功。
當然也可以根據專案的實際情況,告訴Code Inspector只檢查某些型別的ABAP關鍵字呼叫。比如上圖意思就是隻檢查READ TABLE關鍵字呼叫後是否進行了sy-subrc的檢查。
Missing table content check before calling SELECT … FOR ALL ENTRIES IN
在使用FOR ALL ENTRIES IN <itab>之前,必須先檢查內表itab是否為空。這個選項能掃描出沒有按照這個規範來編寫的程式碼。
Programming Conventions - Naming conventions
在這個介面裡為ABAP裡不同型別的變數設定好您團隊裡達成一致的命名規範,然後Code Inspector就能把程式碼裡所有違反了這些命名規範的地方掃描出來。
Metrics and Statistics
這個檢查類別下面的設定都是一些很有意思的統計資訊。
還是舉例說明。下圖紅色區域的設定,意思是如果一個類的方法內的可執行語句行數超過150行,Code Inspector就報一條警告訊息。這是為了避免大家寫出一個過於冗長的方法。
而藍色區域的設定是如果每100行可執行程式碼的對應註釋量小於10行,就報一條警告訊息。這些閥值可以根據實際情況自行修改或關閉。
FAN-OUT Structural Metrics - 統計一個方法的扇出值
方法的扇入值和扇出值在模組化程式設計的上下文會經常被提及,這對概念不是程式設計界首創的,而是源自半導體行業裡的邏輯電路設計:
邏輯閘的扇出係數定義了該門能夠驅動的數字訊號輸入的最大量,而一個程式碼模組的扇出值則代表了其直屬下層的模組個數。
這個選項能夠統計您方法的扇出係數。扇出係數太小,意味著該方法基本沒有呼叫其他下層的函式,這有兩種可能:
- 該方法的邏輯本身非常簡單,只有兩三行程式碼,比如類的setter/getter方法;
- 這個方法的模組化沒有做好,存在最佳化的空間,比如某些直接寫在方法內的語句,可以提煉成下層函式並在方法內呼叫。
Comment Language Metrics
這個選項可以統計程式碼中出現的德文註釋的函式。
Jerry不太明白該選項有什麼用處,給非德國ABAP開發人員吐槽用的麼?
OO Size Metrics
這個選項也是為了防止您不經意間就創造出怪獸級的類(monster class)而生的:一旦您關注的類的屬性超過設定的閥值,比如類的成員,類的公/私有方法等關注點超過選項裡設定的值時,Code Inspector就會報警。
Program Complexity Test – cyclomatic complexity - 程式碼環複雜度(圈複雜度)的測試利器
這又是一個能幫助您寫出Clean ABAP code的強大工具。
什麼是程式碼的環複雜度?
根據維基百科的定義,我們把一段程式碼的執行流畫成一張有向無環圖,然後環複雜度可以透過下面的公式計算出來:
https://en.wikipedia.org/wiki...
環複雜度 = 圖的邊數 - 圖的節點數 + 2
這其實就是我們研究生專業課《圖論》裡學的尤拉定理。
看下面這個例子:
上面這8行ABAP程式碼,環複雜度為3,怎麼計算出來的?
先把其對應的有向無環圖畫出來:
這張圖的邊數為3,即圖中黑色,紅色和綠色三條粗線。
這張圖的頂點數為2,如圖中兩個菱形的藍色圖例所示。
最後環複雜度為3 – 2 + 2 = 3.
統計表明,程式碼的高環複雜度和高故障率之間存在很強的正相關性,這不難理解,程式碼的環複雜度越高,意味著裡面巢狀的IF-ELSE,SWITCH等邏輯越多,無論是程式碼原來的開發人員,還是後來接手的維護人員,讀起來都會覺得頭昏腦脹。
因此大家可以多用ABAP Code Inspector的這個掃描選項,隨時監控您程式碼的環複雜度。
Search DB Operations
把您關注的在程式碼中出現的SQL操作關鍵字全部羅列出來。
Search ABAP Statement Patterns
這個選項也很有用,能根據您指定的正規表示式掃描ABAP程式碼。
例如,您希望找出程式碼裡所有出現了READ TABLE XXX WITH KEY X = X的地方,只需要在上圖的輸入框裡填入對應的正規表示式,即用*代表任意字串:
READ TABLE WITH KEY = *
然後ABAP Code Inspector就會按照我們期望的行為去掃描程式碼:
ABAP報表RS_ABAP_SOURCE_SCAN也能實現完全一致的功能:
ABAP Code Inspector的隱藏功能就介紹到這裡,希望大家能夠好好利用它們,提高您的工作效率和程式碼質量,感謝閱讀。
要獲取更多Jerry的原創文章,請關注公眾號"汪子熙":