本文受The Principles of Good Programming(http://www.artima.com/weblogs/viewpost.jsp?thread=331531)啟發。我覺得這份列表已經足夠了,但這並不完全符合我個人的想法。此外,我還需要更多的論證、細節以及其他資料的連結。
KISS大多數系統如果保持簡單而不是複雜,效果最好。
為什麼
更少的程式碼可以花更少的時間去寫,Bug更少,並且更容易修改。簡單是複雜的最高境界。完美境地,非冗雜,而不遺。相關資料
KISS principle(http://en.wikipedia.org/wiki/KISS_principle)Keep It Simple Stupid (KISS)(http://principles-wiki.net/principles:keep_it_simple_stupid)YAGNIYAGNI的意思是“你不需要它”:在必要之前不要做多餘的事情。
為什麼
去做任何僅在未來需要的特性,意味著從當前迭代需要完成的功能中分出精力。它使程式碼膨脹;軟體變得更大和更復雜。怎麼做
在當你真正需要它們的時候,才實現它們,而不是在你預見到你需要它們的時候。相關資料
You Arent Gonna Need It(http://c2.com/xp/YouArentGonnaNeedIt.html)You’re NOT gonna need it!(http://www.xprogramming.com/Practices/PracNotNeed.html)You ain’t gonna need it(http://en.wikipedia.org/wiki/You_ain't_gonna_need_it)做最簡單的事情為什麼
僅有當我們只解決問題本身時,才能最大化地解決實際問題。怎麼做
捫心自問:“最簡單的事情是什麼?”。相關資料
Do The Simplest Thing That Could Possibly Work(http://c2.com/xp/DoTheSimplestThingThatCouldPossiblyWork.html)關注點分離關注點分離是一種將計算機程式分離成不同部分的設計原則,以便每個部分專注於單個關注點。例如,應用程式的業務邏輯是一個關注點而使用者介面是另一個關注點。更改使用者介面不應要求更改業務邏輯,反之亦然。
引用Edsger W. Dijkstra(https://en.wikipedia.org/wiki/Edsger_W._Dijkstra) (1974)所說:
我有時將其稱為“關注點分離”,即使這不可能完全做到,但它也是我所知道的唯一有效的思維整理技巧。這就是我所說的“將注意力集中在某個方面”的意思:這並不意味著忽略其他方面,只是對於從某一方面的視角公正地來看,另一方面是不相關的事情。
為什麼
簡化軟體應用程式的開發與維護。當關注點很好地分開時,各個部分可以被重用,並且可以獨立開發和更新。怎麼做
將程式功能分成聯絡部分儘可能少的模組。相關資料
Separation of Concerns(https://en.wikipedia.org/wiki/Separation_of_concerns)保持事情不再重複在一個系統內,每一項認識都必須有一個單一的、明確的、權威的表示。
程式中的每一項重要功能都應該只在原始碼中的一個地方實現。相似的函式由不同的程式碼塊執行的情況下,抽象出不同的部分,將它們組合為一個函式通常是有益的。
為什麼
重複(無意或有意的重複)會造成噩夢般的維護,保養不良和邏輯矛盾。對系統中任意單個元素的修改不需要改變其他邏輯上無關的元素。此外,相關邏輯的元素的變化都是可預測的和均勻的,因此是保持同步的。怎麼做
只在一個處編寫業務規則、長表示式、if語句、數學公式、元資料等。確定系統中使用的每一項認識的唯一來源,然後使用該源來生成該認識的適用例項(程式碼、文件、測試等)。使用三法則(Rule of three)(http://en.wikipedia.org/wiki/Rule_of_three_(computer_programming)).相關資料
Dont Repeat Yourself(http://c2.com/cgi/wiki?DontRepeatYourself)Don’t repeat yourself(http://en.wikipedia.org/wiki/Don't_repeat_yourself)Don’t Repeat Yourself(http://programmer.97things.oreilly.com/wiki/index.php/Don't_Repeat_Yourself)相似資料
Abstraction principle(http://en.wikipedia.org/wiki/Abstraction_principle_(computer_programming))Once And Only Once(http://c2.com/cgi/wiki?OnceAndOnlyOnce) is a subset of DRY (also referred to as the goal of refactoring).Single Source of Truth(http://en.wikipedia.org/wiki/Single_Source_of_Truth)A violation of DRY is WET(http://thedailywtf.com/articles/The-WET-Cart) (Write Everything Twice)為維護者寫程式碼為什麼
到目前為止,維護是任何專案中最昂貴的階段。怎麼做
成為維護者。不論何時編寫程式碼,要想著最後維護程式碼的人是一個知道自己住在哪裡的暴力精神病人。如果某個入門的人掌握了程式碼,他們就會從閱讀和學習程式碼中獲得樂趣,以這樣的想法去編寫程式碼和註釋。別讓我想(Don’t make me think)(http://www.sensible.com/dmmt.html).使用最少驚訝原則(Principle of Least Astonishment)(http://en.wikipedia.org/wiki/Principle_of_least_astonishment).相關資料
Code For The Maintainer(http://c2.com/cgi/wiki?CodeForTheMaintainer)The Noble Art of Maintenance Programming(http://blog.codinghorror.com/the-noble-art-of-maintenance-programming/)避免過早最佳化引用Donald Knuth(http://en.wikiquote.org/wiki/Donald_Knuth)所說:
程式設計師浪費大量的時間來思考或擔心程式的非關鍵部分的速度,而考研嘗試這些最佳化實際上在除錯和維護時有很強的負面影響。比如說在97%的開發時間,我們應該忽略低效率:過早的最佳化是萬惡之源。然而,我們不應該在關鍵的3%中放棄我們的機會。
當然,需要理解什麼是“過早”什麼不是“過早”。
為什麼
瓶頸在哪是未知的。最佳化後,閱讀和維護可能會更困難。怎麼做
使它運作,使它正確,使它更快(Make It Work Make It Right Make It Fast)(http://c2.com/cgi/wiki?MakeItWorkMakeItRightMakeItFast)不要在你不需要的時候最佳化,只有在你發現一個瓶頸之後才能最佳化它。相關資料
Program optimization(http://en.wikipedia.org/wiki/Program_optimization)Premature Optimization(http://c2.com/cgi/wiki?PrematureOptimization)最小化耦合模組/元件之間的耦合是它們互相依賴的程度,較低的耦合更好。換句話說,耦合是程式碼單元“B”在未知的程式碼單元“A”更改後“被破壞”的機率。
為什麼
一個模組的更改通常會導致其他模組的更改,產生漣漪效益。由於模組間的依賴性增加,模組裝配可能需要更多的工作和/或時間。特定的模組可能難以重用和/或測試,因為必須包含相關模組。開發人員可能害怕更改程式碼,因為他們不確定什麼會受到影響。怎麼做
消除,最小化和降低必要關聯的複雜性。透過隱藏實現細節,減少耦合。使用迪米特法則(https://mouse0w0.github.io/2018/10/04/Programming-Principles/#迪米特法則)。相關資料
Coupling(http://en.wikipedia.org/wiki/Coupling_(computer_programming))Coupling And Cohesion(http://c2.com/cgi/wiki?CouplingAndCohesion)迪米特法則不要和陌生人說話。
為什麼
這通常會導致更緊密的耦合。可能會暴露過多的實現細節。怎麼做
物件的方法只能呼叫以下方法:
物件自身的方法。方法引數中的方法。方法中建立的任何物件的方法。物件的任何直接屬性或欄位的方法。相關資料
Law of Demeter(http://en.wikipedia.org/wiki/Law_of_Demeter)The Law of Demeter Is Not A Dot Counting Exercise(http://haacked.com/archive/2009/07/14/law-of-demeter-dot-counting.aspx/)組合優於繼承為什麼
類之間的耦合減少。使用繼承,子類很容易做出假設,並破壞里氏代換原則(LSP)。怎麼做
測試LSP(可替換性)以決定何時繼承。當存在“有”(或“使用”)的關係時使用組合,當存在“是”的關係時使用繼承。相關資料
Favor Composition Over Inheritance(http://blogs.msdn.com/b/thalesc/archive/2012/09/05/favor-composition-over-inheritance.aspx)正交性正交性的基本概念是,概念上不相關的東西在系統中不應該相關。
它越簡單,設計越正交,異常就越少。這使得用程式語言學習、讀寫程式變得更容易。正交特徵的含義是獨立於環境;關鍵引數是對稱性與一致性。
穩健性原則堅持保守自己的作為,自由接受他人的作為。
合作的服務依賴於彼此的介面。通常,介面需要提升,導致另一端接收未指定的資料。如果接收到的資料沒有嚴格遵守規範,那麼簡單的實現將僅拒絕合作。更復雜的實現卻可以忽略它無法識別的資料。
為什麼
為了能夠提高服務,你需要確保提供者可以進行更改以支援新的需求,同時對現有客戶端造成最小的破壞。怎麼做
向其他機器(或同一機器上的其他程式)傳送指令或資料的程式碼應該完全符合規範,但接受輸入的程式碼應接受不一致的輸入,只要其意義明確。相關資料
Robustness Principle in Wikipedia(https://en.wikipedia.org/wiki/Robustness_principle)Tolerant Reader(http://martinfowler.com/bliki/TolerantReader.html)控制反轉控制反轉又被稱為好萊塢原則,“不要打電話給我們,我們會打電話給你”。它是一種設計原則,計算機程式的自定義編寫部分從通用框架接收控制流。控制反轉具有強烈的含義,即可重用程式碼和特定於問題的程式碼是獨立開發的,即使它們在應用程式中一同工作。
為什麼
控制反轉用於提高程式的模組性,使其具有可擴充套件性。將任務的執行與實現分離。將模組集中在其設計任務上。使模組不受關於其他系統如何執行其任務的假設約束,而是依賴於約定。以防止模組更換時出現副作用。怎麼做
使用工廠模式使用服務定位器模式使用依賴注入使用依賴查詢使用模板方法模式使用策略模式相關資料
Inversion of Control in Wikipedia(https://en.wikipedia.org/wiki/Inversion_of_control)Inversion of Control Containers and the Dependency Injection pattern(https://www.martinfowler.com/articles/injection.html)最大化聚合單個模組/元件的聚合性是其職責形成有意義的單元的程度,越高的聚合性越好。
為什麼
增加了理解模組的難度。增加了維護系統的難度,因為域中邏輯的更改會影響多個模組,並且一個模組的更改需要相關模組的更改。由於大多數應用程式不需要模組提供的隨機操作集,因此重用模組的難度增加。怎麼做
與組相關的功能共享一項職責(例如在一個類中)。相關資料
CohesionCoupling And Cohesion(http://c2.com/cgi/wiki?CouplingAndCohesion)里氏代換原則里氏代換原則(LSP)完全是關於物件的預期行為:
程式中的物件應該可以替換為其子型別的例項,而不會改變該程式的正確性。
相關資源
Liskov substitution principle(http://en.wikipedia.org/wiki/Liskov_substitution_principle)Liskov Substitution Principle(http://www.blackwasp.co.uk/lsp.aspx)開放/封閉原則軟體實體(例如類)應對擴充套件是開放的,但對修改是封閉的。也就是說,這樣的實體可以允許在不改變其原始碼的情況下修改其行為。
為什麼
透過最小化對現有程式碼的修改來提高可維護性和穩定性怎麼做
編寫可以擴充套件的類(而不是可以修改的類)只暴露需要更換的活動部分,隱藏其他所有部分。相關資源
Open Closed Principle(http://en.wikipedia.org/wiki/Open/closed_principle)The Open Closed Principle(https://8thlight.com/blog/uncle-bob/2014/05/12/TheOpenClosedPrinciple.html)單一職責原則一個類不應該有多個修改的原因。
長話版:每個類都應該有一個單獨的職責,並且該職責應該完全由該類封裝。職責可以定義為修改的原因,一次類或模組應該有且僅有一個修改的原因。
為什麼
可維護性:僅有一個模組或類中需要修改。怎麼做
使用 科裡定律(https://mouse0w0.github.io/2018/10/04/Programming-Principles/#科裡定律).相關資料
Single responsibility principle(http://en.wikipedia.org/wiki/Single_responsibility_principle)隱藏實現細節軟體模組透過提供介面來隱藏資訊(即實現細節),而不洩露任何不必要的資訊。
為什麼
當實現更改時,客戶端使用的介面不必更改。怎麼做
最小化類和成員的可訪問性。不要公開成員資料。避免將私有實現細節放入類的介面中。減少耦合以隱藏更多實現細節。相關資料
Information hiding(http://en.wikipedia.org/wiki/Information_hiding)科裡定律科裡定律是關於為任何特定程式碼選擇一個明確定義的目標:僅做一件事。
Curly’s Law: Do One Thing(http://blog.codinghorror.com/curlys-law-do-one-thing/)The Rule of One or Curly’s Law(http://fortyplustwo.com/2008/09/06/the-rule-of-one-or-curlys-law/)封裝經常修改的程式碼一個好的設計可以辨別出最有可能改變的熱點,並將它們封裝在API之後。當預期的修改發生時,修改會保持在區域性。
為什麼
在發生更改時,最小化所需的修改。怎麼做
封裝API背後不同的概念。將可能不同的概念分到各自的模組。相關資料
Encapsulate the Concept that Varies(http://principles-wiki.net/principles:encapsulate_the_concept_that_varies)Encapsulate What Varies(http://blogs.msdn.com/b/steverowe/archive/2007/12/26/encapsulate-what-varies.aspx)Information Hiding(https://en.wikipedia.org/wiki/Information_hiding)介面隔離原則將臃腫的介面減少到多個更小更具體的客戶端特定介面中。介面應該比實現它的程式碼更依賴於呼叫它的程式碼。
為什麼
如果類實現了不需要的方法,則呼叫方需要了解該類的方法實現。例如,如果一個類實現了一個方法,但只是簡單的丟擲異常,那麼呼叫方將需要知道實際上不應該呼叫這個方法。怎麼做
避免臃腫的介面。類不應該實現任何違反單一職責原則(https://mouse0w0.github.io/2018/10/04/Programming-Principles/#單一職責原則)的方法。相關資料
Interface segregation principle(https://en.wikipedia.org/wiki/Interface_segregation_principle)童子軍軍規美國童子軍有一條簡單的軍規,我們可以使用到我們的職業中:“離開營地時比你到達時更乾淨”。根據童子軍軍規,我們應該始終保持程式碼比我們看到時更乾淨。
為什麼
當對現有程式碼庫進行更改時,程式碼質量往往會降低,從而積累技術債務。根據童子軍軍規,我們應該注意每一個提交(Commit)的質量。無論規模有多小,技術債務都會受到不斷重構的抵制。怎麼做
每次提交都要確保它不會降低程式碼庫的質量。任何時候,如果有人看到一些程式碼不夠清楚,他們就應該抓住機會在那裡修復它。相關資料
Opportunistic Refactoring(http://martinfowler.com/bliki/OpportunisticRefactoring.html)命令查詢分離命令查詢分離原則規定,每個方法都應該是執行操作的命令,或者是向呼叫者返回資料但不能同時做兩件事的查詢。提問不應該改變答案。
利用這個原則,程式設計師可以更加自信地進行編碼。查詢方法可以在任何地方以任何順序使用,因為它們不會改變狀態。而使用命令,你必須更加小心。
為什麼
透過將方法清晰地分為查詢和命令,程式設計師可以在不瞭解每個方法的實現細節的情況下,更加自信地編碼。怎麼做
將每個方法實現為查詢或命令。對方法名使用命名約定,該方法名錶示該方法是查詢還是命令。相關資料
Command Query Separation in Wikipedia(https://en.wikipedia.org/wiki/Command–query_separation)Command Query Separation by Martin Fowler(http://martinfowler.com/bliki/CommandQuerySeparation.html)本文翻譯自Programming Principles(http://java-design-patterns.com/principles/)