C#開(kāi)發(fā)人員如何使用和誤用隱式和顯式類型?

本文譯至 To var or not to var: how do C# developers use and misuse implicit and explicit typing? | SpringerLink

作者:Pierre A. Akiki
摘要:當(dāng)使用“var”關(guān)鍵字的隱式輸入法被引入C#中時(shí),它在開(kāi)發(fā)人員中引起了矛盾的意見(jiàn)。本文首先解釋了隱式輸入和顯式輸入之間的區(qū)別,然后概述了開(kāi)發(fā)人員的意見(jiàn)和網(wǎng)上提供的指南。然后,本文報(bào)告了一項(xiàng)調(diào)查C#開(kāi)發(fā)人員如何使用和濫用隱式和顯式類型的研究結(jié)果。這項(xiàng)研究涉及分析10個(gè)不同開(kāi)源軟件項(xiàng)目的源代碼,包括超過(guò)16,500,000行代碼和超過(guò)93萬(wàn)個(gè)變量。本研究調(diào)查了開(kāi)發(fā)者在多大程度上使用了一種影響變量類型可讀性和聲明長(zhǎng)度的排版形式。它還調(diào)查了是否在一般情況下和每個(gè)軟件項(xiàng)目中都采用了一套一致的準(zhǔn)則。開(kāi)發(fā)了一個(gè)名為“Code Analysis and Refactoring Engine for C#”(Care#)的工具,并用于進(jìn)行本研究的代碼分析。
關(guān)鍵詞: C#;代碼分析;隱式和顯式類型;可讀性;一致性

簡(jiǎn)介

過(guò)去C#變量聲明只是顯式的,直到C# 3.0版本引入隱式類型。隱式類型化的變量是使用“var”關(guān)鍵字來(lái)聲明的,因此推斷類型的責(zé)任被委托給了編譯器。這里就出現(xiàn)了一個(gè)問(wèn)題。什么時(shí)候開(kāi)發(fā)者應(yīng)該使用隱式類型來(lái)代替顯式類型?

微軟C#的首席架構(gòu)師Anders Hejlsberg說(shuō),決定在編程語(yǔ)言中保留什么比決定包含什么更難(Hejlsberg 2008)。他談到了擁有指導(dǎo)原則的重要性,這些原則可以讓開(kāi)發(fā)人員了解如何使用A language的某些爭(zhēng)議性的功能,在C#社區(qū)內(nèi)引發(fā)了一些矛盾的意見(jiàn),正如在一些在線討論中觀察到的那樣(Lippert,2011)。微軟提供了一套關(guān)于如何使用這一特性的指導(dǎo)原則,但這些指導(dǎo)原則并沒(méi)有被認(rèn)為是對(duì)公約的約束(Microsoft 2015).由于C#是當(dāng)今世界上最好的編程語(yǔ)言(TIOBE 2017),因此有必要研究一下“var”在實(shí)踐中是如何使用的。

研究問(wèn)題

本文研究的是C#中隱式和顯式類型的使用和誤用。本文試圖回答的首要研究問(wèn)題反映在標(biāo)題中,即:C#開(kāi)發(fā)人員如何使用和濫用隱式和顯式類型?這個(gè)問(wèn)題分為三個(gè)子問(wèn)題(RQ1-RQ3),分別從源代碼的可讀性和一致性的角度來(lái)探究類型的使用和濫用??勺x性是指讀者快速、輕松理解源代碼的能力(Hashim,1996)。一致性可以定義為具有統(tǒng)一的符號(hào)、術(shù)語(yǔ)和符號(hào)學(xué)(Peercy 1981)??勺x性和一致性都被認(rèn)為是影響可維護(hù)性的因素(Ghosh和Rana,2011)。本文的首要目標(biāo)是從可讀性和一致性的角度來(lái)確定C#開(kāi)發(fā)人員使用隱式和顯式類型的方式。問(wèn)題RQ1和RQ2中的每一個(gè)問(wèn)題又被劃分為子問(wèn)題,由本文所介紹的不同研究部分來(lái)回答。
本文還介紹了一個(gè)名為Code Analysis and Refactoring Engine for C# (Care#)的工具。這個(gè)工具可以幫助軟件開(kāi)發(fā)人員避免由于打字錯(cuò)誤而對(duì)可讀性和一致性可能產(chǎn)生的負(fù)面影響。Care#有一個(gè)分析組件,它可以檢測(cè)隱式和顯式變量聲明,并根據(jù)它們對(duì)類型可讀性和聲明長(zhǎng)度的影響將它們分類歸類。Care#在決定是否需要重構(gòu)之前,使用該組件對(duì)源代碼進(jìn)行分析。

研究動(dòng)機(jī)

在《清潔代碼》一書(shū)中,Robert Martin提到了許多專家的觀點(diǎn),認(rèn)為這是一個(gè)對(duì)各種學(xué)派關(guān)于清潔代碼應(yīng)該是什么樣子的看法(Martin 2009)。下面的句子非常簡(jiǎn)短地總結(jié)了這些觀點(diǎn)。Jarne Stroustrup說(shuō),干凈的代碼應(yīng)該是聰明的。Grady Booch說(shuō),干凈的代碼應(yīng)該是簡(jiǎn)潔和直接的。Dave Thomas說(shuō),干凈的代碼應(yīng)該是可由原作者以外的開(kāi)發(fā)人員閱讀。Michael Feather說(shuō),干凈的代碼看起來(lái)像是由關(guān)心它的人寫(xiě)的。Ron Jeffries說(shuō),干凈的代碼不包含重復(fù)的內(nèi)容。如果我們?cè)贑#隱式和顯式類型化的背景下思考這些意見(jiàn),銘記打字的兩個(gè)MS對(duì)人類讀者的影響。例如,當(dāng)類型不能直接讀取時(shí),用var聲明一個(gè)變量,可能會(huì)影響源碼的可讀性. 另一方面,顯式類型會(huì)造成重復(fù),并可能導(dǎo)致滾動(dòng)或當(dāng)類型的名稱很長(zhǎng)時(shí)不得不減小字體大小。這些影響是導(dǎo)致開(kāi)發(fā)者在使用這兩種形式的輸入法時(shí)意見(jiàn)相左的部分原因。研究專業(yè)C#項(xiàng)目的開(kāi)發(fā)人員是以考慮可讀性和一致性的方式應(yīng)用排版,還是只使用各自認(rèn)為合適的任何排版形式,是很有意思的。因此,本文通過(guò)分析現(xiàn)有的開(kāi)源軟件項(xiàng)目的源代碼,研究開(kāi)發(fā)人員是如何考慮排版的。

重構(gòu)使引入bug的可能性最小化。它可以改善設(shè)計(jì)或?qū)崿F(xiàn)設(shè)計(jì)的代碼的可讀性或性能.Care#可以重構(gòu)變量聲明以提高可讀性,使變量的類型變得明顯或使聲明的長(zhǎng)度變得更短。

需要注意的是,本文的目的并不是要嚴(yán)格地偏重和推廣一種類型化形式(隱式或顯式)而不是另一種。本文的主要目的是通過(guò)回答1.1節(jié)中提出的研究問(wèn)題,了解軟件開(kāi)發(fā)人員如何使用隱式和顯式類型化。

文章的結(jié)構(gòu)

本文的其余部分組織如下。第2節(jié)解釋了C#中隱式和顯式類型之間的區(qū)別,以及這兩種形式的類型都是強(qiáng)制性的情況。第3節(jié)簡(jiǎn)要介紹了微軟關(guān)于在C#中使用隱式和顯式類型的指南。在第4節(jié)中,我們提供了開(kāi)發(fā)者對(duì)使用這兩種形式的輸入法的意見(jiàn)樣本。這些意見(jiàn)是從在線討論和評(píng)論中提取的。相關(guān)工作的概述將在第5節(jié)中介紹。本研究的設(shè)計(jì)和結(jié)果是為了分析軟件開(kāi)發(fā)者如何使用和濫用C#中的隱式和顯式輸入法而進(jìn)行的,在第6和7節(jié)中進(jìn)行了介紹和討論。第8節(jié)介紹了本研究的有效性威脅。最后,在第9節(jié)中給出了結(jié)論和未來(lái)的工作。

在C#中使用隱式和顯式類型學(xué)

C#中對(duì)隱式類型的支持始于2007年11月發(fā)布的3.0版本。在方法范圍內(nèi)聲明的局部變量,可以通過(guò)使用聲明左側(cè)的var關(guān)鍵字進(jìn)行隱式類型化(Microsoft 2015)。下面的示例變量聲明是隱式和顯式類型化的。
var car = new Car(); //隱式類型化
Car car = new Car(); //顯式類型化。

微軟關(guān)于在C#中使用隱式和顯式輸入法的指南

微軟提供了一些關(guān)于何時(shí)在C#程序中使用隱式輸入法的指南(Microsoft 2015)。正如這些指南的作者所說(shuō),他們的意圖是提供最佳實(shí)踐,以提高和促進(jìn)一致性、可理解性和可維護(hù)性。遵循共同的指南,至少在同一公司內(nèi),一般來(lái)說(shuō)比擁有不一致的實(shí)踐更可取。這適用于各種情況,比如命名和縮進(jìn)。例如,Python甚至在編譯過(guò)程中強(qiáng)制執(zhí)行縮進(jìn)的一致性。一開(kāi)始可能很難在共同的準(zhǔn)則上達(dá)成一致,尤其是當(dāng)所采用的表 1 對(duì)使用 im- 的限制時(shí)。

關(guān)于C#中隱式和顯式輸入法使用的在線討論

在C#中,有許多關(guān)于使用隱式和顯式類型的博客文章和論壇討論。正如這些討論所顯示的那樣,關(guān)于在不同情況下使用何種編碼風(fēng)格,開(kāi)發(fā)者之間經(jīng)常會(huì)有相互沖突的意見(jiàn)。
考慮以下在Channel 9上的例子討論,這是一個(gè)為使用微軟技術(shù)的開(kāi)發(fā)者提供視頻的網(wǎng)站(Channel9 2010)。

相關(guān)工作

據(jù)我所知,還沒(méi)有針對(duì)本文所涉及的主題的廣泛研究。然而,源代碼分析有許多應(yīng)用(Binkley 2007)。許多研究人員對(duì)源代碼進(jìn)行了分析,以確定可以修復(fù)的問(wèn)題,從而提高軟件質(zhì)量。一些論文專門(mén)針對(duì)C#,而其他論文則針對(duì)不同的編程語(yǔ)言。本節(jié)將非常簡(jiǎn)要地概述一些與源代碼分析、軟件質(zhì)量以及針對(duì)C#和其他編程語(yǔ)言的重構(gòu)相關(guān)的工作。

研究設(shè)計(jì)

我們進(jìn)行了一項(xiàng)研究,調(diào)查C#開(kāi)發(fā)人員如何使用和濫用隱式和顯式類型。分析了十個(gè)開(kāi)源軟件項(xiàng)目的源代碼。分析包括調(diào)查類型的形式(隱式和顯式)如何影響類型可讀性和變量聲明的長(zhǎng)度。它還包括觀察軟件應(yīng)用程序的兩個(gè)不同版本之間的類型化形式是如何變化的。本研究有助于回答在第一節(jié)中陳述和解釋的研究問(wèn)題。

程序

首先,從GitHub上提供的C#項(xiàng)目中隨機(jī)抽取10個(gè)開(kāi)源軟件項(xiàng)目樣本。隨機(jī)樣本包括不同規(guī)模和類型的項(xiàng)目。我對(duì)所選軟件項(xiàng)目的源代碼事先并不了解。同時(shí),這些項(xiàng)目的作者也不知道他們的代碼將被用于本研究。所選的每個(gè)軟件項(xiàng)目都包括兩個(gè)版本。每個(gè)項(xiàng)目的兩個(gè)版本被選為平均相隔1年。這樣一來(lái),這些項(xiàng)目很可能會(huì)有足夠大的變化,從而可以觀察到開(kāi)發(fā)人員對(duì)類型的選擇是否隨著時(shí)間的推移而變化。例如,開(kāi)發(fā)者可能在特定情況下將隱式重構(gòu)為顯式,或者反之。另一方面,這些項(xiàng)目不太 可能會(huì)有涉及類和方法完全重寫(xiě)的變化,這可能會(huì)阻止一個(gè)版本中的變量和另一個(gè)版本中的變量之間的可追溯性。

我們確定了變量聲明的類別,以便根據(jù)變量聲明對(duì)類型可讀性的影響對(duì)其進(jìn)行分類。這些類別中的一部分是根據(jù)我在C#中的經(jīng)驗(yàn)和微軟的指南初步確定的。然后,對(duì)所選的軟件項(xiàng)目進(jìn)行了初步分析,并根據(jù)確定的類別對(duì)變量聲明進(jìn)行了提取和分類。之后,對(duì)仍未分類的變量聲明(即不符合任何一個(gè)類別)進(jìn)行檢查,以引出其余類別。未分類的變量通過(guò)查詢數(shù)據(jù)(extract- ed variables)進(jìn)行檢查,這是用Care#進(jìn)行分析的結(jié)果。在檢查過(guò)程中發(fā)現(xiàn)的類別被添加到Care#中,然后重新進(jìn)行分析。這個(gè)過(guò)程被重復(fù),直到所有的類別都被確定。根據(jù)隱式類型對(duì)變量類型可讀性的影響,將變量聲明類別分為三組中的一組。一旦確定了所有的變量聲明類別并進(jìn)行了分組,就對(duì)源代碼進(jìn)行了重新分析。然后,手動(dòng)和自動(dòng)檢查被形成,以識(shí)別分類中可能的錯(cuò)誤。

研究結(jié)果

本節(jié)報(bào)告了第6節(jié)所述的研究結(jié)果,并試圖回答第1節(jié)所述的研究問(wèn)題;

對(duì)有效性的威脅

對(duì)結(jié)果有效性的一個(gè)威脅是從C#代碼中提取變量的準(zhǔn)確性,無(wú)論提取是純粹基于Roslyn還是為Care#編寫(xiě)的自定義算法。為了減輕這種威脅,通過(guò)使用手動(dòng)驗(yàn)證和自動(dòng)單元測(cè)試來(lái)驗(yàn)證自動(dòng)分析,以確保算法正常工作。
另一個(gè)威脅來(lái)自于數(shù)據(jù)是從10個(gè)開(kāi)源C#中收集的。
可能不代表工業(yè)實(shí)踐的項(xiàng)目。為了減輕這一威脅:
挑選過(guò)程是隨機(jī)進(jìn)行的,所選項(xiàng)目在規(guī)模(代碼行數(shù))和類型(如開(kāi)發(fā)工具、商業(yè)工具)方面是多樣化的。同時(shí),分析的代碼行數(shù)(超過(guò)16,500,000)與類似的代碼分析研究相當(dāng),如17,600,000(Okur和Dig,2012);約4,445,415(Callaú等,2013);420,694(Ma等,2017)。

結(jié)論和今后的工作

當(dāng)使用var關(guān)鍵字的隱式輸入法被添加到C#中時(shí),它成為一個(gè)有爭(zhēng)議的功能。軟件開(kāi)發(fā)者對(duì)其使用沒(méi)有達(dá)成普遍共識(shí)。本文分析了C#開(kāi)發(fā)人員如何使用和濫用隱式和顯式輸入法。解釋了這兩種形式的輸入法之間的區(qū)別,并介紹了開(kāi)發(fā)人員在網(wǎng)上表達(dá)的意見(jiàn)樣本。此外,還介紹并解釋了Microsoft現(xiàn)有的關(guān)于使用隱式輸入法的指南。

為了了解C#開(kāi)發(fā)人員在實(shí)際項(xiàng)目中如何使用隱式和顯式輸入法,我們進(jìn)行了一項(xiàng)研究。該研究檢查了開(kāi)發(fā)人員是否在他們的項(xiàng)目中始終堅(jiān)持一套準(zhǔn)則。它還檢查了開(kāi)發(fā)人員使用這兩種類型的方式是否會(huì)影響源代碼的類型可讀性和冗余性,以及變量聲明的長(zhǎng)度。

本文進(jìn)行的研究分析了10個(gè)開(kāi)源軟件項(xiàng)目中的每個(gè)項(xiàng)目的兩個(gè)版本。選取的軟件項(xiàng)目在規(guī)模和目的上都是多樣化的,有超過(guò)1650萬(wàn)行代碼和超過(guò)93萬(wàn)個(gè)變量。研究表明,開(kāi)發(fā)人員在使用隱式和顯式排版時(shí)總體上沒(méi)有遵循一致的指導(dǎo)原則,而且這兩種排版形式都存在誤用的情況,可能會(huì)影響源代碼的可讀性。另外,當(dāng)對(duì)10個(gè)分析軟件項(xiàng)目的兩個(gè)版本分別進(jìn)行比較時(shí),并沒(méi)有出現(xiàn)明顯的基于明確的準(zhǔn)則從一種排版形式轉(zhuǎn)向另一種排版形式的趨勢(shì)。

本文還介紹了基于開(kāi)源C#編譯器Roslyn的C#代碼分析和重構(gòu)引擎(Care#)。Care#被用來(lái)分析本文所介紹的研究對(duì)象的項(xiàng)目的源代碼。目前,它支持對(duì)變量聲明中的輸入形式進(jìn)行分析和重構(gòu)。在未來(lái),Care#將被擴(kuò)展到支持更多類型的分析和重構(gòu)。它還將作為更多研究的起點(diǎn),這些研究旨在了解和改進(jìn)C#開(kāi)發(fā)人員的編碼習(xí)慣。一個(gè)計(jì)劃中的未來(lái)擴(kuò)展與基本的編碼實(shí)踐有關(guān),包括硬編碼值和魔數(shù)的使用。另一個(gè)計(jì)劃中的未來(lái)擴(kuò)展與分析用戶界面(UI)表示有關(guān),以便檢測(cè)氣味并建議可能的修復(fù),這些修復(fù)可以通過(guò)重構(gòu)操作自動(dòng)應(yīng)用。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容