我總結(jié)了一些軟件開發(fā)原則。這些原則大多以簡(jiǎn)化系統(tǒng)為核心。在我看來,一個(gè)簡(jiǎn)單的系統(tǒng)將更加可靠,更容易修改,并且通常更容易使用。當(dāng)我的想法改變時(shí),我想更新它們。

1
消除無效狀態(tài)。
我把這一點(diǎn)放在第一位,因?yàn)槲艺J(rèn)為這是最重要、最強(qiáng)大的原則之一。
這個(gè)詞在定義類型時(shí)可能聽到過,但實(shí)際上這一原則適用于所有與表示數(shù)據(jù)相關(guān)的地方——比如數(shù)據(jù)庫(kù)設(shè)計(jì)。
它不僅可以減少系統(tǒng)的狀態(tài)數(shù)量(從而變得更簡(jiǎn)單),還可以減少無效狀態(tài)的數(shù)量!您的系統(tǒng)不需要處理這些無效狀態(tài),因?yàn)樗鼈儗?shí)際上不能在您的程序中顯示。
這不僅僅是一個(gè)小技巧,它可以極大地簡(jiǎn)化你的系統(tǒng),防止各種類型的bug。
2
數(shù)據(jù)一致性使系統(tǒng)更加簡(jiǎn)單。
對(duì)數(shù)據(jù)施加一致性規(guī)則,減少系統(tǒng)需要處理的狀態(tài)數(shù)量。這是從上一個(gè)原則中衍生出來的。
定義
這是一致性的一般含義:數(shù)據(jù)遵循某些規(guī)則,并始終在任何時(shí)候遵循這些規(guī)則。這個(gè)定義與ACID有關(guān),但不要與CAP混淆。
規(guī)則可以是任何東西。例如,您的信用永遠(yuǎn)不會(huì)變?yōu)樨?fù)數(shù),或者其他人不應(yīng)該看到私人帖子。它不限于外鍵或唯一索引,盡管它們也是有效的規(guī)則。
與數(shù)據(jù)庫(kù)一樣,應(yīng)用程序也可以通過使用ACID事務(wù)來加強(qiáng)一致性。最好是在數(shù)據(jù)庫(kù)級(jí)別上保持一致性,但在實(shí)踐中,這對(duì)于稍微復(fù)雜的事情來說并不常見。
實(shí)用建議
任何限制或破壞一致性的行為都會(huì)導(dǎo)致復(fù)雜性。這就提出了以下實(shí)際建議:
使系統(tǒng)更:
更少的數(shù)據(jù)庫(kù)(理想情況下是一個(gè))
標(biāo)準(zhǔn)化,減少冗余數(shù)據(jù)。
一個(gè)好數(shù)據(jù)庫(kù)設(shè)計(jì)。
ACID事務(wù)。
更多的數(shù)據(jù)約束。
使系統(tǒng)更加復(fù)雜:
多個(gè)數(shù)據(jù)庫(kù)
冗余或非標(biāo)準(zhǔn)化數(shù)據(jù)。
數(shù)據(jù)庫(kù)設(shè)計(jì)不好。
數(shù)據(jù)約束較少(或沒有)。
當(dāng)然,有時(shí)候也有正當(dāng)?shù)睦碛勺屜到y(tǒng)變得復(fù)雜。我不希望復(fù)雜性變成一個(gè)骯臟的詞。請(qǐng)參考下面的原則不要用牛刀殺雞。
我認(rèn)為這一原則是當(dāng)今軟件工程中最被低估的原則之一。一致性問題經(jīng)常被忽視。很多問題,我敢說,大多數(shù)問題基本上都是一致——數(shù)據(jù)不符合一些期望。
參見附錄,了解不一致是如何導(dǎo)致復(fù)雜性的。
3
先行數(shù)據(jù)設(shè)計(jì)。
這個(gè)問題,代碼還是數(shù)據(jù)?
代碼可以丟失和重寫,但數(shù)據(jù)很少。
數(shù)據(jù)比代碼更重要。代碼的唯一目的是轉(zhuǎn)換數(shù)據(jù)。
在設(shè)計(jì)新系統(tǒng)時(shí),最好從數(shù)據(jù)庫(kù)和數(shù)據(jù)結(jié)構(gòu)開始,并在此基礎(chǔ)上開發(fā)代碼。理想情況下,通過表達(dá)數(shù)據(jù)來考慮可以應(yīng)用于數(shù)據(jù)的約束和實(shí)現(xiàn)。
代碼設(shè)計(jì)是數(shù)據(jù)設(shè)計(jì)的下一步。數(shù)據(jù)模型越簡(jiǎn)單,代碼就越簡(jiǎn)單。
你給我看流程圖,但是當(dāng)你把表藏起來的時(shí)候,我很困惑。如果你給我看你的表,我通常不需要你的流程圖,這是不言而喻的。-fredbrooks。
不好的程序員關(guān)心代碼。良好的程序員關(guān)心的是數(shù)據(jù)結(jié)構(gòu)和它們之間的關(guān)系。-Linustorvalds,Linux之父。
4
不要用牛刀殺雞。
這是軟件開發(fā)人員最常犯的錯(cuò)誤。
這一原則意味著,在權(quán)衡需要付出復(fù)雜性的成本時(shí),要確保權(quán)衡的必要性得到經(jīng)驗(yàn)證據(jù)的支持。
常見錯(cuò)誤:
試圖構(gòu)建一個(gè)復(fù)雜的可伸縮系統(tǒng),可以擴(kuò)展到你可能永遠(yuǎn)不需要的規(guī)模。
使服務(wù)盡可能小,不考慮需求或成本。
優(yōu)化性能,增加不一致性或復(fù)雜性。
建議:
盡量從最簡(jiǎn)單、最正確的系統(tǒng)開始。
測(cè)量性能。
如果實(shí)際問題無法解決,不要付出復(fù)雜的代價(jià)或違反其他原則。
有些優(yōu)化無法衡量,因?yàn)樗鼈兊某杀痉浅5突驗(yàn)榱恪@?,使用正確的數(shù)據(jù)結(jié)構(gòu),以確保您想要執(zhí)行的操作具有您想要的性能。
的確,有時(shí)候經(jīng)驗(yàn)本身就能告訴你是否做出了正確的權(quán)衡。但是如果你能證明的話,那就更好了。
當(dāng)你必須做出選擇時(shí),請(qǐng)選擇正確性和簡(jiǎn)單性,而不是性能。
在某些情況下,正確而簡(jiǎn)單的代碼是性能最好的代碼!
真正的問題是,程序員花太多時(shí)間在錯(cuò)誤的地方和錯(cuò)誤的時(shí)間上擔(dān)心效率。早期優(yōu)化是編程中所有罪惡的根源(或至少大多數(shù))。-計(jì)算機(jī)科學(xué)家。
5
避免為局部簡(jiǎn)單性增加全局復(fù)雜性。
也就是說,避免整個(gè)系統(tǒng)變得更復(fù)雜,以使系統(tǒng)的一部分更簡(jiǎn)單。
這種交換通常是不平等的。對(duì)局部簡(jiǎn)單性的追求會(huì)導(dǎo)致整體復(fù)雜性的增加,而且是數(shù)量級(jí)的。
例如,使用較小的服務(wù)可以使這些服務(wù)變得更簡(jiǎn)單,但是減少一致性和需要更多的過程間通信使系統(tǒng)更加復(fù)雜。
6
識(shí)別內(nèi)部復(fù)雜性。
有時(shí)候事情本身就很復(fù)雜,你不能簡(jiǎn)化問題。
任何這樣的嘗試都只會(huì)使系統(tǒng)更加復(fù)雜。
7
使用的技術(shù)越少,系統(tǒng)就越簡(jiǎn)單。
對(duì)一小部分技術(shù)的深入理解比對(duì)許多技術(shù)的表面理解要好。
更少的技術(shù)意味著更少的東西需要學(xué)習(xí),更少的操作和維護(hù)復(fù)雜性。
8
專注于學(xué)習(xí)概念,而不是技術(shù)。
不要過分關(guān)注技術(shù)的復(fù)雜細(xì)節(jié),因?yàn)槟憧梢噪S時(shí)查閱它們。你必須學(xué)習(xí)基本概念。
技術(shù)會(huì)改變,但這個(gè)概念是永恒的。在更新的技術(shù)中使用你學(xué)到的概念,你可以更快地學(xué)習(xí)新技術(shù)。
例如,不要過分關(guān)注React、Kubernetes、Haskell、Rust。
重點(diǎn)學(xué)習(xí):
純函數(shù)式編程。
關(guān)系型模型
規(guī)范的方法
邏輯編程
代數(shù)數(shù)據(jù)類型。
類型(通用和特定)
借位檢查員(仿射/線性類型)
依賴類型
HowardCurrry。
宏
(homoicoicicity)
Virtualdom。
線性回歸
...
9
代碼一致性很重要。
有時(shí),一致性代碼比正確代碼更重要。如果要更改代碼庫(kù)中某些代碼的行為,請(qǐng)修改所有示例。否則,你只能忍受。
代碼的可讀性更多地與一致性(而不是簡(jiǎn)單性)有關(guān)。人們通過模式識(shí)別來理解代碼,所以請(qǐng)重復(fù)(和記錄)模式!
10
共享原則很重要。
如果你和隊(duì)友之間有更多的共同原則,你就能更好地一起工作,你就會(huì)更喜歡和他們一起工作。
11
附錄:由不一致性引起的復(fù)雜性。
這是我能想到的最簡(jiǎn)單的例子,希望能與實(shí)際問題毫不費(fèi)力地聯(lián)系起來。
假設(shè)一個(gè)數(shù)據(jù)庫(kù)有兩個(gè)布爾變量x和y,你的應(yīng)用程序有一個(gè)規(guī)則,即x=y,可以通過使用一個(gè)事務(wù)來修改這兩個(gè)變量來執(zhí)行這個(gè)規(guī)則。
如果正確執(zhí)行這一規(guī)則,數(shù)據(jù)只有兩種狀態(tài):(x=true,y=true)或(x=false,y=false)。
基于這一規(guī)則的函數(shù)toggle非常簡(jiǎn)單。您可以讀取其中一個(gè)值,并將兩個(gè)值設(shè)置為反向值。
現(xiàn)在,假設(shè)你把這兩個(gè)變量放在不同的數(shù)據(jù)庫(kù)中,不能一起修改,會(huì)發(fā)生什么?
數(shù)據(jù)可以有兩種以上的狀態(tài):(x=true,y=false)或(x=false,y=true),因?yàn)槟銦o法保證x=y的一致性。
如果您的系統(tǒng)處于這些狀態(tài)之一,您應(yīng)該使用哪個(gè)值?
toggle函數(shù)的行為是什么?
在寫入新值時(shí),如何保證兩次寫入都成功?
沒有正確答案。
當(dāng)然,如果我們從一開始就遵循消除無效狀態(tài)的原則,那么只有一個(gè)變量!