自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

軟件依賴的一知半解

開發(fā) 架構
對系統(tǒng)架構而言,軟件依賴有著嚴重的風險,而這些風險常常會被忽視。本文的目的是提高對風險的認識,并嘗試更多的解決方案。

對系統(tǒng)架構而言,外部系統(tǒng)依賴往往是系統(tǒng)質量屬性的最大風險,對軟件自身也是如此。軟件依賴有著嚴重的風險,而這些風險常常會被忽視。我們可能尚未理解有效選擇和使用依賴關系的最佳實踐,甚至沒有理解何時選擇依賴關系。本文的目的是提高對風險的認識,并嘗試更多的解決方案。

在軟件開發(fā)中,依賴項是程序員想要調用的附加代碼。添加依賴項可以避免重復工作,例如設計、測試、調試和維護特定的代碼單元,這個代碼單元被稱為包,或者庫,或者模塊等,本文會混用。采用軟件依賴項很常見,咱們都經歷過手動安裝所需庫的步驟,比如 C 的 PCRE 或 zlib; C++的 Boost 或 Qt; 或 Java 的 JUnit等。這些軟件庫包含了高質量且經過調試的代碼,需要大量的專業(yè)知識來開發(fā)。對于一個需要這些軟件包提供的功能的程序來說,手動下載、安裝和更新軟件包的工作要比從頭開始開發(fā)這些功能要容易得多。

依賴管理器,也稱為包管理器,可以自動下載和安裝依賴包。由于依賴管理器使單個軟件包更容易下載和安裝,成本較低, 使得發(fā)布和重用較小的軟件包更經濟。例如,Node.js 的依賴管理器 NPM 提供了對超過幾十萬個包的訪問?,F(xiàn)在基本上每種編程語言都有依賴管理器: Maven (Java)、 Composer(PHP)和pip (Python)等都超過了10萬個包。

這種細粒度的、廣泛的軟件復用的到來是這些年來軟件開發(fā)中最重要的轉變之一。然而,如果我們不更加小心,就會導致嚴重的問題。

1. 依賴的演變

包或者庫都是從 Internet 下載的代碼,將一個包作為依賴項添加自己的程序中,該程序暴露依賴項中的所有失敗和缺陷,因為它完全依賴于這些下載的代碼。這種方式聽起來非常不安全。為什么人們這么做?因為它很簡單,看起來很有效,是引用內部依賴的自然延續(xù)。

過去,大多數開發(fā)人員都信任自己所依賴的軟件,比如操作系統(tǒng)和編譯器。這些軟件是從已知的來源購買的,雖然存在著漏洞的可能性,但至少開發(fā)者知道他們在和誰打交道,通常有商業(yè)或法律資源可用。

在互聯(lián)網上免費分發(fā)的開源軟件已經取代了許多早期購買的軟件。一些項目建立起了眾所周知的聲譽,例如早期軟件包 libjpeg (1991),HP STL (1994)和 zlib (1995)等,聲譽往往會成為了人們決定使用哪些依賴的重要因素,對信任軟件來源的商業(yè)和法律支持被聲譽支持所取代,這可能就是共識的力量。

依賴管理器進一步縮小了開源代碼重用模型的規(guī)模?,F(xiàn)在,開發(fā)人員可以在由數十行代碼組成的單個函數的粒度上共享代碼,這是一項重大的技術成就。無數的軟件包是可用的,編寫代碼可能涉及大量的軟件包,但是用于信任代碼的商業(yè)、法律和聲譽支持機制并沒有繼續(xù)下去。開發(fā)人員信任更多的代碼,而不需要太多的理由。

然而,采用不良依賴的成本可以看作是每個不良結果的成本乘以其發(fā)生的可能性之和。使用依賴項的場景決定了壞結果的成本。如果只是個人愛好,其中大多數壞結果的成本幾乎為零,因為只是在享受樂趣,風險概率幾乎為零。但是,如果是一個維護多年的生產軟件,依賴關系中的 bug 的成本可能非常高: 服務器可能宕機,敏感數據可能泄露,客戶可能受到傷害,甚至公司可能倒閉。高失敗成本使得評估和降低嚴重風險變得更加重要。

不管預期的成本是多少,都需要一些估計和減少添加軟件依賴性風險的方法。可能需要更好的工具來幫助,就像依賴管理器一直關注于降低下載和安裝的成本那樣。

2. 依賴的檢查

在使用代碼依賴時,基本的檢查可以讓我們了解遇到問題的可能性有多大。如果檢查中發(fā)現(xiàn)了可能出現(xiàn)的小問題,可以采取措施準備或者避免它們。如果檢查中發(fā)現(xiàn)了大問題,最好不要使用這個包, 也許能夠找到一個更合適的,也許需要自己開發(fā)一個。開源軟件包是由其作者發(fā)布的,希望它們會有用,但是較少有可用性或支持的保證。系統(tǒng)掛了,不得不調試這些包,整個項目的質量和性能風險都在我們自己身上。

因此,我們需要在依賴檢查時考慮一些因素。

2.1 設計

文件清楚嗎?API有清晰的設計嗎?如果作者能夠在文檔中很好地解釋依賴包的 API 及其設計,那么他們在源代碼中實現(xiàn)正確的可能性就會增加。使用清晰的、設計良好的 API 編寫代碼也更容易、更快,并且更少出錯。作者是否記錄了他們對客戶端代碼的期望,以使升級兼容呢?(例如 C++ 23的兼容性文檔。)

2.2 代碼質量

代碼寫得好嗎?讀一些代碼吧。作者看起來是否小心謹慎,始終如一?看到的代碼起我們想要調試的代碼嗎?需要有檢查代碼質量的系統(tǒng)方法。例如,簡單地編譯一個啟用了重要編譯器警告的 c 或 c + + 程序(例如-Wall) ,就可以讓開發(fā)人員了解在避各種未定義行為方面的嚴重程度,看看有多少不安全的代碼。忽略關于死記硬背的建議,轉而關注語義問題。

對不熟悉的開發(fā)實踐要保持開放的心態(tài)。例如,SQLite 庫提供了一個單獨的200,000行 c 源文件和一個單獨的11,000行稱為 amalgamation 的頭文件。這些文件的大小會引起最初的警覺,但是深入進去會發(fā)現(xiàn)實際的開發(fā)源代碼包含了一個100多個 c 源文件、測試和支持腳本的文件樹。事實證明,單文件分發(fā)是從原始數據源自動構建的,對于最終用戶,尤其是那些沒有依賴項管理器的用戶來說更加容易。另外,編譯后的代碼也運行得更快,因為編譯器可以看到更多的優(yōu)化機會。

2.3 測試

代碼有測試嗎?能運行它們嗎?測試確定了代碼的基本功能是正確的,并且表明開發(fā)人員對于保持代碼的正確性是認真的。例如,SQLite 開發(fā)樹有一個非常全面的測試套件,超過了30,000個單獨的測試用例,以及解釋測試策略的文檔。未來方案的修改可能會引入回歸測試,而這些回歸測試很容易被發(fā)現(xiàn)。

假設測試運行通過,還可以運行時檢測(如代碼覆蓋率分析、競爭檢測、內存分配檢查和內存泄漏檢測)來收集更多信息。

2.4 調試

找到包里的問題列表,里面有開放的 bug 報告嗎?使用多久了?是否有許多錯誤尚未修復?最近有什么錯誤被修復了嗎?如果看到很多關于 bug 的公開問題,而且已經公開了很長一段時間,這不是一個好的跡象。另一方面,如果關閉的問題表明缺陷很少,并且發(fā)現(xiàn)是及時修復的,那就太好了。

2.5 維護

查看包的提交歷史,代碼被積極維護了多長時間?現(xiàn)在還在積極維護嗎?積極維護了較長時間的軟件包更有可能繼續(xù)得到維護。有多少人在包上做了提交?許多軟件包是業(yè)余時間創(chuàng)建和分享的個人項目,還有一些是一群付費開發(fā)人員數千小時工作的結果。一般來說,后一種類型的軟件包更有可能迅速修復錯誤,進行穩(wěn)定的改進,并進行常規(guī)維護。

2.6 用法

是否有許多其他軟件依賴于此代碼庫?依賴管理器通常可以提供關于使用情況的統(tǒng)計數據,或者可以使用搜索來評估其他人使用該包的頻率。更多的用戶至少意味著有很多人能夠很好地使用代碼,并且能夠更快地發(fā)現(xiàn)新的 bug。廣泛的使用還可以避免持續(xù)維護的問題,因為有興趣的用戶可能會做出更多貢獻。

2.7 安全性

依賴包能夠處理不可信的輸入嗎?如果是,它是否對惡意輸入具有強大的抵抗力?它是否有列出安全問題的歷史?例如, 流行的 PCRE 正則表達式庫有諸如緩沖區(qū)溢出等問題的歷史,特別是在其解析器中。這一發(fā)現(xiàn)并沒有立即導致放棄 PCRE,但它確實使我們更仔細地考慮測試和隔離。

2.8 許可證

代碼是否得到了正確的許可?它到底有沒有許可證?公司是否接受這樣的許可證?很多 GitHub 上的項目都沒有明確的許可證。公司可能會對依賴項的許可證施加進一步的限制。例如,不允許使用類似 agpl 許可證授權的代碼,它可能過于繁瑣,也不允許使用類似 wtpl 的許可證,它可能過于模糊。

2.9 依賴的依賴

代碼庫是否有自己的依賴項?間接依賴關系中的缺陷與直接依賴關系中的缺陷一樣對程序不利。依賴管理器可以列出給定包的所有依賴項,理想情況下應該按照這里描述的方式檢查每個依賴項。具有許多依賴項的包會帶來額外的檢查工作,因為這些相同的依賴項會帶來需要進行評估的額外風險。

許多開發(fā)人員可能從來沒有看過依賴關系的完整列表,也不知道它們依賴什么。例如,包括 Babel、 Ember 和 Reactall 在內的許多流行項目間接依賴于一個名為 left-pad 的微型庫,該包由一個單獨的八行函數組成。在2016年3月,作者從 NPM 中刪除了這個包,無意中破壞了大多數 Node.js 用戶的構建。當時的轟動至今記憶猶新。

3. 依賴的測試

檢查過程應該包括運行庫自己的測試。如果庫通過了檢查,并且決定依賴于它,那么下一步應該是編寫新的測試,重點是我們應用程序所需的功能。這些測試通常以簡短的獨立程序開始,編寫這些程序是為了確保我們能夠理解庫的 API,并確保它完成預期的任務。值得付出額外的努力,將這些程序轉換為可以針對包的較新版本運行的自動化測試。如果發(fā)現(xiàn)了一個 bug 并且有了一個潛在的修復,那么希望能夠輕松地重新運行這些特定于項目的測試,以確保修復沒有破壞其他任何東西,值得對基本檢查所確定的可能存在問題的領域進行研究。

4. 依賴的抽象

根據庫的不同,也許更新會把軟件包帶向一個新的方向,也許會發(fā)現(xiàn)嚴重的安全問題,也許會有更好的選擇。出于所有這些原因,將項目輕松遷移到新的依賴項是值得的。

如果庫將在項目源代碼的許多地方使用,那么遷移到新的依賴項將需要對所有這些不同的源位置進行更改。更糟糕的是,如果庫在自己項目的 API 中公開,那么遷移到新的依賴項將需要對調用API 的所有代碼進行更改,而我們可能無法控制這些更改。為了避免這些代價,有必要定義一個自己的接口,并使用依賴項實現(xiàn)該接口的封裝。封裝應該只包含項目從依賴庫中需要的內容,而不是依賴庫提供的所有內容。理想情況下,這允許僅更改封裝接口來替換不同但同樣適合的依賴關系。每個項目的遷移到新接口時,將測試封裝接口的實現(xiàn)。

這種間接性使測試備用庫變得容易,并且它防止了在源代碼樹的其余部分中意外地引入依賴庫的內部方法。反過來,這又確保了在需要時可以輕松地切換到不同的依賴項。

5. 依賴的隔離

在運行時隔離依賴項也可能是適當的,以便限制錯誤可能造成的損害。例如,Google Chrome 允許用戶在瀏覽器中添加依賴文件/擴展代碼。因此,在一個糟糕的擴展中,一個可利用的 bug 不能自動訪問瀏覽器本身的整個內存,并且可以被阻止進行不適當的系統(tǒng)調用。如今,隔離依賴關系可以降低運行該代碼的相關風險。

可疑代碼的運行時隔離是困難的,而且很少完成。真正的隔離需要一種完全內存安全的語言,沒有非類型化的代碼。這不僅在 C和 C++ 語言中具有挑戰(zhàn)性,而且在提供受限制不安全操作的語言中也很具有挑戰(zhàn)性,例如 Java 在包含 JNI的時候,或者 Go和 Swift 在包含它們的“不安全”特性時。即使是在 JavaScript 這樣的內存安全語言中,代碼通常也可以訪問超出其需要的內容。針對這類問題的眾多可能防御措施之一,是更好地限制依賴。

6. 依賴的避免

如果一個依賴項看起來太危險,無法找到一種方法來隔離它,最好的答案可能是完全避免它,或者至少避免那些我們認為最有問題的部分。

如果只需要依賴庫的一小部分,最簡單的解決方案可能是復制所需的內容,當然,保留適當的版權和其他法律聲明。我們正在承擔修復錯誤、維護等責任,但也完全與更大的風險隔離開來。一點點復制總比一點點依賴要好。

7. 依賴的升級

升級帶來了引入新 bug 的機會,如果沒有相應的回報,為什么要冒這個風險呢?這種分析忽略了兩個成本。首先是最終升級的成本。在軟件方面,代碼更改的難度不是線性的,做10個小更改比做一個等價的大更改更簡單,也更容易做對。第二個問題是發(fā)現(xiàn)已修復bug 的代價。特別是在安全場景中,已知的錯誤可能會被利用,可能是攻擊者的闖入。

及時升級是很重要的,但這意味著向項目中添加新的代碼,這意味著要更新新版本依賴庫的風險評估。至少,需要瀏覽從當前版本到升級版本的變更差異,或者至少閱讀發(fā)布文檔,以確定升級代碼中可能需要關注的領域。如果許多代碼正在更改,以致難以消化,那么可以將這種情況納入風險評估。

重新運行依賴庫自己的測試也是有意義的。如果它具有自己的依賴項,那么項目的配置完全有可能使用與庫作者使用的不同版本依賴項。運行庫自己的測試可以快速識別特定于配置的問題。同樣,升級不應該是完全自動的。在部署升級版本之前,必須驗證它們是否適合自己的環(huán)境。

在大多數情況下,延遲升級比快速升級的風險更大。

8. 依賴的關注

重要的是要持續(xù)關注,甚至可能重新評估使用它們的決定。

首先,確保使用我們所認為的特定庫版本?,F(xiàn)在,大多數依賴管理器可以輕松記錄給定庫版本預期源碼的加密哈希值,然后在另一臺計算機或測試環(huán)境中重新下載這個庫時檢查這個哈希。這可以確保使用與我們檢查測試時相同的依賴源碼。

同樣重要的是,要注意新的間接依賴關系是否會爬進來。升級可以很容易地引入新的包,而我們的項目現(xiàn)在依賴于這些包。它們也是值得關注的,惡意代碼可能被隱藏在一個不同的包中。依賴關系還會影響項目的大小。

升級是重新考慮使用依賴項的自然時機,定期重新審視依賴關系也很重要。這個項目被放棄了嗎?也許是時候開始計劃取代這種依賴性了。

9. 依賴,該說不該說的

軟件復用好處不應被低估,依賴關系比以往任何時候都多,它給軟件開發(fā)人員帶來了積極的轉變。即便如此,我們卻沒有完全考慮到潛在的后果。

  • 關于軟件依賴有三個主要的建議:
  • 認識到問題,我們需要集中精力來解決這個問題。
  • 為今天建立最佳實踐,需要最佳實踐來使用依賴關系的管理。這意味著制定從決策到評估,以及減少和跟蹤風險的過程。事實上,正如工程師專注于測試一樣,有些人可能需要專注于管理依賴關系。
  • 為明天開發(fā)更好的依賴技術。依賴管理器基本上消除了下載和安裝的成本。未來的開發(fā)工作應該側重于降低使用依賴項所必需的評估和維護成本。構建工具至少應該使運行依賴庫自己的測試變得容易,還應該提供簡單的方法來隔離可疑的依賴庫。

對特定依賴關系的嚴格檢查需要大量工作,并且仍然有例外出現(xiàn)。對于每一個可能的新依賴,不太可能有開發(fā)人員真正付出這樣的努力,盡管文中給出的可能只是一個子集。

責任編輯:武曉燕 來源: 喔家ArchiSelf
相關推薦

2022-01-16 20:25:57

WebAssembly網絡

2021-05-06 10:26:49

穩(wěn)定幣加密貨幣

2021-10-18 11:42:23

數據系統(tǒng)權衡

2020-03-09 09:56:13

高并發(fā)高可用架構

2021-03-26 00:20:34

NFT區(qū)塊鏈數據庫

2020-02-04 18:27:38

人工智能倫理學一知半解

2022-11-16 12:48:38

2022-01-26 09:53:23

計算機體系結構

2020-06-17 14:13:29

索引數據庫場景

2024-02-05 08:35:32

VuenextTickDOM

2018-04-04 19:07:11

區(qū)塊鏈人工智能應用場景

2019-10-21 09:32:48

緩存架構分層

2020-05-07 10:29:29

瀏覽器Sessioncookie

2012-08-20 14:39:34

Me WidgetEmotion UI華為

2018-12-05 08:26:52

物聯(lián)網智能物聯(lián)網技術

2019-04-02 10:51:29

瀏覽器緩存前端

2021-01-15 08:10:26

Vue開發(fā)模板

2019-08-29 09:30:20

Java泛型構造器

2020-12-14 18:02:25

區(qū)塊鏈人民幣技術

2021-12-11 19:04:38

漏洞
點贊
收藏

51CTO技術棧公眾號