阮 航,陳 恒,彭 鑫+,趙文耘
1.復(fù)旦大學(xué) 軟件學(xué)院,上海 201203 2.復(fù)旦大學(xué) 上海數(shù)據(jù)科學(xué)重點(diǎn)實(shí)驗(yàn)室,上海 201203
面向設(shè)計(jì)的開源軟件項(xiàng)目重構(gòu)經(jīng)驗(yàn)研究*
阮 航1,2,陳 恒1,2,彭 鑫1,2+,趙文耘1,2
1.復(fù)旦大學(xué) 軟件學(xué)院,上海 201203 2.復(fù)旦大學(xué) 上海數(shù)據(jù)科學(xué)重點(diǎn)實(shí)驗(yàn)室,上海 201203
技術(shù)債;軟件設(shè)計(jì);重構(gòu);開源項(xiàng)目
在現(xiàn)實(shí)世界中,軟件不是一成不變的。隨著時(shí)間的推移,軟件一直在不斷演化。演化的原因可能包括增加新需求,修改原有功能,刪除無用功能,修復(fù)軟件漏洞或者改善軟件性能等。代碼量在軟件演化過程中變得愈來愈龐大,代碼結(jié)構(gòu)也愈來愈復(fù)雜,偏離了最初的設(shè)計(jì)方向,軟件的質(zhì)量和可理解性也會(huì)降低。此時(shí)如果不及時(shí)對軟件進(jìn)行重構(gòu),會(huì)給后續(xù)開發(fā)帶來許多困難和阻礙。
重構(gòu)是在不改變軟件外部行為的條件下,對軟件內(nèi)部結(jié)構(gòu)的一種調(diào)整,提高軟件的可理解性,降低其修改成本[1]。重構(gòu)可以改善軟件的設(shè)計(jì),提高代碼的可理解性,幫助開發(fā)人員定位bug位置,使程序員能夠更加快速地開發(fā)軟件[1]。在實(shí)際軟件開發(fā)過程中,重構(gòu)逐漸占有越來越重要的地位,特別是在敏捷開發(fā)和極限編程實(shí)踐里。極限編程團(tuán)隊(duì)通過周期性的重構(gòu)來扭轉(zhuǎn)軟件退化,并循環(huán)持續(xù)進(jìn)行重構(gòu)[2]。
項(xiàng)目開發(fā)之初會(huì)對高層架構(gòu)進(jìn)行設(shè)計(jì),后續(xù)開發(fā)中根據(jù)設(shè)計(jì)的架構(gòu)完成項(xiàng)目的編碼工作。一份好的設(shè)計(jì)可以讓開發(fā)者輕松地完成工作,相反一份不好的設(shè)計(jì)會(huì)使開發(fā)者在面對同樣的工作時(shí)付出更多的勞動(dòng)。在實(shí)際開發(fā)過程中,即使有良好的設(shè)計(jì),但為了盡早交付軟件產(chǎn)品,開發(fā)人員往往會(huì)犧牲代碼質(zhì)量,破壞原有的設(shè)計(jì)。這就是技術(shù)債,長遠(yuǎn)的債務(wù)需要在維護(hù)階段花費(fèi)更多的人力去補(bǔ)償。
重構(gòu)是否真的可以改善代碼質(zhì)量,重構(gòu)在實(shí)際軟件開發(fā)過程中的地位如何。針對這兩個(gè)問題,本文選擇兩個(gè)開源項(xiàng)目進(jìn)行經(jīng)驗(yàn)研究,主要有兩個(gè)關(guān)注點(diǎn):(1)實(shí)際項(xiàng)目中重構(gòu)出現(xiàn)的頻率和類型,其中面向設(shè)計(jì)的重構(gòu)在所有重構(gòu)中是否是重要的一部分;(2)不好的設(shè)計(jì)是否真的對軟件開發(fā)造成了困難和阻礙,這種情況在開源項(xiàng)目中是否真實(shí)存在,如果對其進(jìn)行合理的重構(gòu),是否有利于后續(xù)的開發(fā)。
本文組織結(jié)構(gòu)如下:第2章簡要概述本文的相關(guān)工作;第3章通過一個(gè)使用策略模式進(jìn)行重構(gòu)的例子證明重構(gòu)的重要性,繼而介紹重構(gòu)的相關(guān)概念;第4章描述研究的問題,介紹選取的研究對象以及選取原因,并說明數(shù)據(jù)收集方法;第5章根據(jù)收集到的數(shù)據(jù)回答研究問題并得出結(jié)論;第6章對研究中的發(fā)現(xiàn)和不足之處進(jìn)行討論;第7章總結(jié)全文。
下面從重構(gòu)和技術(shù)債兩部分介紹相關(guān)工作。重構(gòu)部分介紹目前學(xué)術(shù)界對重構(gòu)的相關(guān)研究;技術(shù)債部分描述了設(shè)計(jì)相關(guān)的技術(shù)債的研究工作,說明了不良設(shè)計(jì)問題對于軟件開發(fā)和維護(hù)的阻礙。
眾多學(xué)者對重構(gòu)的時(shí)機(jī)和分類已經(jīng)進(jìn)行了研究。Fowler[1]的工作總結(jié)了22種代碼壞味道幫助定位重構(gòu)機(jī)會(huì),總結(jié)了一系列重構(gòu)類型,以及指導(dǎo)怎樣合理進(jìn)行重構(gòu)。Gamma等人[3]分類整理了共23種設(shè)計(jì)模式,幫助開發(fā)者設(shè)計(jì)出更加靈活的、模塊化的、可復(fù)用的和易理解的軟件。Kerievsky[4]在前兩者的基礎(chǔ)上把重構(gòu)與模式結(jié)合起來進(jìn)行考慮,描述了模式導(dǎo)向的重構(gòu)。
Mens等人[5]對目前為止軟件重構(gòu)技術(shù)進(jìn)行了總結(jié),對每個(gè)重構(gòu)階段的相關(guān)研究都進(jìn)行了介紹,并分析了目前研究出的技術(shù)和工具。Mens等人[6]指出未來重構(gòu)面臨的問題是基本原理問題和實(shí)踐問題。
代碼壞味道會(huì)阻礙軟件演化,開發(fā)歷史中對代碼壞味道的修改明顯多于其他部分[7-8]。Munro[9]提出了一種通過使用度量值的集合自動(dòng)監(jiān)測代碼壞味道的方法。
M?ntyl?[10]發(fā)現(xiàn)處于領(lǐng)導(dǎo)級(jí)別的工程師更關(guān)注于較高層次的代碼壞味道,而且在項(xiàng)目中經(jīng)驗(yàn)豐富的人員能發(fā)現(xiàn)更多的代碼壞味道;人工進(jìn)行的代碼壞味道甄別和現(xiàn)有的度量產(chǎn)生了沖突。Kataoka等人[11]設(shè)計(jì)了一款通過程序不變量來挑選出代碼壞味道并進(jìn)行重構(gòu)的工具。
現(xiàn)有研究面向的重構(gòu)操作大都是簡單的原子性操作,當(dāng)需要完成比較高級(jí)的復(fù)合型操作時(shí),仍舊需要人工進(jìn)行輔助。
技術(shù)債由Cunningham首次提出,指的是開發(fā)團(tuán)隊(duì)在設(shè)計(jì)或架構(gòu)選型時(shí)從短期效應(yīng)的角度選擇了一個(gè)易于實(shí)現(xiàn)的方案,但從長遠(yuǎn)來看,這種方案會(huì)帶來更消極的影響,亦即開發(fā)團(tuán)隊(duì)所欠的債務(wù)[12]。
在技術(shù)債相關(guān)信息不明確的時(shí)候,Guo等人[13]對技術(shù)債的問題嚴(yán)重性,技術(shù)債是如何影響軟件項(xiàng)目和技術(shù)債影響軟件項(xiàng)目的哪些方面進(jìn)行了探索。Schmid[14]提出應(yīng)該用一系列近似值來模擬各個(gè)方面,然后慎重決定技術(shù)債。Tom等人[15]對技術(shù)債提出了一個(gè)完整的理論框架體系。
Ernst等人[16]通過對現(xiàn)實(shí)生活中1 800多位工程師和架構(gòu)師的調(diào)查和訪問,分析技術(shù)債的相關(guān)問題。結(jié)論顯示技術(shù)債是一個(gè)有意義且容易理解的抽象比喻,工程師們一致同意設(shè)計(jì)結(jié)構(gòu)是造成軟件技術(shù)債的主要原因。如何處理和管理技術(shù)債目前仍然存在諸多困難,但他們認(rèn)為從原始設(shè)計(jì)追蹤有助于解決這一問題。
本章通過一個(gè)計(jì)算顧客購物清單應(yīng)支付金額的案例,介紹重構(gòu)相關(guān)的基本知識(shí),展示結(jié)構(gòu)設(shè)計(jì)對于軟件演化的影響,以及利用重構(gòu)進(jìn)行結(jié)構(gòu)調(diào)整對于軟件后續(xù)開發(fā)的益處。
案例的大致結(jié)構(gòu)如圖1所示,圖中展示了一個(gè)在商場中付款時(shí),用來計(jì)算顧客購買貨物應(yīng)支付金額的類Payment。
Fig.1 Payment class structure圖1 Payment類結(jié)構(gòu)
用戶分為3種:(1)有等級(jí)并可以使用積分的用戶;(2)有等級(jí)但不可以使用積分的用戶;(3)無等級(jí)的用戶。有等級(jí)的用戶可以享受對應(yīng)的等級(jí)打折優(yōu)惠,并且可以使用積分來抵消掉一部分的消費(fèi)金額。
這個(gè)計(jì)算支付金額的案例存在設(shè)計(jì)缺陷。設(shè)計(jì)最大的缺點(diǎn)是當(dāng)對原有功能進(jìn)行擴(kuò)展時(shí)會(huì)遇到很多阻礙,比如需要根據(jù)顧客所選擇的支付方式提供一些不同的優(yōu)惠政策,這些優(yōu)惠有著不同的計(jì)算方式。如果采取圖1所示的設(shè)計(jì)方法,需要修改大量的分支代碼。這樣的設(shè)計(jì)會(huì)令后續(xù)的功能擴(kuò)展更加困難,當(dāng)出現(xiàn)復(fù)雜的邏輯判斷時(shí),往往需要進(jìn)行重構(gòu)來減少程序復(fù)雜度。
面對圖1中所展示的結(jié)構(gòu),適用于使用策略模式進(jìn)行結(jié)構(gòu)上的改進(jìn)和優(yōu)化。應(yīng)用策略模式令客戶端的代碼與實(shí)際的算法分離,便于對原有算法進(jìn)行修改以及增加新算法等。在應(yīng)用策略模式后,調(diào)整后的設(shè)計(jì)結(jié)構(gòu)如圖2所示。
此設(shè)計(jì)的優(yōu)點(diǎn)在于可以使計(jì)算模塊和客戶端分開,當(dāng)需要增加新的計(jì)算方式時(shí),可以直接在服務(wù)端進(jìn)行修改,客戶端可以很簡單地通過調(diào)用新增的策略來實(shí)現(xiàn),對客戶端的修改量很小。例如需要根據(jù)顧客所選擇的支付方式提供一些不同的優(yōu)惠政策時(shí),所要進(jìn)行的修改只是去增加繼承自GetBillStrategy抽象類的一種新的計(jì)算方式策略類。重構(gòu)可以幫助開發(fā)者改善代碼結(jié)構(gòu),更加有益于新功能的添加和后續(xù)的維護(hù)工作。面對同樣增加新功能的需求,優(yōu)化后代碼所需要進(jìn)行的修改量遠(yuǎn)遠(yuǎn)少于未進(jìn)行優(yōu)化的代碼。
接下來,對研究中出現(xiàn)的重構(gòu)進(jìn)行介紹。
Fig.2 Payment class structure after using strategy mode圖2 應(yīng)用策略模式后的Payment類結(jié)構(gòu)
如前文曾經(jīng)介紹過的,現(xiàn)有重構(gòu)的命名都是基于文獻(xiàn)[1]進(jìn)行的,本文按照重構(gòu)是否涉及軟件設(shè)計(jì)和難易程度將重構(gòu)分為3類:不涉及設(shè)計(jì)的重構(gòu)、涉及設(shè)計(jì)的簡單重構(gòu)和基于設(shè)計(jì)模式的重構(gòu)。
這里所說的是否涉及到設(shè)計(jì),采用如下判定方式:所應(yīng)用的重構(gòu)方式是否改變了原有的類結(jié)構(gòu),包括類在包中的位置、類與類之間的依賴關(guān)系等,這樣的變化可以通過類圖直觀地展現(xiàn)。
提煉函數(shù),替換算法,分解/合并條件式,重新命名函數(shù)/重新命名屬性等重構(gòu)方法是在實(shí)際研究過程中觀察到的不涉及軟件設(shè)計(jì)的重構(gòu)。不涉及設(shè)計(jì)的重構(gòu)的操作比較單一,多數(shù)是一些簡化和移動(dòng)操作。
搬移函數(shù),提煉類,用多態(tài)替換條件式,函數(shù)上移/下移,提煉父類等重構(gòu)方式都涉及到對設(shè)計(jì)的優(yōu)化與改進(jìn),其中一些實(shí)現(xiàn)是由比較簡單的重構(gòu)所構(gòu)成。
設(shè)計(jì)模式是經(jīng)過分類的反復(fù)使用的代碼設(shè)計(jì)經(jīng)驗(yàn)的總結(jié),可以方便進(jìn)行后續(xù)的代碼復(fù)用。設(shè)計(jì)模式的應(yīng)用會(huì)伴隨著新的輔助類的添加或者是對現(xiàn)有類的結(jié)構(gòu)調(diào)整,是一種比較高級(jí)的重構(gòu)方式。
本章對研究的整體過程進(jìn)行介紹:首先說明研究所關(guān)注的兩個(gè)問題;其次介紹選取的研究對象,并解釋選取研究對象的原因;最后介紹數(shù)據(jù)收集的方法。
本研究的目的在于發(fā)現(xiàn)重構(gòu)在現(xiàn)實(shí)項(xiàng)目中是否有廣泛的應(yīng)用,研究面向軟件設(shè)計(jì)的重構(gòu)在所有重構(gòu)中的重要性,以及分析重構(gòu)是否會(huì)改善軟件設(shè)計(jì)。在對開源項(xiàng)目的研究中,主要關(guān)注以下兩個(gè)研究問題。
問題1重構(gòu)在現(xiàn)實(shí)項(xiàng)目中是否有很多應(yīng)用,其中是否出現(xiàn)了面向設(shè)計(jì)的重構(gòu)。
研究問題1的主要目的是研究在開源項(xiàng)目中開發(fā)人員對重構(gòu)的重視程度,并且在其中發(fā)現(xiàn)開發(fā)人員對面向軟件設(shè)計(jì)的重構(gòu)的關(guān)注度。在版本歷史中,研究開發(fā)人員是否發(fā)現(xiàn)重構(gòu)機(jī)會(huì)然后進(jìn)行重構(gòu),可以了解重構(gòu)在開源項(xiàng)目中是否被認(rèn)可和應(yīng)用,其中面向軟件設(shè)計(jì)的重構(gòu)的比例可以顯示出這類重構(gòu)是否是重要的一部分。
問題2在現(xiàn)實(shí)項(xiàng)目中,是否存在由于未進(jìn)行重構(gòu)改善不良設(shè)計(jì),導(dǎo)致后續(xù)開發(fā)過程中遇到了不必要的障礙的情況,以及后續(xù)是否意識(shí)到并進(jìn)行重構(gòu)。
研究問題2的主要目的是研究面向設(shè)計(jì)的重構(gòu)的影響,關(guān)注點(diǎn)在于開源項(xiàng)目中是否真實(shí)存在這樣面向設(shè)計(jì)的重構(gòu)。當(dāng)存在這樣的重構(gòu)機(jī)會(huì)時(shí),觀察在后續(xù)沒有進(jìn)行重構(gòu)的這一段開發(fā)過程中,開發(fā)人員是否因?yàn)檫@樣的不良設(shè)計(jì)遇到了不必要的困難。如果在開源項(xiàng)目中找到了面向設(shè)計(jì)的重構(gòu),通過研究重構(gòu)前的開發(fā)階段,考慮面向設(shè)計(jì)的重構(gòu)是否可以解決這些阻礙。
本文選取jEdit和Jabref兩個(gè)開源項(xiàng)目作為研究對象。選擇這兩個(gè)開源項(xiàng)目的原因有以下兩點(diǎn):(1)這兩個(gè)開源項(xiàng)目使用Java語言編寫,Java語言是一種面向?qū)ο蟮母呒?jí)編程語言,出現(xiàn)重構(gòu)機(jī)會(huì)的可能性更高;(2)項(xiàng)目規(guī)模較小,更利于理解代碼結(jié)構(gòu)和內(nèi)部邏輯。
jEdit是一款比較成熟的開源程序員文本編輯器,由Slava Pestov在1998年進(jìn)行主要內(nèi)核的開發(fā),目前內(nèi)核大致穩(wěn)定沒有繼續(xù)修改,但仍有很多開發(fā)者在制作和更新相應(yīng)插件。
Jabref是一個(gè)用Java語言編寫的支持多平臺(tái)的文獻(xiàn)推送和管理工具,2005年開始開發(fā),到目前為止仍在持續(xù)開發(fā)和更新。
在對這兩個(gè)開源項(xiàng)目的研究中,分別選擇了3個(gè)版本間的所有提交作為研究對象。jEdit選擇了jedit-4-3-pre16至jedit-4-3-pre17和jedit-4-3-pre17至jedit-4-3-pre18兩個(gè)階段;Jabref選擇了v2.11至v2.11.1和v2.11.1至v3.0兩個(gè)階段。在選擇了研究目標(biāo)后,對數(shù)據(jù)進(jìn)行了預(yù)處理,最后采用人工閱讀的方式收集所需數(shù)據(jù)。
由于開源項(xiàng)目的提交次數(shù)多,修改的文件之間的關(guān)系復(fù)雜,人工閱讀所有提交歷史并統(tǒng)計(jì)數(shù)據(jù)是不現(xiàn)實(shí)的。針對這個(gè)問題,對這兩個(gè)項(xiàng)目的各個(gè)階段設(shè)計(jì)了對應(yīng)的數(shù)據(jù)庫表結(jié)構(gòu)來儲(chǔ)存相關(guān)信息,方便查詢和統(tǒng)計(jì)。在數(shù)據(jù)庫上進(jìn)行的數(shù)據(jù)統(tǒng)計(jì)需要基于人工閱讀的經(jīng)驗(yàn)。
人工閱讀開源項(xiàng)目的提交歷史是本文經(jīng)驗(yàn)研究的主要方法,在人工閱讀過程中主要關(guān)注兩個(gè)研究問題。
問題1主要面向的對象是開發(fā)項(xiàng)目過程中開發(fā)人員實(shí)際做出的重構(gòu)操作,并要關(guān)注其中涉及到軟件設(shè)計(jì)的部分。對于這個(gè)研究問題,在人工閱讀過程中需要注意觀察提交日志帶有refactoring關(guān)鍵字的提交。同時(shí)需要通過閱讀源碼發(fā)現(xiàn)未標(biāo)明的重構(gòu),結(jié)合提交信息和具體的修改內(nèi)容人工判斷每次提交的意圖,了解是否應(yīng)用了重構(gòu)操作,以及是否存在面向設(shè)計(jì)的重構(gòu)。
問題2主要研究的是開發(fā)的某段過程中是否存在不好的設(shè)計(jì),使后續(xù)開發(fā)遇到了不必要的困難。這個(gè)問題采用兩種思路進(jìn)行研究:第一種思路是在閱讀前對項(xiàng)目的各個(gè)模塊進(jìn)行大致的理解,了解程序的運(yùn)行流程和互相之間的調(diào)用處理關(guān)系,在這個(gè)基礎(chǔ)上尋找不好的設(shè)計(jì),并追蹤這個(gè)設(shè)計(jì)對于后續(xù)開發(fā)的不良影響。第二種思路是先尋找到開發(fā)人員已經(jīng)進(jìn)行過的面向設(shè)計(jì)的重構(gòu),在這次重構(gòu)的提交基礎(chǔ)上回溯檢查此次提交前的提交,從而發(fā)現(xiàn)沒有進(jìn)行改善設(shè)計(jì)的重構(gòu)前,開發(fā)過程中是否遇到了阻礙。
本章對研究結(jié)果進(jìn)行分析。數(shù)據(jù)來源于兩個(gè)開源項(xiàng)目的4個(gè)開發(fā)階段,在后文中表示如下:jEdit的jedit-4-3-pre16至jedit-4-3-pre17階段表示為pre1617,jedit-4-3-pre17至jedit-4-3-pre18階段表示為pre1718;Jabref的v2.11至v2.11.1階段表示為v11to111,v2.11.1至v3.0階段表示為v111to3。
所有提交在數(shù)據(jù)庫統(tǒng)計(jì)中發(fā)現(xiàn),有一部分不包含java文件,修改的是用于記錄的log文檔、配置文件等,可以通過文件類型進(jìn)行排除。在排除了無關(guān)的提交后,pre1617、pre1718、v11to111和v111to3的提交次數(shù)為230次、134次、58次和278次。
在這些提交中,搜索“refactoring”和“restructure”關(guān)鍵詞發(fā)現(xiàn)包含重構(gòu)的提交。jEdit項(xiàng)目在pre1617中出現(xiàn)了1次標(biāo)明重構(gòu)的提交,Jabref在v111to3中出現(xiàn)了7次標(biāo)明重構(gòu)的提交(排除了對測試用例重構(gòu)的提交)。但在后續(xù)的人工閱讀階段發(fā)現(xiàn),重構(gòu)操作遠(yuǎn)不止搜索到的8次提交,這一情況說明現(xiàn)在開發(fā)人員對于重構(gòu)操作的認(rèn)識(shí)不夠,但是開發(fā)人員實(shí)際上進(jìn)行了一部分自身沒有意識(shí)到是重構(gòu)的操作。例如:一個(gè)搬移getBoolean方法的重構(gòu)被開發(fā)人員描述為“New method StandardUtilities.getBoolean()that will convert an object into a Boolean”,只提到了新方法的添加,沒有體現(xiàn)該方法移動(dòng)到StandardUtilities類中。兩個(gè)項(xiàng)目中標(biāo)明為重構(gòu)的共8次提交中有2次是提煉函數(shù)重構(gòu),其余6次是重命名重構(gòu),這些都是簡單的重構(gòu)類型,并且這些重構(gòu)大多只涉及一個(gè)類的修改。說明開發(fā)人員對于部分簡單重構(gòu)是有一定的理解的,或者說開發(fā)人員更認(rèn)可同一個(gè)類中進(jìn)行的重構(gòu)。
jEdit的開發(fā)時(shí)間要遠(yuǎn)遠(yuǎn)早于Jabref,所研究的jEdit開發(fā)階段的時(shí)間在2008年11月至2009年11月,Jabref所研究的開發(fā)階段在2015年11月,這證明了重構(gòu)的重要性正一步步被認(rèn)可,提交日志中注明“refactoring”或“restructure”關(guān)鍵字的提交逐漸變多。
pre1617、pre1718、v11to111和v111to3所包含的重構(gòu)次數(shù)分別為31次、8次、19次和43次。在jEdit中平均有10.71%的提交是關(guān)于重構(gòu)的,在Jabref中平均有18.45%的提交是關(guān)于重構(gòu)的,這些數(shù)據(jù)說明了重構(gòu)在開發(fā)中的重要性,開發(fā)人員進(jìn)行了不少?zèng)]有意識(shí)到的重構(gòu)。
開發(fā)人員進(jìn)行過的重構(gòu)主要有8種類型,分別是搬移函數(shù)、提煉類、方法上移、改變參數(shù)、搬移值域、重命名函數(shù)或?qū)傩?、替換算法、提煉方法和自封裝值域。所列舉的前5種重構(gòu)會(huì)涉及到軟件設(shè)計(jì)的調(diào)整,因?yàn)檫@些重構(gòu)會(huì)更改類之間的調(diào)用關(guān)系或?qū)哟谓Y(jié)構(gòu)。
各個(gè)種類的重構(gòu)操作在pre1617、pre1718、v11to111和v111to3中的比例如圖3所示,明顯看到重命名和搬移函數(shù)重構(gòu)操作在各個(gè)研究階段分布較多。重命名和搬移函數(shù)重構(gòu)的經(jīng)常出現(xiàn)表明,在開發(fā)過程中對類的職責(zé)劃分不清晰。重命名重構(gòu)以下的部分表示面向軟件設(shè)計(jì)的重構(gòu)操作,面向軟件設(shè)計(jì)的重構(gòu)在每個(gè)階段所占比例大約在50%左右,pre1718因?yàn)榘溯^少的重構(gòu)操作(8次),所以被排除在外。從這個(gè)比例可以看出,面向設(shè)計(jì)的重構(gòu)操作在所有重構(gòu)中占有較高比例。
Fig.3 Refactoring classification ratio圖3 重構(gòu)分類比例
研究中觀察到的面向設(shè)計(jì)的重構(gòu)操作包含搬移函數(shù)、提煉類、方法上移、改變參數(shù)和搬移值域。這些重構(gòu)有一個(gè)共同點(diǎn):在重構(gòu)中涉及到的修改的類大多只有兩個(gè)。這說明目前觀察到的涉及軟件設(shè)計(jì)的重構(gòu)是比較簡單的重構(gòu),只是兩個(gè)類之間的結(jié)構(gòu)的分配,沒有比較復(fù)雜的涉及多個(gè)類結(jié)構(gòu)的重構(gòu)出現(xiàn)。
重構(gòu)在實(shí)際項(xiàng)目中有著重要的應(yīng)用,項(xiàng)目中對其關(guān)注度也越來越高。但是目前開發(fā)人員對于重構(gòu)的認(rèn)知度偏低,對實(shí)際上是重構(gòu)操作的提交很少進(jìn)行注明。開發(fā)人員對于重命名等簡單重構(gòu)已經(jīng)有普遍認(rèn)知,基本能夠主動(dòng)標(biāo)識(shí)。面向軟件設(shè)計(jì)的重構(gòu)在重構(gòu)中出現(xiàn)頻率較高,主要是在兩個(gè)類之間進(jìn)行相關(guān)的函數(shù)和屬性搬移,調(diào)整類的層次結(jié)構(gòu)等簡單重構(gòu),但沒有應(yīng)用設(shè)計(jì)模式的復(fù)雜重構(gòu)出現(xiàn)。
由于未及時(shí)重構(gòu),不合理的設(shè)計(jì)對后續(xù)開發(fā)造成了阻礙的情況是存在的,但是其中的大部分沒有被合理地重構(gòu)或者處理方式不合適。下面通過兩個(gè)最典型的例子進(jìn)行分析研究,并展示合理的重構(gòu)對后續(xù)開發(fā)的積極影響。其中5.2.1小節(jié)中的例子被開發(fā)人員識(shí)別出重構(gòu)機(jī)會(huì)并進(jìn)行了重構(gòu),5.2.2小節(jié)中的例子沒有進(jìn)行重構(gòu)。
Jabref的圖形化界面模塊中存在一個(gè)包gui,專門用來保存與界面相關(guān)的對象,其中一部分對象用來表示對話框。有一個(gè)對話框類DuplicateResolverDialog實(shí)現(xiàn)了用于保存位置和大小信息的方法savePosition。
此處出現(xiàn)了設(shè)計(jì)缺陷,保存對話框大小和位置信息的方法屬于通用的設(shè)置方法,很有可能被同樣是對話框的其他類復(fù)用。并且在DuplicateResolver-Dialog的init初始化方法中有一段代碼的意圖是設(shè)置對話框的大小和位置信息,這樣獨(dú)立的操作沒有提煉成方法。
在后續(xù)的開發(fā)中,id為313bf3b的提交中出現(xiàn)了新的需求:為MergeEntryDialog類和MergeEntry-DOIDialog類添加保存對話框大小和位置的功能。按照之前較差的設(shè)計(jì),開發(fā)人員實(shí)現(xiàn)的方式就是在MergeEntryDialog類和MergeEntryDOIDialog類中增加savePosition方法。實(shí)現(xiàn)與DuplicateResolverDialog類相同,同時(shí)初始化中設(shè)置初始大小和位置的功能也同樣實(shí)現(xiàn),結(jié)構(gòu)如圖4所示。按照這樣的設(shè)計(jì),后續(xù)的向其他對話框類中添加相同方法時(shí)需要不斷地增加新方法,修改初始化方法,會(huì)產(chǎn)生大量的冗余代碼。此外一旦需要對這個(gè)方法的邏輯進(jìn)行修改,就不得不對每個(gè)實(shí)現(xiàn)該方法的對話框類進(jìn)行修改,增加了維護(hù)和修改的成本。
Fig.4 Irrelevant dialog structure圖4 無關(guān)聯(lián)的對話框結(jié)構(gòu)
id為c47fe58的提交中發(fā)現(xiàn)了這個(gè)問題,對于結(jié)構(gòu)的調(diào)整是提取savePosition方法為GUIGlobals的靜態(tài)方法,并通過重命名函數(shù)和增加參數(shù)的重構(gòu)修改為storeDialogSize方法。與此同時(shí),設(shè)置大小和位置的代碼塊提取出來成為GUIGlobals的靜態(tài)方法set-DialogSize,結(jié)構(gòu)如圖5所示。在id為c582705的提交中對這一部分又進(jìn)行了重構(gòu),提煉單獨(dú)的Position-Window類來維護(hù)這兩個(gè)靜態(tài)方法用以調(diào)用。
Fig.5 Dialog structure after refactoring in project圖5 項(xiàng)目中重構(gòu)后對話框結(jié)構(gòu)
這樣的設(shè)計(jì)改進(jìn)是可以消除冗余代碼和減少后期維護(hù)難度的,但不是最好的面向?qū)ο蟮慕鉀Q辦法。提取方法作為靜態(tài)方法的處理方式破壞了面向?qū)ο蟮睦砟?,很難利用多態(tài)處理相關(guān)問題。在研究中發(fā)現(xiàn)有十幾次類似的通過將方法提取到通用類中改為靜態(tài)方法的方式處理相似問題,這樣的處理方式并沒有對設(shè)計(jì)進(jìn)行修改,開發(fā)人員考慮到修改后的測試成本和軟件的正確性問題等多方面原因,選擇最簡單的增加靜態(tài)功能的方式進(jìn)行處理,沒有從根本上改善設(shè)計(jì)問題。
設(shè)置和存儲(chǔ)對話框大小位置信息的功能在邏輯上與對話框類聯(lián)系緊密,應(yīng)該作為對話框類的方法實(shí)現(xiàn)。一個(gè)較好的改進(jìn)方案是為需要實(shí)現(xiàn)該功能的對話框?qū)崿F(xiàn)統(tǒng)一的父類,其中storeDialogSize和set-DialogSize方法,實(shí)現(xiàn)該功能的類繼承自這個(gè)父類獲取該方法的實(shí)現(xiàn),重構(gòu)后結(jié)構(gòu)如圖6。這樣不僅可以消除冗余代碼,而且當(dāng)特別的子類需要有特別的邏輯修改時(shí)還可以通過覆寫的方式修改,改善了代碼的可維護(hù)性和可擴(kuò)展性。
Fig.6 Dialog structure after reasonably refactoring圖6 合理重構(gòu)后對話框結(jié)構(gòu)
Jabref在搜索部分需要選擇不同的搜索模式而使用不同的策略進(jìn)行搜索,設(shè)計(jì)的方式是使用一個(gè)枚舉類型的SearchMode保存相關(guān)內(nèi)容,在SearchBar通過對應(yīng)的RadioButton來進(jìn)行切換選擇策略。Jabref沒有進(jìn)行很好的設(shè)計(jì),導(dǎo)致有大量switch和if…else…語句出現(xiàn)在方法中,主要表現(xiàn)在initSearchModeMenu、getSearchModeMenuItem、getSearchMode、focus和 on-SearchTextChanged這5個(gè)方法中。
在id為a1b231e的提交中,為了更簡單地進(jìn)行搜索模式的選擇,搜索模式需要從原有的6種減少到3種。面對這樣的新需求,SearchBar類需要在上述5個(gè)方法中做大量的修改,如圖7和圖8所示為get-SearchModeMenuItem方法修改部分。其他的方法也都包含關(guān)于這幾種模式的選擇判定的switch或if…else…語句,同樣需要進(jìn)行大量分支的刪除,重復(fù)出現(xiàn)的判斷對后續(xù)修改造成的困難展露無遺。
Fig.7 Function getSearchModeMenuItem before changing圖7 修改前getSearchModeMenuItem方法
這個(gè)設(shè)計(jì)問題可以通過應(yīng)用狀態(tài)模式解決。后文對簡化后3種模式的實(shí)現(xiàn)進(jìn)行優(yōu)化分析,設(shè)計(jì)結(jié)構(gòu)調(diào)整如圖9。
Fig.9 SearchBar structure after refactoring圖9 重構(gòu)后SearchBar結(jié)構(gòu)
在沒有應(yīng)用設(shè)計(jì)模式的重構(gòu)前,實(shí)現(xiàn)對搜索模式的增刪修改時(shí),需要對SearchBar類中涉及到模式類型判斷的方法進(jìn)行大量修改,同時(shí)需要修改用于維護(hù)信息的SearchMode類。如果能及時(shí)應(yīng)用本文所調(diào)整的結(jié)構(gòu),增刪模式的操作變得極為簡單。當(dāng)需要變更模式類型時(shí),只需要增加SearchMode對應(yīng)的模式實(shí)現(xiàn),并修改SearchBar的初始化方法實(shí)現(xiàn)對應(yīng)按鈕的添加,再在Globals存儲(chǔ)的模式數(shù)組中添加名稱字符串,就可以完成模式的增刪,不需要在項(xiàng)目中修改大量的方法,同時(shí)可以減少大量判斷語句的使用,提高代碼性能,代碼結(jié)構(gòu)也更加清晰易懂。
Fig.8 Function getSearchModeMenuItem after changing圖8 修改后getSearchModeMenuItem方法
本章介紹在研究過程中產(chǎn)生的思考以及研究中存在的不足。
不良設(shè)計(jì)是導(dǎo)致代碼質(zhì)量下降的重要原因之一,阻礙開發(fā)人員對軟件的開發(fā)和維護(hù)。及時(shí)利用重構(gòu)改善不良設(shè)計(jì)是理想的處理方法,可以降低不良設(shè)計(jì)對后續(xù)開發(fā)造成的危害。研究中發(fā)現(xiàn)不良設(shè)計(jì)的出現(xiàn)與原因可以總結(jié)為3種情況:
(1)在軟件設(shè)計(jì)階段產(chǎn)生的不良設(shè)計(jì)。軟件架構(gòu)師不可能設(shè)計(jì)出絕對正確的軟件設(shè)計(jì),這種不良設(shè)計(jì)的出現(xiàn)是無可避免的。
(2)由于技術(shù)債產(chǎn)生的不良設(shè)計(jì)。由于人力、時(shí)間和資源等因素的限制,開發(fā)人員無法在要求的短期時(shí)間內(nèi)交付可展示的工作成果。為了及時(shí)交付工作成果,開發(fā)人員往往選擇舍棄部分設(shè)計(jì)以在短期內(nèi)完成工作,也就是軟件工程領(lǐng)域的技術(shù)債問題。面向設(shè)計(jì)的技術(shù)債屬于開發(fā)人員不得不因?yàn)楝F(xiàn)實(shí)因素做出讓步的一種決策。
(3)在開發(fā)過程中產(chǎn)生的不良設(shè)計(jì)。軟件開發(fā)是一個(gè)漫長的過程,期間會(huì)出現(xiàn)無數(shù)次的功能增加與變更。功能的增加與變更會(huì)改變原有的類結(jié)構(gòu),這會(huì)暴露出目前設(shè)計(jì)的問題。這種問題在設(shè)計(jì)之初可能不是一個(gè)不良設(shè)計(jì),在后續(xù)的修改過程中才變成了不良設(shè)計(jì)。
考慮5.2.1小節(jié)的例子,最初只有DuplicateResolver-Dialog這一個(gè)對話框類實(shí)現(xiàn)了保存對話框大小的功能,僅在該類中維護(hù)相關(guān)方法是合理的。如果在設(shè)計(jì)之初設(shè)計(jì)成繼承父類方法的方式,會(huì)使其他對話框類出現(xiàn)不必要的方法,父類在整個(gè)結(jié)構(gòu)中顯得多余。當(dāng)增加MergeEntryDialog類和MergeEntry-DOIDialog類后,才發(fā)現(xiàn)原來設(shè)計(jì)的不足之處,需要消除冗余代碼。
了解不良設(shè)計(jì)的出現(xiàn)階段和原因能夠幫助對不良設(shè)計(jì)進(jìn)行追蹤和記錄,有利于為后續(xù)維護(hù)和修改提供有益信息。
(1)和(2)中產(chǎn)生的不良設(shè)計(jì)可以通過審查和記錄的方式發(fā)現(xiàn)問題所在,但(3)中產(chǎn)生的不良設(shè)計(jì)需要在開發(fā)中定期進(jìn)行重構(gòu)才可以解決。
經(jīng)過研究,開源項(xiàng)目歷史中已經(jīng)存在重構(gòu)相關(guān)的提交,面向設(shè)計(jì)的重構(gòu)在所有發(fā)現(xiàn)的重構(gòu)中占有接近一半的數(shù)量,是重構(gòu)中重要的一部分。面向設(shè)計(jì)的重構(gòu)可以提高可理解度,也能夠減少冗余的代碼,降低代碼的維護(hù)難度。如果在開發(fā)過程中自覺地進(jìn)行重構(gòu),可以為以后的開發(fā)降低難度,提高效率。
但重構(gòu)仍然面臨一些問題:首先是對重構(gòu)的認(rèn)知,目前開發(fā)人員對于重構(gòu)普遍只處于聽說過的階段,并不了解重構(gòu)的具體內(nèi)容,這使重構(gòu)難以系統(tǒng)地進(jìn)行;其次是重構(gòu)的效益,重構(gòu)后代碼的優(yōu)點(diǎn)更多體現(xiàn)在后續(xù)的開發(fā)過程中,這種未來效益很難得到重視;面向設(shè)計(jì)一類的復(fù)雜重構(gòu)不僅修改一個(gè)類,常常涉及到幾個(gè)類的變動(dòng),其間難免會(huì)出現(xiàn)漏洞,這樣的修改成本和測試成本是開發(fā)人員不愿意承擔(dān)的,因此開發(fā)人員更偏向于改動(dòng)單一的類來完成需求,不會(huì)自覺地進(jìn)行較為復(fù)雜的重構(gòu)。
開發(fā)人員對重構(gòu)的不理解,管理人員對重構(gòu)的輕視和重構(gòu)成本過高,是無法進(jìn)行重構(gòu)的主要原因。通過自動(dòng)判定應(yīng)當(dāng)應(yīng)用重構(gòu)的位置和自動(dòng)應(yīng)用重構(gòu)后,重構(gòu)的價(jià)值可以更好地體現(xiàn),降低重構(gòu)難度和成本,重構(gòu)才能真正應(yīng)用到每個(gè)開發(fā)過程中。
研究可能會(huì)因?yàn)橐韵聨讉€(gè)因素導(dǎo)致研究結(jié)果不準(zhǔn)確,主要包括對面向設(shè)計(jì)的重構(gòu)的識(shí)別,研究對象的選擇和開發(fā)階段的識(shí)別3個(gè)因素。
對于現(xiàn)有的重構(gòu)操作,本文按照重構(gòu)是否改變了軟件設(shè)計(jì)將其分為3類,主要判斷依據(jù)是重構(gòu)是否改變了軟件類之間的依賴關(guān)系,使用類圖展示可以清晰地辨別出這種變化,但是有一部分重構(gòu)無法準(zhǔn)確判斷是否改變了設(shè)計(jì)。
以添加參數(shù)的重構(gòu)為例。添加參數(shù)的重構(gòu)在研究中被定義為面向設(shè)計(jì)的重構(gòu)操作:第一種情況也是大多數(shù)情況,是在A類的方法中增加了B類的參數(shù),這樣就更改了類與類之間的依賴關(guān)系,這樣的操作認(rèn)為是面向設(shè)計(jì)的重構(gòu)。第二種情況是,在A類中添加了A類自身屬性作為參數(shù),這也屬于添加參數(shù)的重構(gòu),但不改變類之間的關(guān)系,這一情況在研究中出現(xiàn)得不多,因此仍然認(rèn)為添加參數(shù)是面向設(shè)計(jì)的重構(gòu)。在研究中遇到第二種情況時(shí),并不統(tǒng)計(jì)為添加參數(shù)的重構(gòu),僅僅統(tǒng)計(jì)入重構(gòu)總次數(shù)。
研究中選取了兩個(gè)項(xiàng)目,jEdit開發(fā)時(shí)間比Jabref更早。這里可能出現(xiàn)的問題是研究選取的對象太少,在兩個(gè)開源項(xiàng)目間的統(tǒng)計(jì)和比較可能不具有普遍性,但是在研究項(xiàng)目中發(fā)現(xiàn)的實(shí)例確實(shí)可以證明不良設(shè)計(jì)對于軟件開發(fā)的不良影響,而且驗(yàn)證了重構(gòu)對于改善設(shè)計(jì)的重要作用。
本文在每個(gè)開源項(xiàng)目的兩個(gè)開發(fā)階段通過統(tǒng)計(jì)和閱讀源碼的方式進(jìn)行研究,開發(fā)階段的選取是隨機(jī)的。這樣選取開發(fā)階段可能會(huì)存在問題,jEdit是保持內(nèi)核基本不變的開源項(xiàng)目,選取的階段可能設(shè)計(jì)已經(jīng)基本定型,暴露出的問題可能偏少,而處于不斷開發(fā)過程的Jabref項(xiàng)目中暴露設(shè)計(jì)問題的可能性更高。同時(shí)隨機(jī)化挑選也有一定優(yōu)勢,隨機(jī)化挑選開發(fā)階段可以排除由于挑選開發(fā)活動(dòng)頻繁的階段造成的結(jié)論特殊性。
軟件在現(xiàn)實(shí)世界中不是一成不變的,隨著時(shí)間的推移一直在不斷進(jìn)行演化。為了解決各種原因造成的代碼設(shè)計(jì)問題,需要在開發(fā)過程中不斷進(jìn)行重構(gòu)改善代碼質(zhì)量。
在對現(xiàn)有重構(gòu)類型和應(yīng)用場景已經(jīng)有一定理解的基礎(chǔ)上,本文提出了兩個(gè)研究問題進(jìn)行探索。研究中選取兩個(gè)開源項(xiàng)目作為研究對象,在每個(gè)研究對象上隨機(jī)選取兩個(gè)版本間的開發(fā)歷史作為觀察,通過數(shù)據(jù)預(yù)處理后人工閱讀的方式收集開源項(xiàng)目中的實(shí)際例證和數(shù)據(jù)進(jìn)行問題研究。
研究證明重構(gòu)是開發(fā)過程中重要的一部分,在研究的兩個(gè)開源項(xiàng)目的提交歷史中分別占有10.71%和18.45%的比例。雖然重構(gòu)在項(xiàng)目中應(yīng)用很多,但是開發(fā)人員在應(yīng)用重構(gòu)的過程中往往沒有意識(shí)到所做的操作是重構(gòu),沒有在提交日志中說明,提交日志中指明修改是重構(gòu)的提交只占實(shí)際重構(gòu)中極小的一部分。提交日志中指明本次修改是重構(gòu)的提交中,主要的重構(gòu)類型是重命名,這說明開發(fā)人員對于重構(gòu)操作的類型和定義的了解只處于最初級(jí)的階段。面向設(shè)計(jì)的重構(gòu)在所有重構(gòu)中占據(jù)將近1/2的數(shù)量,是重構(gòu)的一個(gè)重要方面。開發(fā)人員在開發(fā)中識(shí)別出并進(jìn)行重構(gòu)的面向設(shè)計(jì)重構(gòu)只涉及兩個(gè)類之間的變動(dòng),操作過于簡單。
研究過程中發(fā)現(xiàn)了這樣的情況,由于未進(jìn)行合理設(shè)計(jì),導(dǎo)致進(jìn)行功能擴(kuò)展的過程中遇到了不必要的障礙,極少有開發(fā)人員意識(shí)到是設(shè)計(jì)問題并進(jìn)行重構(gòu)調(diào)整。但是所進(jìn)行的重構(gòu)并沒有在根本上解決設(shè)計(jì)問題,有時(shí)反而會(huì)導(dǎo)致其他設(shè)計(jì)問題的出現(xiàn)。研究通過提出合理的解決辦法,將合理重構(gòu)方式與開發(fā)人員實(shí)際重構(gòu)進(jìn)行對比,體現(xiàn)出應(yīng)用合理重構(gòu)對于提高代碼質(zhì)量的重要性,很大程度上改善了代碼的可維護(hù)性。軟件設(shè)計(jì)在開發(fā)過程中具有指導(dǎo)性意義,在演化過程中軟件設(shè)計(jì)的退化問題和技術(shù)債的管理問題往往需要應(yīng)用重構(gòu)去解決。
未來的研究需要找到合適的評(píng)價(jià)軟件設(shè)計(jì)質(zhì)量的度量,從而指導(dǎo)在何時(shí)何處應(yīng)用何種重構(gòu)改善代碼設(shè)計(jì),沒有指導(dǎo)的盲目重構(gòu)是沒有意義的。目前沒有足夠的工具幫助開發(fā)人員管理面向設(shè)計(jì)的技術(shù)債問題,在未來對這些方面需要進(jìn)一步的研究。
[1]Flower M.Refactoring:improving the design of existing code[M].Upper Saddle River,USA:Addison-Wesley Professional,1999:53-89.
[2]Martin R C.Agile software development:principles,patterns,and practices[M].Upper Saddle River,USA:Prentice Hall,2002:9-16.
[3]Gamma E,Helm R,Johnson R,et al.Design patterns:elements of reusable object-oriented software[M].Upper Saddle River,USA:Addison-Wesley Longman Publishing Co Inc,1995:241-276.
[4]Kerievsky J.Refactoring to patterns[M].Upper Saddle River,USA:Addison-Wesley,2002:232.
[5]Mens T,Tourwe T.A survey of software refactoring[J].IEEE Transactions on Software Engineering,2004,30(2):126-139.
[6]Mens T,Demeyer S,Bois B D,et al.Refactoring:current research and future trends[J].Electronic Notes in Theoretical Computer Science,2010,82(3):483-499.
[7]Khomh F,Penta M D.An exploratory study of the impact of code smells on software change-proneness[C]//Proceedings of the 16th Working Conference on Reverse Engineering,Lille,France,Oct 13-16,2009.Washington:IEEE Computer Society,2009:75-84.
[8]Olbrich S,Cruzes D S,Basili V,et al.The evolution and impact of code smells:a case study of two open source systems[J].Biology of Reproduction,2009,68(5):390-400.
[9]Munro M J.Product metrics for automatic identification of“bad smell”design problems in Java source-code[C]//Proceedings of the 11th International Software Metrics Symposium,Como,Italy,Sep 19-22,2005.Washington:IEEE Computer Society,2005:15.
[10]M?ntyl? M V,Vanhanen J,Lassenius C.Bad smells — humans as code critics[C]//Proceedings of the 20th International Conference on Software Maintenance,Chicago Illinois,USA,Sep 11-17,2004.Washington:IEEE Computer Society,2004:399-408.
[11]Kataoka Y,Notkin D,Ernst M D,et al.Automated support for program refactoring using invariants[C]//Proceedings of the 2001 International Conference on Software Maintenance,Italy,Nov 6-10,2001.Washington:IEEE Computer Society,2001:736-743.
[12]Cunningham W.The WyCash portfolio management system[J].ACM SIGPLAN OOPS Messenger,1992,4(2):29-30.
[13]Guo Yuepu,Seaman C,Gomes R,et al.Tracking technical debt—an exploratory case study[C]//Proceedings of the 27th International Conference on Software Maintenance,Williamsburg,USA,Sep 25-30,2011.Washington:IEEE Computer Society,2011:528-531.
[14]Schmid K.A formal approach to technical debt decision making[C]//Proceedings of the 9th International ACM Sigsoft Conference on Quality of Software Architectures,Vancouver,Canada,Jun 17-21,2013.New York:ACM,2013:153-162.
[15]Tom E,Aurum A,Vidgen R.An exploration of technical debt[J].Journal of Systems&Software,2013,86(6):1498-1516.
[16]Ernst N A,Bellomo S,Ozkaya I,et al.Measure it?manage it?ignore it?software practitioners and technical debt[C]//Proceedings of the 10th Joint Meeting on Foundations of Software Engineering,Bergamo,Italy,Aug 30-Sep 4,2015.New York:ACM,2015:50-60.
RUAN Hang was born in 1993.He is an M.S.candidate at Software Engineering Laboratory,Fudan University.His research interest is software maintenance and evolution.
阮航(1993—),男,遼寧凌源人,復(fù)旦大學(xué)軟件工程實(shí)驗(yàn)室碩士研究生,主要研究領(lǐng)域?yàn)檐浖S護(hù)與演化。
CHEN Heng was born in 1992.He is an M.S.candidate at Software Engineering Laboratory,Fudan University.His research interest is software maintenance and evolution.
陳恒(1992—),男,江蘇泰州人,復(fù)旦大學(xué)軟件工程實(shí)驗(yàn)室碩士研究生,主要研究領(lǐng)域?yàn)檐浖S護(hù)與演化。
彭鑫(1979—),男,湖北黃岡人,2006年于復(fù)旦大學(xué)計(jì)算機(jī)科學(xué)專業(yè)獲得博士學(xué)位,現(xiàn)為復(fù)旦大學(xué)教授,CCF高級(jí)會(huì)員,主要研究領(lǐng)域?yàn)樾枨蠊こ?,自適應(yīng)軟件,軟件產(chǎn)品線,軟件維護(hù),逆向工程。
ZHAO Wenyun was born in 1964.He received the M.S.degree from Fudan University in 1989.Now he is a professor at Fudan University,and the senior member of CCF.His research interests include software reuse,software product line and software engineering.
趙文耘(1964—),男,江蘇常熟人,1989年于復(fù)旦大學(xué)獲得碩士學(xué)位,現(xiàn)為復(fù)旦大學(xué)教授,CCF高級(jí)會(huì)員,主要研究領(lǐng)域?yàn)檐浖?fù)用,軟件產(chǎn)品線,軟件工程。
Empirical Study of Design-Oriented Refactorings in Open Source Projects*
RUAN Hang1,2,CHEN Heng1,2,PENG Xin1,2+,ZHAO Wenyun1,2
1.Software School,Fudan University,Shanghai 201203,China 2.Shanghai Key Laboratory of Data Science,Fudan University,Shanghai 201203,China
Software is constantly changing and evolving,driven by the increment of requirements.Software often degrades from the original design,the quality of codes also becomes poor.Developers will meet more barriers and difficulties in the future development when there are some technical debts in the original design.It is necessary to improve the quality of codes by refactorings.This paper introduces some common types of refactorings under the review of related literature,and introduces a simple case to verify the importance of the design-oriented refactorings.This paper aims to answer two questions:(1)whether there are applied refactorings in the open source project and whether there are design-oriented refactorings among them;(2)whether there exists some situation that the structure with a bad design causes difficulties in the fellow-up development and whether the developers apply some refactorings to it later.This paper proves the wide use and importance of refactorings in open source projects,particularly the importance of the design-oriented refactorings.
technical debt;software design;refactoring;open source project
the Ph.D.degree in computer science from Fudan University in 2006.Now he is a professor at Fudan University,and the senior member of CCF.His research interests include requirements engineering,self-adaptive software systems,software product line,software maintenance and reverse engineering.
2016-09, Accepted 2016-11.
A
TP311
+Corresponding author:E-mail:pengxin@fudan.edu.cn
RUAN Hang,CHEN Heng,PENG Xin,et al.Empirical study of design-oriented refactorings in open source projects.Journal of Frontiers of Computer Science and Technology,2017,11(9):1418-1428.
10.3778/j.issn.1673-9418.1609025
*The National Natural Science Foundation of China under Grant No.61370079(國家自然科學(xué)基金);the National Key Research and Development Program of China under Grant No.2016YFB1000801(國家重點(diǎn)研發(fā)計(jì)劃).
CNKI網(wǎng)絡(luò)優(yōu)先出版: 2016-11-07, http://www.cnki.net/kcms/detail/11.5602.TP.20161107.1703.008.html
摘 要:軟件在演化過程中經(jīng)常被修改,軟件結(jié)構(gòu)往往會(huì)偏離原有的設(shè)計(jì)方向,軟件質(zhì)量也會(huì)逐漸變差。不良設(shè)計(jì)造成的技術(shù)債務(wù)在后續(xù)開發(fā)過程中會(huì)帶來許多困難和阻礙,需要及時(shí)重構(gòu),改善原有代碼的不良設(shè)計(jì)。對常見的重構(gòu)操作進(jìn)行了簡單介紹和分類。在兩個(gè)開源項(xiàng)目上進(jìn)行了經(jīng)驗(yàn)研究,關(guān)注兩個(gè)問題:(1)重構(gòu)在開源項(xiàng)目中是否被廣泛應(yīng)用,其中是否存在面向設(shè)計(jì)的重構(gòu);(2)是否存在沒有及時(shí)重構(gòu)改善原有代碼的不良設(shè)計(jì),導(dǎo)致后續(xù)開發(fā)遇到不必要的困難的情況,并且后續(xù)是否進(jìn)行了重構(gòu)。初步證明了重構(gòu)在開源項(xiàng)目中的廣泛應(yīng)用和重要性,以及面向設(shè)計(jì)的重構(gòu)的重要作用。