總之不要寫就對了 :)
讓函數或變數本身就可以說明自己
縮排
對齊
對象曝露行為,隱藏數據
數據暴露結構,沒有明顯的行為
將錯誤處理分開隔離,獨立於主邏輯之外,就可以單獨處理其錯誤
API邊界
尚未存在的程式邊界
可讀性!!
Build-Operate-Check 構造-操作-檢驗
測試宣告:BDD(Behavior Driven Development): Given-When-Then原則
應該短小,且更加短小
單一權責原則(Single Responsibility Principle):
class / module應該只會有一條修改其的理由,一個系統應該由許多短小的class而不是少量龐大的class組成,每個小class只封裝一個權責,且只有一個修改他的理由,與其他class達成期望的系統行為
內聚性
class 中應該只有少數的變量,class內的方法應該要操作一或多個其中的變量,這表示class的方法與變數互相有關,形成一個邏輯整體
OCP Open-Close-Principle 開放封閉原則
透過將class中各個方法拆解為class的派生(繼承)子類別後,可以利用擴充方式來擴充既有的子類別,而非動到原始的class去更改程式碼
e.g. 像是class apple 有許多方法(make flowers, get taller, add one leaf…等),透過將其各種方法拆解成class bloom extends apple, class grow extends apple,這樣我們就可以利用派生的子class去擴充子class的方法,而不會動到原本的class apple
測試驅動系統架構,而非先做大設計(從整個系統框架都想好後再做),在之後的迭代和更新新增功能會更加彈性
整潔的系統有利於敏捷開發
使用大概可以工作的最簡單方案
簡單設計的四條規則(重要性由上至下)
2~4:重構
每次增加或修改代碼之後,回顧其修改後的代碼,讓設計更加整潔(提升內聚性 降低耦合 模塊化 縮小尺寸 更好的命名),並運行測試且通過它!
不可重複
把可以共用的部分抽取出來,如此一來不僅減少測試,且也減少額外的風險(萬一被修改或刪除)
表達程式設計者的意圖
如果花十分鐘寫程式(一般較具有系統的專案),讀9分寫1分,不管是新增還是之後的維護,都會花大量的時間去理解既有的程式碼,因此如果能把程式保持短小精簡,且命名各個功能/變數到位,那麼讀起來會更加輕鬆,你開心大家都開心 :)
盡可能減少classes / methods的數量
不要有太多細小的classes / methods,但是此條規則為優先程度最低的,意即在達到以上三點之後,再來考慮這點吧!
開發上的防禦原則
SRP 單一權責原則
將多線程執行的代碼和其他代碼分離,否則如果商業邏輯與多線程互相耦合,則會難以修改與除錯
限制數據作用域
當數據有共享時,要注意各個線程可能會互相干擾,導致無法預期的錯誤,因此要限制其數據的作用區域範圍!
使用數據複製
呈上,避免共享數據是更好的方法,透過複製唯讀數據的方式來拿取數據的副本,在最後再將其數據做整合處理
多線程之間盡可能獨立
各個線程就像是平行世界,從源頭複製所需的數據,再各自處理和暫存數據,並可以再透過資料庫的方式共享資源
一開始就寫完美程式,是不可能的!擁抱醜陋,先從醜醜的草稿開始吧!
再來逐漸改進,越改越好,但不是說一開始能工作的醜醜程式就把她留著(很多人寫完能動的程式碼就認為完工了),一有機會就要將他重構或改寫的更好!
透過一次次的小小重構和抽離,並通過測試確保程式可行,將程式各個模組分開,降低依賴耦合程度!
如果在上午寫了混亂的程式碼,下午就趁熱把它解決,不讓混亂變得更亂!
透過抽象化方法,將程式寫得更加簡潔且清楚,在每次寫程式後都比原來更整潔
將各個方法或函式分類整理到適合該class或檔案的地方,讓語意更加達意
修改變數名稱,讓變數名稱能更符合修改後的情境,且更好理解
註釋
冗餘或程式本身就可以解釋的註釋都是不用寫的!
特別是被注釋掉的程式,現在可以透過git等工具去取得之前的版本,儘管刪掉沒關係!
函數
一般問題
code.16
//此範例就是混合了兩個抽象層級, 一個是針對字串的直接操作,一個是調用函數
function renderTypedString(str: string) {
return '_' + str + getSeparatedStr(str)
}
//可以改成像是以下,不僅比較好測試,且更清楚!
function getUnderlinedStr(str: string)) {
return '_' + str
}
function renderTypedString(str: string) {
return getUnderlinedStr(str) + getSeparatedStr(str)
}
newScore = score + averageScore
而非k = j + 10
function doGetDataFromDB() { ... }
然而以上方法只有提到取得資料而沒有描述該關閉連接的功能,就應該改為function doGetDataFromDBThenDiconnectDB() { ... }
會比較好(儘管名稱真的很長)constants 用config等等的從外部引入