王洋
摘要:Debian的架構(gòu)通過(guò)詳細(xì)分析軟件包的相關(guān)性來(lái)了解軟件包之間的相互作用進(jìn)行了研究。Debian中的依賴是廣泛的,這使得其成為一個(gè)有趣的架構(gòu),但它們使得分析更為復(fù)雜。研究中提供了分層模式的分析,此模式基于如何使用它們將每個(gè)軟件包分類為五個(gè)層之一。這些層也可以被可視化以給出應(yīng)用如何被結(jié)構(gòu)化的簡(jiǎn)明視圖。使用這些視圖,研究發(fā)現(xiàn)有新的架構(gòu)子模式和反子模式,可以幫助開(kāi)發(fā)人員創(chuàng)建和維護(hù)軟件包。
關(guān)鍵詞:Debian;架構(gòu);五層;子模式;反子模式
中圖分類號(hào):TP311 文獻(xiàn)標(biāo)識(shí)碼:A 文章編號(hào):1009-3044(2017)13-0075-03
1概述
為了有效地描述Debian的架構(gòu),本文提出了一套可以用來(lái)對(duì)軟件包進(jìn)行分類的模式。首先,軟件包可以根據(jù)進(jìn)入和離開(kāi)依賴關(guān)系的數(shù)量被分類為分層模式或隱藏模式的一部分。一旦被發(fā)現(xiàn)是分層模式的一部分,該軟件包可以進(jìn)一步分類為特定層。本文還提出了兩種自動(dòng)分類技術(shù),以提供屬于每個(gè)模式的每層的軟件包的數(shù)量。
屬于應(yīng)用層的軟件包與其他層不同,該層內(nèi)的軟件包之間的依賴性可以提供關(guān)于特定應(yīng)用如何被結(jié)構(gòu)化的許多信息。結(jié)構(gòu)化應(yīng)用程序的不同方法通過(guò)五個(gè)子模式描述。這些子模式是由軟件包維護(hù)者做出的設(shè)計(jì)選擇。通過(guò)引人這些模式,我們可以向經(jīng)驗(yàn)不足的維護(hù)者提供有關(guān)使用模式和避免模式的信息。
1.1可視化Debian軟件包
Debian是一個(gè)擁有大量軟件包的龐大系統(tǒng),繪制有向圖有助于直觀的說(shuō)明Debian軟件包如何相互交互。要手動(dòng)繪制和組織超過(guò)30000個(gè)軟件包,具有120000個(gè)依賴關(guān)系是幾乎不可能的,因此我們依靠軟件來(lái)幫助可視化。我們從每個(gè)軟件包中獲取依賴性數(shù)據(jù),然后將數(shù)據(jù)合并到一個(gè)文件中。數(shù)據(jù)從Wa-terloo大學(xué)的SWAG實(shí)驗(yàn)室進(jìn)入LSEdit。LSEdit是一個(gè)圖形可視化工具,用于查看,操作,查詢,布局和大圖聚類。但是,由于軟件包的數(shù)量和依賴性,很難輸出。
在這個(gè)不成功的可視化Debian的嘗試之后,我們決定縮小并研究單個(gè)應(yīng)用程序及其依賴關(guān)系。Frans Pop開(kāi)發(fā)的一個(gè)名為debtree的工具提取了一個(gè)特定軟件包的所有依賴,然后輸出一個(gè)圖。這些圖是大而凌亂的,但是比嘗試一次查看整個(gè)軟件包集合更易于管理。可視化軟件包和詳細(xì)描述它們的依賴關(guān)系的功能允許我們理解使軟件包運(yùn)行的內(nèi)部工作原理。這個(gè)程序被應(yīng)用到各種其他軟件包。我們仔細(xì)檢查了其他20個(gè)軟件包,注意到他們都共享兩個(gè)基本的架構(gòu)模式之一。
1.2分層模式
軟件包可以分類到分層模式或隱藏模式中。屬于分層模式的軟件包是對(duì)整個(gè)應(yīng)用程序有貢獻(xiàn)的單個(gè)部分。我們發(fā)現(xiàn),可以將包含在分層模式中的軟件包分類為五個(gè)層:元包層,應(yīng)用程序?qū)?,?yīng)用程序庫(kù)層,特定目的庫(kù)層和通用庫(kù)層。
1.3隱藏模式
除了五個(gè)軟件包層之外,還有一組額外的軟件包不符合分層模型,我們將這些軟件包標(biāo)記為隱藏包。對(duì)于要被分類為隱藏包的軟件包,它必須不具有對(duì)其他軟件包的依賴性,也不具有來(lái)自任何軟件包的依賴性。屬于這個(gè)組的許多軟件包只包含數(shù)據(jù)或文本。但是,也可能是這樣的情況,軟件包是一個(gè)輕量級(jí)的應(yīng)用程序。事實(shí)上,Debian中很多軟件包不包含單個(gè)依賴或引用。隱藏包是不與系統(tǒng)的其他軟件包交互的獨(dú)立軟件包。
1.4軟件包層的自動(dòng)分類
為了研究Debian的整體組成,我們更詳細(xì)地研究隱藏和五層,更具體地說(shuō),每個(gè)層的組成和它們?nèi)绾蜗嗷ソ换?。我們把整套Debian軟件包分配給一個(gè)層或者作為一個(gè)隱藏包。
我們可以通過(guò)使用軟件包的描述手動(dòng)將軟件包分類到五層中,但是手動(dòng)分類超過(guò)30000個(gè)軟件包是不可行的,因此我們尋求一種自動(dòng)完成這個(gè)任務(wù)的方法。在手動(dòng)分類的過(guò)程中,我們注意到許多相同的通用庫(kù)被一遍又一遍地引用,同時(shí),在應(yīng)用程序庫(kù)級(jí)別及以上的軟件包很少被引用。這個(gè)發(fā)現(xiàn)影響到所有Debian軟件包的In、Out、Transitive In和Transitive Out度的計(jì)數(shù)。軟件包的In度是直接依賴它的其他軟件包的數(shù)量。Out度計(jì)算對(duì)軟件包的直接依賴的數(shù)量。Transitive In計(jì)算直接或間接依賴于它的軟件包數(shù)。例如,如果軟件包A依賴于軟件包B,而軟件包B依賴于軟件包C,則軟件包C將具有1的In度,但是傳遞In數(shù)為2。Transitive Out指的是需要安裝以滿足所有依賴關(guān)系的軟件包的總數(shù)。我們使用兩種方法來(lái)對(duì)軟件包進(jìn)行分類。第一種方法是通過(guò)簡(jiǎn)單的排序和過(guò)濾。這是一個(gè)特殊過(guò)程,其步驟如下:
1.通用庫(kù):
我們首先根據(jù)Transitive In計(jì)數(shù)對(duì)軟件包的列表進(jìn)行排序,因?yàn)槲覀冇^察到通用庫(kù)被廣泛引用。在大約500次計(jì)數(shù)時(shí),程序包不再類似于通用程序包,因此我們決定在此時(shí)設(shè)置閾值。
2.隱藏包:
現(xiàn)在,我們開(kāi)始識(shí)別隱藏包。這些是孤立的軟件包,因此組合的In和Out度為1的軟件包被標(biāo)記。我們將In和Out度的閾值設(shè)置為l而不是0,是因?yàn)樾⌒洼p量級(jí)應(yīng)用程序仍然依賴于標(biāo)準(zhǔn)c庫(kù)以便運(yùn)行。具有單個(gè)依賴關(guān)系的這些應(yīng)用程序仍然被認(rèn)為是隱藏,因?yàn)闆](méi)有有意義的依賴結(jié)構(gòu)。
3.元包和應(yīng)用級(jí)別:
使用隱藏的方式,具有小于5的In計(jì)數(shù)和大于30的Transi-five Out計(jì)數(shù)的軟件包將被認(rèn)為是元包層或應(yīng)用層的一部分。應(yīng)用程序通常傾向于具有很少的引用,但是依賴于許多其他的軟件包。元包和應(yīng)用程序在頂層,因此依賴于應(yīng)用程序、特定的和通用的函數(shù)庫(kù)。因此,這些頂層軟件包將始終具有比庫(kù)軟件包更大的Transitive Out計(jì)數(shù)。我們還決定將元包和應(yīng)用程序級(jí)軟件包組合為一個(gè)組,因?yàn)椴唤?jīng)常遇到元包,此外,幾乎不可能基于In/Out的度區(qū)分這兩個(gè)組之間的差異。
4.特定目的庫(kù):
為了篩選特定目的庫(kù),我們尋找In度大于15或Transitive1n數(shù)超過(guò)100的軟件包。從應(yīng)用我們前面的三個(gè)步驟,我們現(xiàn)在剩下的包也具有小于500的Transitive In計(jì)數(shù)和小于30的Transitive Out計(jì)數(shù)。這是對(duì)特定目的庫(kù)的描述,因?yàn)樗鼈儽韧ㄓ脦?kù)更少引用,通常具有較小的Out度。
5.應(yīng)用程序庫(kù):
剩余的軟件包現(xiàn)在標(biāo)記為應(yīng)用程序庫(kù)。這些包具有小于15的In度和小于30的Transitive Out度。由于使用有限,應(yīng)用程序庫(kù)往往具有較小的In和Out度。
總的來(lái)說(shuō)以上所描述的過(guò)程是特定的,并且僅進(jìn)行以提供對(duì)每個(gè)包層的大小的估計(jì)。表1總結(jié)了軟件包的In,Out,Tran—sitive In和Transitive Out度計(jì)數(shù)。大多數(shù)手動(dòng)分類軟件包似乎也使用點(diǎn)對(duì)點(diǎn)方法分類到同一層。
我們分組軟件包的第二個(gè)技術(shù)是應(yīng)用聚類算法到整個(gè)Debian軟件包。Weka是一個(gè)開(kāi)源工具,包含一組機(jī)器學(xué)習(xí)算法。我們使用其中一個(gè)可用的聚類算法幫助我們將軟件包分類為層或隱藏。K均值是一種較好的機(jī)器學(xué)習(xí)算法,用于將數(shù)據(jù)集分割成k個(gè)單獨(dú)的集群,其中每個(gè)集群中的實(shí)例彼此相似。在這個(gè)特定算法中的相似性度量被定義為兩個(gè)實(shí)例之間的歐幾里德距離。我們將簇?cái)?shù)參數(shù)設(shè)置為5以對(duì)應(yīng)于層數(shù),然后讓算法運(yùn)行。具有5個(gè)簇的K均值聚類的結(jié)果顯示于表2。由k均值產(chǎn)生的輸出是5個(gè)軟件包的集群,算法認(rèn)為它們是彼此最相似的。Weka不輸出軟件包所屬的集群。因此,為了提取K均值分配給每個(gè)軟件包的集群,必須對(duì)源代碼進(jìn)行一些修改,添加的源代碼體現(xiàn)出文本文件中的所有軟件包的實(shí)例及其對(duì)應(yīng)的集群。
從檢查每個(gè)集群中的軟件包的連接性,我們注意到每個(gè)集群中的一個(gè)共同的主題,類似于我們的點(diǎn)對(duì)點(diǎn)過(guò)程。使用與點(diǎn)對(duì)點(diǎn)方法相似的推理方式,將軟件包層分配給集群,如下所示。具有高Transitive In度的軟件包被聚集在一起,因此我們將這個(gè)簇標(biāo)記為通用庫(kù)的層。大多數(shù)軟件包展現(xiàn)出零或非常少的連接性的集群被標(biāo)記為隱藏。應(yīng)用層軟件包與具有大量高Transitive Out計(jì)數(shù)和低Transitive In計(jì)數(shù)的集群匹配。兩個(gè)剩余的集群被選擇為應(yīng)用程序庫(kù)或特定目的庫(kù)。具有較高Out/Transitive Out計(jì)數(shù)和較低In/Transitive In的簇被標(biāo)記為應(yīng)用程序庫(kù)層。具有相反特性的簇被標(biāo)記為特定目的庫(kù)。由K均值算法輸出的簇的特性各自明顯不同,因此使得每個(gè)簇表示一層更容易。
表2中的數(shù)字顯示了Debian在軟件包模式(和層)方面的組成。最引人注目的是Debian中超過(guò)一半的軟件包是隱藏的。這些是與組的其余部分隔離的軟件包,并且不包含任何有意義的依賴性。另一方面,Debian的另一半?yún)⑴c了最重的分層模式。在屬于分層模式的軟件包中,大多數(shù)是應(yīng)用程序級(jí)別層的一部分。這表明Debian包含大量的應(yīng)用程序軟件,而不是支持軟件包。雖然庫(kù)文件通常在Debian中被引用,但是沒(méi)有大量的文件。
有趣的是,點(diǎn)對(duì)點(diǎn)方法和K均值產(chǎn)生類似的結(jié)果,如表5.2,區(qū)別在于特定目的庫(kù)計(jì)數(shù),因?yàn)槭褂命c(diǎn)對(duì)點(diǎn)幾乎找到了10倍。聚類算法的工作方式可以解釋為什么表示特定目的庫(kù)的K均值聚類很小。該算法將類似的軟件包集中在一起,因此我們?cè)邳c(diǎn)對(duì)點(diǎn)方法中發(fā)現(xiàn)的許多特定目的庫(kù)被認(rèn)為更類似于其他集群中的軟件包。無(wú)論如何,此分析提供了Debian的組成和用戶可用的軟件包類型的估計(jì)。
1.5應(yīng)用子模式
分層和隱蔽模式描述了如何相對(duì)于整個(gè)軟件集合來(lái)構(gòu)造軟件包。相比之下,本節(jié)中描述的模式僅處理應(yīng)用程序級(jí)別的模式。這些模式是Debian維護(hù)者如何設(shè)計(jì)和布置特定應(yīng)用程序的表現(xiàn)形式。因此,我們將稱這些為子模式和反子模式。子模式是包裝軟件的通用解決方案,而反子模式展示了用于包裝軟件的另一種方法。
1.5.1應(yīng)用子模式:共享
我們提供的第一個(gè)應(yīng)用程序子模式是共享模式。這種模式發(fā)生在維護(hù)者從一個(gè)或多個(gè)被重用的軟件包中導(dǎo)出部分時(shí)。節(jié)省空間是重要的,有時(shí)對(duì)于嵌入式或其他低資源機(jī)器是必要的。通常情況下,這些包名稱以“common”結(jié)尾,因此我們將這個(gè)共享模式標(biāo)記為這樣共享模式背后的想法類似于創(chuàng)建庫(kù)包,但規(guī)模較小。例如,庫(kù)包通常適用于更廣泛的受眾,需要特殊的包裝實(shí)踐,以確保所有依賴包的效率無(wú)誤。
1.5.2應(yīng)用子模式:模塊化
另一個(gè)子模式是模塊化子模式。在這種模式中,應(yīng)用程序被分成多個(gè)部分,其中每個(gè)部分在很大程度上是彼此獨(dú)立的。當(dāng)應(yīng)用程序頻繁更新時(shí),Debian維護(hù)者需要確保應(yīng)用程序的新添加項(xiàng)可以單獨(dú)應(yīng)用。一般來(lái)說(shuō),維護(hù)者必須盡可能模塊化它們所包裝的應(yīng)用程序。
1.5.3應(yīng)用反子模式:意大利面
當(dāng)這種類似意粉的模式發(fā)生時(shí),大量的交織依賴使得很難看到為什么特定的軟件包被引用。這使得管理依賴關(guān)系變得困難,因?yàn)榫S護(hù)者需要很好地理解每個(gè)軟件包的功能。維護(hù)者最初不計(jì)劃具有意大利面依賴性。但是隨著時(shí)間的推移,軟件包的結(jié)構(gòu)可能通過(guò)一系列更新和修訂而演變成這種混亂的狀態(tài)。在某種程度上,維護(hù)者可能需要重組軟件包。
1.5.4應(yīng)用反子模式:完全連接
應(yīng)用程序的所有軟件包都相互引用的依賴關(guān)系圖通常不是很好的設(shè)計(jì)。如果應(yīng)用程序中的每個(gè)軟件包都依賴于每個(gè)其他軟件包,則它應(yīng)該只保留為單個(gè)軟件包。從軟件包描述中,每個(gè)phpgroupware應(yīng)用程序包都有一個(gè)唯一的函數(shù),并且看起來(lái)這個(gè)應(yīng)用程序是模塊化的,然而,依賴性使得這個(gè)模塊化不能令人滿意,因?yàn)橐粋€(gè)軟件包的安裝需要安裝其余軟件包。
1.5.5應(yīng)用反子模式:整體
還有一個(gè)反子模式,但它不能像其他一樣可視化,這使得它難以識(shí)別。這是單片子模式,它適用于大型應(yīng)用程序級(jí)包。從共享和模塊化子模式我們發(fā)現(xiàn),將一個(gè)更大的軟件包分解成更小的子模式是一個(gè)好主意,并導(dǎo)致一個(gè)改進(jìn)的結(jié)構(gòu)。大型獨(dú)立軟件包違反了這個(gè)理念,因此它是一個(gè)反子模式。雖然整體對(duì)于不涉及軟件包的人來(lái)說(shuō)很難注意到,但是負(fù)責(zé)軟件包的應(yīng)該知道整體反子模式是什么時(shí)候出現(xiàn)的。
1.6小結(jié)
本文的目標(biāo)是研究Debian的架構(gòu)。開(kāi)放源代碼軟件的用戶基礎(chǔ)龐大,可用的新軟件包的數(shù)量正以驚人的速度增長(zhǎng)。然而,在這種普及性之下,對(duì)于上傳的軟件包以及它們?nèi)绾蜗嗷ソ换?,存在理解不足的情況。在本文中,我們提出了這樣的概念:軟件包或者以隱藏模式單獨(dú)存在,或者屬于分層模式中的五個(gè)層之一。這些層是:元包層,應(yīng)用程序?qū)?,?yīng)用程序庫(kù)層,特定目的庫(kù)層和通用庫(kù)層。在Debian中,一半以上的軟件包是隱藏的,因此沒(méi)有對(duì)其他軟件包的依賴。另一半形成了一個(gè)頂層的分層模式,這意味著大多數(shù)軟件包被分組到應(yīng)用程序?qū)?,而在?kù)級(jí)別比較少。
將軟件包分類到它們的層中,并且僅可視化每個(gè)層內(nèi)的依賴性允許更容易理解的圖。應(yīng)用程序?qū)又熊浖目梢暬苤匾?,因?yàn)槲覀儷@得了顯示應(yīng)用程序組織方式的簡(jiǎn)明圖。在這種可視化中,刪除了對(duì)低級(jí)庫(kù)的自動(dòng)依賴性,剩下的是來(lái)自開(kāi)發(fā)人員的創(chuàng)建軟件包的包裝設(shè)計(jì)。我們以兩個(gè)子模式和三個(gè)反子模式的形式呈現(xiàn)包裝設(shè)計(jì)原則:共享,模塊化,意面,完全連接和整體。經(jīng)驗(yàn)豐富的軟件包維護(hù)人員知道包裝軟件的最佳方法,但通過(guò)記錄這些模式,我們希望幫助新開(kāi)發(fā)人員生產(chǎn)更高質(zhì)量的軟件包,這些軟件包不容易出錯(cuò)并且更易于升級(jí)。