李 菊,傅向華,馬軍超
(深圳技術大學大數據與互聯網學院,廣東 深圳 518000)
在線評測(Online Judge,OJ)系統是一種在教學實驗、程序設計競賽、企業軟件類崗位招聘、培訓、計算機等級認證等活動中用來評測代碼的在線系統。該系統由前端和后端兩部分組成;用戶可以在前端Web 界面提交源代碼及測試用例,然后在后端對所提交的源代碼進行編譯;最后系統將根據測試用例基線對源代碼輸出進行評估,將源代碼的準確性、內存占用及運行時間輸出在前端Web 界面。目前著名的OJ系統有北京大學的Peking University Online Judge(POJ)、浙江大學的Zhejiang University Online Judge(ZOJ)、杭州電子科技大學的Hangzhou Dianzi University Online Judge(HDOJ)等[1]。這些在線評測系統只能對學生提交的源代碼的正確性、內存及性能進行評測,而無法對代碼的規范性進行評測。這導致學生代碼編程規范意識薄弱,編寫的代碼可讀性差、低效、穩定性及可擴展性差,提交的代碼質量無法保證。
隨著互聯網的快速發展,各軟件企業也開始逐步重視軟件的代碼質量。無論是阿里發布的《Java 開發手冊》;還是華為投入20億美元,計劃用五年時間提高代碼質量,都充分突顯出軟件企業對軟件代碼質量的重視程度[2]。高質量代碼體現為:正確性、可讀性、高效性、穩定性、可維護性、可擴展性。因此編碼不僅要實現完整的功能,而且要保證代碼具有良好的可讀性、高效性、穩定性、可維護性、可擴展性。遵循代碼編程規范的習慣是代碼高質量特性的保證。因此為了更好的適應企業人才需求,急需基于代碼編程規范,對現有實驗教學的在線判題系統進行改造升級,以讓學生養成遵循代碼編程規范的習慣,提高學生的代碼質量。
本系統架構由上至下主要分為三層,即Web 界面層、業務邏輯層、數據層。Web 服務器主要用于用戶題目錄入,代碼測試用例輸入,源代碼提交,評測結果反饋。業務邏輯層主要為代碼編譯,代碼運行,代碼結果與基線的比對評測。數據庫層主要為源代碼或題目的增,刪,改,查。詳情見圖1。

圖1 系統架構圖
本系統主要在原在線判題系統的動態判題得分基礎上[3],增加基于代碼編程規范的靜態判題得分,系統實施圖如圖2所示。

圖2 系統實施圖
目前國內各大軟件企業使用比較多的代碼規范有Google、華為、騰訊、阿里巴巴等公司制定的代碼編程規范,其中使用最多的是Google 的開源代碼編程規范。為了更好的對接企業人才需求,本系統的檢測代碼規范標準,主要參考Google 開源的CC++、Java、Python 語言代碼規范,制定出適用于C、C++、Java、Python計算機語言類課程實驗教學的七大類規范規則:
⑴ 布局類:縮進、空格、空行、大括號的位置的規范等。
●程序塊使用縮進風格,縮進的空格數為4個。
●大擴號(‘{’和‘}’)與它們的語句左對齊,并各獨占一行。
●函數、類獨立的模塊之間必須加空行。
●操作符前后加空格,進行對等操作時,若是關系密切的操作符(如.)后不加空格。
●每行語句的字符數不能超過80個。
●一行只寫一條語句(包括賦值語句)。
●if、for、do、while、case、switch、default 等語句獨占一行。
⑵命名類:類、對象、函數和變量的命名等。
●類、對象、接口名,使用首字母大寫的大小寫混合法。
●函數、變量名,使用首字母使用小寫,剩余單詞使用首字母大寫的大小寫混合法。
●常量、枚舉名,使用全大寫字母。
⑶ 注釋類:注釋位置、數量、哪些變量常量要注釋等;
●注釋要放在其代碼上方相鄰位置或右方。
●注釋與所描述內容進行同樣的縮進。
●源程序的注釋量必須在占總代碼10%以上。
⑷邏輯類:缺少分支語句、浮點數比較、運算錯誤(除0)、死循環等;
●在switch 中每個case 語句都應該包含break 或者return。
●不要對浮點數進行比較運算,尤其是不要進行==、!=運算,減少>、<運算。
●進行除法或取模運算,要對分母為零的情況進行特殊處理。
●在for循環中提供終止條件。
●不要在if語句中使用等號=進行賦值操作。
⑸冗余類:冗余變量、冗余參數、重復代碼等;
●避免局部變量與全局變量同名。
●避免定義未使用到的變量及參數。
●一個源文件的代碼重復度不超過10%。
⑹復雜類:過大函數、過大對象、過大類、函數復雜度等;
●一個函數的代碼行不超過50行(非空,非注釋)。
●一個函數的代碼嵌套不超過4層。
●一個類的代碼行不超過50行(非空,非注釋)。
●一個函數使用的if、while、for、switch語句要在10個以內。
⑺內存類:數據越界、內存泄漏等。
●避免超過整數的最大值及最小值,導致上溢和下溢。
●寫代碼時new 與delete、malloc 與free 要成對出現,避免內存泄漏。
本系統主要在原系統使用動態分析技術評測程序功能準確性的基礎上,融合編譯原理中的靜態分析技術進行代碼規范評測。靜態分析技術是一種程序分析技術,不需要實際執行程序,不受程序輸入輸出的影響,與運行環境無關[4],因而比動態程序分析技術的分析速度快。靜態分析技術的主要流程為:通過詞法分析、語法分析等流程,將源代碼轉換成抽象語法樹,再進行缺陷檢測、代碼規范、系統檢測等研究分析。通過靜態分析技術中的控制流分析及語義分析,可以彌補動態分析代碼規范判別方面的不足,對代碼進行較全面的分析。本系統實現過程如圖3所示。

圖3 代碼規范檢測過程圖
⑴詞法分析:對輸入的源代碼逐行進行字符串掃描,利用正則表達式技術提取每行代碼的有意義詞法單元,包括關鍵字、標記符,再將詞法單元成非語法節點(空格及注釋)和語法節點(非空格及非注釋字符串),存儲在鏈表中,形成符號表[5]。
⑵語法分析:根據詞法分析中形成的符號表,結合語法規則,組成函數聲明、變量定義、循環語句、條件判斷等語句,再生成抽象語法樹[5]。
⑶語義分析:根據抽象語法樹及源代碼的語句結構,進行變量類型、數組大小、函數調用信息等的上下文關聯,以識別出代碼語句是否存在漏洞。
⑷控制流分析:根據抽象語法樹識別函數內部的if、while、for 調用嵌套關系,形成函數調用流向圖,以檢測代碼的邏輯關系,檢查函數內部的嵌套是否會導致死循環,除此之外還可以通過流向圖分析函數的復雜度。
⑸規則匹配:結合語義分析及控制流分析分析結果,匹配代碼規范標準,挖掘不規范的代碼語句及位置。
本次系統實驗驗證,僅針對本系統中的靜態代碼規范檢測結果進行分析。實驗的驗證環境為本校當前在線評測系統環境,詳情如表1。

表1 系統實驗環境
為了驗證系統檢測代碼規范的準確性,本次實驗針對C/C++、Java、Python 分別構造了較為全面的測試用例,可以覆蓋本系統檢測標準中的七大類27 條規則,詳情見表2。表中的總耗時為系統10 次隨機實驗的平均耗時,由表2 可知不同語言由于語法和關鍵詞的差異,導致在代碼檢測實現過程的差異,造成了代碼規范檢測耗時的差異。其中C/C++語言比Java語言在單文件代碼行數相當的情況下,要快一倍左右。四種語言的單文件耗時均在2s 以內,且代碼規范檢測準確率均達100%。

表2 不同語言代碼規范檢測測試結果
為了更好的驗證本系統的實用性,本次實驗還從本校的17次面向對象課程實驗中,抽取了五次實驗的一個行政班的結果,針對代碼規范檢測結果進行比對,測試結果詳情見表3。該課程使用的語言為C++,學生每次提交的代碼行數在30~90 行之間,由表3 可知,在這個代碼行范圍內,每個文件的耗時受代碼行數影響不大,耗時在0.66s 左右,且比較穩定。每個行政班的人數在30~40 人之間,每次實驗的題目數在4~7 道之間,且因為題目難度不同,存在一題多交的現象,由表3 可知,每個班單次實驗提交到系統的文件數在250~430之間,總耗時在170~300s之間,由于每個行政班每次上機實驗的時間為200min,因此該系統的代碼規范檢測速度較快。

表3 面向對象程序課程上機實驗測試結果
此外,本次實驗還對本校Python 語言程序設計、Java 程序設計課程的上機實驗結果進行分析,結果與表3類似。
由上面的實驗結果和分析可知,本系統中的代碼規范檢測功能,能有效、全面的檢測出代碼規范問題,并且檢查速度較快,也比較穩定。
本系統采用靜態分析技術,對原有的在線判題系統進行改造,在保證原有系統正確性功能評測的基礎上,增加了代碼規范檢測評測功能。經系統實驗驗證,該系統能快速、穩定、全面有效的檢測出代碼中存在的代碼規范問題,有助于學生養成遵循代碼編程規范的習慣,提升代碼質量。本系統還有很多需要完善之處,其中最需要完善的是,對代碼的規范進行更精確的測評,同時又不損失太多效率。