hacker-laws 的的中文翻譯。php
對開發人員有用的定律,理論,原則和模式。(Laws, Theories, Principles and Patterns that developers will find useful.)git
爲了方便閱讀,維基百科增長了中文連接!github
英文連接表示 hacker-laws 項目還沒有完成。正則表達式
github 地址數據庫
當談論到開發時,人們會談到許多定律。 這個倉庫收錄了一些最多見的定律。請分享這個倉庫並提交 PR !編程
❗: 這個倉庫包含對一些定律、原則以及模式的解釋,但不提倡其中任何一個。 它們的應用始終存在着爭論,而且很大程度上取決於你正在作什麼。安全
如今咱們開始吧!服務器
阿姆達爾定律是一個顯示計算任務潛在加速能力的公式。這種能力能夠經過增長系統資源來實現。 一般用於並行計算中,它能夠預測增長處理器數量的實際好處。增長處理器數量會受到程序並行性的限制。markdown
舉例說明:若是程序由兩部分組成,部分 A 必須由單個處理器執行,部分 B 能夠並行運行,那麼咱們向執行程序的系統添加多個處理器只能得到有限的好處。 它能夠極大地提高部分 B 的運行速度,但部分 A 的運行速度將保持不變。網絡
下圖展現了運行速度的潛能:
(圖片來源: By Daniels220 at English Wikipedia, Creative Commons Attribution-Share Alike 3.0 Unported, en.wikipedia.org/wiki/File:A…)
能夠看出,50% 並行化的程序僅僅受益於 10 個處理單元,而 95% 並行化的程序能夠經過超過一千個處理單元顯著提高速度。
隨着摩爾定律減慢,以及單個處理器的速度增長緩慢,並行化是提升性能的關鍵。 圖形編程是一個很好的例子,現代着色器能夠並行渲染單個像素或片斷。這也是爲何現代顯卡一般具備數千個處理核心(GPU 或着色器單元)的緣由。
參見:
布魯克斯是《人月神話》的做者。
軟件開發後期,添加人力只會使項目開發得更慢。
這個定律代表,在許多狀況下,試圖經過增長人力來加速延期項目的交付,將會使項目交付得更晚。 布魯克斯也明白,這是一種過分簡化。但通常的推理是,新資源的增長時間和通訊開銷,會使開發速度減慢。 並且,許多任務是不可分的,好比更多的資源容易分配,這也意味着潛在的速度增長也更低。
諺語 九個女人不能在一個月內生一個孩子 與布魯克斯法則同出一轍,特別是某些不可分割或者並行的工做。
參見:
系統的技術邊界受制於組織的結構。在改進組織時,一般會提到它。康威定律代表,若是一個組織被分散成許多小型、無聯繫的單元,那麼它開發的軟件也是小而分散的。 若是一個組織更多地垂直創建在特性或服務周圍,那麼軟件系統也會反映這一點。
參見:
即便考慮到侯世達定律,它也老是比你預期的要長。
在估計須要多長時間時,您可能會聽到此定律。軟件開發中彷佛不言而喻,咱們每每不能準確地估計須要多長時間才能完成。
咱們傾向於太高估計技術在短時間內的影響,並低估長期效應。
(羅伊阿馬拉)
技術成熟度曲線是高德納諮詢公司最初製做的技術興起和發展的直觀表現。一圖頂千言:
(圖片來源: By Jeremykemp at English Wikipedia, CC BY-SA 3.0, commons.wikimedia.org/w/index.php…)
簡而言之,這個週期代表,新技術及其潛在影響一般會引起一陣浪潮。 團隊快速使用這些新技術,有時會對結果感到失望。 這多是由於該技術還不夠成熟,或者現實應用尚未徹底實現。 通過一段時間後,技術的能力提升了,使用它的實際機會會增長,最終團隊能夠提升工做效率。 羅伊·阿馬拉簡潔地總結了這一點:咱們傾向於高估技術短時間內的影響,並低估長期效應。
有足夠數量 API 的用戶, 你在合同中的承諾並不重要: 你係統的全部可觀察行爲 將取決於某人。
(Hyrum Wright)
隱式接口定律代表,當你擁有足夠數量的 API 用戶時,API 的全部行爲(即便那些未被定義爲公共說明的一部分)最終都會被某人所依賴。 一個簡單的例子,例如 API 的響應時間這種非功能性因素。 一個更微妙的例子是:用戶使用正則表達式判斷錯誤信息的類型。 即便 API 的公共說明沒有說明消息的內容,來指示用戶錯誤的類型。一些用戶可能會使用該消息,而且更改消息,實際上會破壞用戶的 API。
參見:
集成電路中的晶體管數量大約每兩年翻一番。
一般用於說明半導體和芯片技術提升的絕對速度。從 20 世紀 70 年代到 21 世紀後期,摩爾的預測被證實是高度準確的。 近年來,這種趨勢略有變化,部分緣由受到[量子隧穿效應](zh.wikipedia.org/wiki/量子穿隧效應… 然而,並行化計算的進步以及半導體技術和量子計算潛在的革命性變化,可能意味着摩爾定律在將來幾十年內繼續保持正確。
在工做可以完成的時限內,工做量會一直增長,直到全部可用時間都被填充爲止。
基於官僚機構的研究背景,該定律被應用於軟件開發中。該理論認爲,團隊在截止日期以前效率低下,而後在截止日期前趕忙完成工做,從而使實際截止日期有些隨意。
將這個定理與[侯世達定律](#侯世達定律)相結合,則會得到更加悲觀的觀點: 工做將擴大以填補所需時間,而且須要比預期更長的時間。
參見:
技術由兩類人主導,一類是管理人員, 一類是技術人員。
普特定律經常遵循普特推論:
每一個技術層次都會發展地逆轉。
這些結論代表,因爲各類選擇標準和羣體組織的趨勢,技術組織的工做層面將有一些技術人員,以及一些不瞭解複雜性和挑戰的管理人員。 這種現象多是因爲 The Peter Principe 或者 Dilbert's Law 形成的。
可是,應該強調的是,諸如此類的定律是一種普遍的歸納,可能適用於某些類型的組織,而不適用於其餘組織。
參見:
該定律代表系統中存在着必定程度的複雜性,而且不能減小。
系統中的某些複雜性是無心的。 這是因爲結構不良,錯誤或者糟糕的建模形成的。 能夠減小以及消除無心的複雜性。 然而,因爲待解決問題固有的複雜性,某些複雜性是內在的。 這種複雜性能夠移動,但不能消除。
一個該定律的有趣元素是,即便簡化整個系統,內在的複雜性也不會下降。它會移動到用戶,而且用戶必須以更復雜的方式行事。
在某種程度上,全部非平凡的抽象都是漏洞。
(喬爾斯 波爾斯基)
該定律指出,一般用於簡化複雜系統的抽象,某些狀況下將在底層系統有漏洞,這使得抽象表現爲意外的方式。
例如加載文件並讀取其內容。 文件系統 API 是較低級別內核系統的抽象,它們自己是與磁盤(或 SSD 的閃存)上的數據更改相關的物理過程抽象。 在大多數狀況下,處理文件(如二進制數據流)的抽象將起做用。 可是,對於磁盤驅動器,順序讀取數據將比隨機訪問快得多(因爲頁面錯誤的開銷增長)。但對於 SSD 驅動器,此開銷不會出現。 須要理解基礎細節來處理這種狀況(例如,數據庫索引文件的良好結構能夠減小隨機訪問的開銷),開發人員須要合理的抽象,來處理不一樣的細節。
當引入的抽象更多時,上面的例子會變得更復雜。 Linux 操做系統容許經過網絡訪問文件,但在本地表示爲普通文件。 若是存在網絡故障,這種抽象將有漏洞。 若是開發人員將這些文件視爲普通文件,而不考慮它們可能會受到網絡延遲和故障的影響,那麼解決方案就會出錯。
描述該定律的文章代表,過分依賴抽象,加上對底層過程的理解不足,實際上使得問題在某些狀況下更加複雜。
參見:
真實的例子:
該定理顯示,羣體將給予更多的時間和注意力來處理瑣碎的問題,而不是用來處理嚴肅而實質性的問題。
常見的虛構例子是委員會批准核電站的計劃,他們大部分時間都在討論自行車棚的結構,而不是電廠自己等更爲重要的設計。 若是沒有大量的專業知識或者準備,很難給很是大的複雜主題討論提供寶貴的意見。 可是,人們但願看到寶貴的意見。 所以,傾向於將過多的時間集中在小細節上,這很容易推理,但不必定特別重要。
上面的虛構例子致使使用Bike Shedding這個詞,做爲在瑣碎細節上浪費時間的表達。
Unix 哲學是軟件組件應該很小,並專一於作一件特定的事情。 將小型、簡單以及定義良好的單元組合在一塊兒,而不是使用大型、複雜以及多用途程序,能夠更輕鬆地構建系統。
像微服務架構這種現代實踐能夠被認爲是這種哲學的應用,其中服務很小,集中於作一件特定的事情,由簡單的構建塊組成複雜的行爲。
Spotify 模型是團隊和組織結構的一種方法,已被 Spotify 實驗室推廣。 在此模型中,團隊圍繞功能而非技術進行組織。
Spotify 模型還普及了部落、行會以及章節的概念,這些是其組織結構的其餘組成部分。
任何語言設計中,討論下面列表中某個要素所花費的總時間與其位置上的兩個要素成正比。
- 語義
- 語法
- 詞法
- 評論詞法
(簡而言之,對於語義上花費的每個小時,將在評論詞法上花費 8 小時)。
與 帕金森瑣碎定理 相似, 沃德勒定律指出,在設計語言時,與這些特徵的重要性相比,花在語言結構上的時間至關多。
參見:
原則一般是與設計相關的準則。
對本身所作的事情要保守,對本身接受的人要寬容。
一般應用於服務器應用程序開發中,該原則指出,你發送給其餘人的內容應儘量小且符合要求,而且處理不符合要求的輸入。
該原則的目標是構建穩健的系統。若是能夠理解意圖,它們能夠處理不良的輸入。 可是,接受錯誤格式的輸入可能存在安全隱患,特別是此類的輸入未通過充分測試。
這是一個縮寫,指的是:
這些是 Object-Oriented Programming 的關鍵原則。 諸如此類的設計原則可以幫助開發人員構建更易於維護的系統。
每一個模塊或者類只應該有一項功能。
SOLID 的第一個原則。 這個原則代表模塊後者類只應該作一件事。 實際上,這意味着對程序功能的單個小更改,應該只須要更改一個組件。 例如,更改密碼驗證複雜性的方式應該只須要更改程序的一部分。
理論上講,這使代碼更健壯,更容易更改。 知道正在更改的組件只有一個功能,這意味着測試更改更容易。 使用前面的例子,更改密碼複雜性組件應該隻影響與密碼複雜性相關的功能。 變動具備許多功能的組件可能要困可貴多。
參見:
實體應開放擴展並關閉修改。
SOLID 的第二個原則。 這個原則指出實體(能夠是類,模塊,函數等)應該可以使它們的行爲進行擴展,可是它們的擴展行爲不該該被修改。
舉一個假設的例子,想象一個可以將 Markdown 轉換爲 HTML 的模塊。 若是能夠擴展模塊以處理新的 markdown 特徵,而無需修改內部模塊,則能夠認爲是開放擴展。 若是用戶不能修改模塊以處理現有的 Markdown 特徵,那麼它被認爲是關閉修改。
這個原則與面向對象編程緊密相關,咱們能夠設計對象以便於擴展,可是能夠避免以意想不到的方式改變其現有對象的行爲。
參見:
能夠在不破壞系統的狀況下,用子類型替換類型。
SOLID 的第三個原則。 該原則指出,若是組件依賴於類型,那麼它應該可以使用該類型的子類型,而不會致使系統失敗或者必須知道該子類型的詳細信息。
舉個例子,假設咱們有一個方法,讀取 XML 文檔。 若是該方法使用基類型 file,則從 file 派生的任何內容,都能用在該方法中。 若是 file 支持反向搜索,而且 xml 解析器使用該函數,可是派生類型 network file 嘗試反向搜索時失敗,則 network file 將違反該原則。
該原則與面向對象編程特別有關,必須仔細建模類型層次,以免混淆系統用戶。
參見
不該該強迫客戶端依賴它不使用的方法。
SOLID 的第四個原則。 該原則指出組件的消費者不該該依賴於它實際上不使用的組件功能。
舉一個例子,假設咱們有一個方法,讀取 XML 文檔。 它只須要讀取文件中的字節,向前移動或向後移動。 若是因爲文件結構不相關(例如更新文件安全性的權限模型),須要更新此方法,則原則已失效。 文件最好實現 搜索流 接口,並讓 XML 讀取器使用它。
該原則與面向對象編程緊密相關,其中接口,層次結構和抽象類型用於不一樣組件的 minimise the coupling。 Duck typing 是一種經過消除顯式接口來強制執行該原則的方法。
參見:
高級模塊不該該依賴於低級實現。
SOLID 的第五個原則。 該原則指出,更高級別的協調組件不該該知道其依賴關係的細節。
舉個例子,假設咱們有一個從網站讀取元數據的程序。咱們假設主要組件必須知道下載網頁內容的組件,以及能夠讀取元數據的組件。若是咱們考慮依賴反轉,主要組件將僅依賴於能夠獲取字節數據的抽象組件,而後是一個可以從字節流中讀取元數據的抽象組件。主要組件不須要了解 TCP、IP、HTTP、HTML 等。
這個原則很複雜,由於它彷佛能夠反轉系統的預期依賴性(所以得名)。實踐中,這也意味着,單獨的編排組件必須確保抽象類型的正確實現被使用(例如在前面的例子中,必須提供元數據讀取器組件、HTTP 文件下載功能和 HTML 元標籤讀取器)。而後,這涉及諸如 Inversion of Control 和 Dependency Injection 之類的模式。
該項目還沒有編寫完成,最新進展請查看 github.com/nusr/hacker…