# 知識閱讀 -  陳皓 / 我做系統架構的一些原則

這次推薦的文章是來自 CodeShell  上面的 [陳皓 / 我做系統架構的一些原則 ](https://coolshell.cn/articles/21672.html)

滿多的概念是很不錯的，尤其又是中文的文張，在閱讀上也比較快速方便。詳細的內容我就不會去特別寫了，我只會針對各個原則上提出些我的看法和理解。

作者在這邊提出了十一個原則

### 原則一：關注於真正的收益而不是技術本身

作者這邊有提到要做架構設計，需要滿足三個條件：
1. 是否可以降低技術門檻加快整個團隊的開發流程
2. 是否可以讓整個系統可以運行的更穩定
3. 是否可以通過簡化和自動化降低成本

個人理解上，這邊的概念符合 DevOps 的文化。在開發上很大的成本會是人力成本，而將可以自動的就自動化起來，減少人力上的成本。

### 原則二：以應用服務和 API 為視角，而不是以資源和技術為視角

個人理解也認同作者的概念，在工作上會區分職位，所以判斷事情的角度會有所差別。以維運和資安的角度會希望越限縮越好，但開發者通常都希望越自由越好(個人經驗)。以現在的技術來說，Dev 跟 Ops 的工具也越來越模糊，功能越來越複雜，有時候要去區分也很難。但在團隊上應該要是大家有同一目標才對，這樣判斷的方向是一致的才好。
不過個人覺得更好的是說 **以產品方向為視角**

### 原則三：選擇最主流和成熟的技術

這是可以理解的，越是主流和成熟的技術。有更多的資源可以去學習，也有更多的管道可以去討論。不要去選擇自己熟悉的技術，而是要以最有效益的方式去選擇。不然到頭來會發現，之後要轉換技術會是很大的事情。 

### 原則四：完整性會比性能更重要

這也是真的很有感的地方，現在很多架構設計上都在追求效能。想吃多大多大的流量，但是一個產品最最基礎的資料，才是最核心的地方。作者提出兩個原則：

1. 使用最科學嚴謹的技術模型為主，並以不嚴謹的模型為補充
2. 性能上的東西，總是有很多解法的

### 原則五：制定並遵循服從標準、規範和最佳實踐

這就不用太廢話了，開發上不要不遵守標準然後又不有一套公司自有的標準，根本找死。以下列出作者提到的建議和規範（包括但不限於）：

* 服務間調用的協議標準和規範：其中包括 RESTful API 路徑、HTTP 方法、狀態碼、HTTP Header、返回數據 JSon Scheme ...
* 一些命名的標準和規範：User ID，Service name、標籤名、狀態名、錯誤碼、Message、資料庫 ...
* 日誌和監控的規範：日誌格式、監控資料、Alerting ...
* 設定上的規範：OS 設定、Middleware 設定、Packages ...
* Middleware 使用的規範：資料庫、Cache、Message Queue …
* 軟體和開發 Library 版本統一：整個組織架構內，軟體或開發 Library 的版本最好每年都升級一次，然後在各團隊內統一

重要提醒：

* RESTful API 規範：非常重要的事情，作者給兩個覺得寫得最好的參考 - [Paypal](https://github.com/paypal/api-standards/blob/master/api-style-guide.md) 和 [Microsoft](https://github.com/microsoft/api-guidelines)。RESTful API 有標準和規範最大的好處就是監控系統可以很容易地做各種統計分析，控制系統可以很容易的做流量編排和調度
* Systems Tracing Analysis：對於 Tracing 來說，基本上都是參考於 [Google Dapper](https://research.google/pubs/pub36356/) 這篇論文，目前有很多的實現，最嚴格的實現是 [Zipkin](https://zipkin.io/)。Zipkin 貼近 Google Dapper 論文的好處在於 --- Stateless，快速地把 Span 發出來，不消耗應用程式的 Memory 和 CPU。這意味著，監控系統寧可自己死了也不能干擾實際應用。
* 軟體升級：發現很多公司包括 BAT，他們完全沒有軟體升級的活動，全靠開發人員自發。然而，這種成體系的活動，是永遠不可能靠大眾的自發形成的。一個公司至少一年要有一次軟體版本升級的 review，然後形成軟體版本的統一和一致，這樣會極大簡化系統架構的複雜度。

### 原則六：重視架構擴展性和可維運性

這邊我認同系統設計上的擴展性和可維運性很重要，因為系統會是慢慢擴展的，沒有一定的彈性會在未來很麻煩。但其實也是要考量，當下的情境，像是過度設計就會是個問題。保有擴展性但不要過度設計。

擴展性：要求有標準規範且不耦合的業務架構
可維運性：要求的是可控制能力

* 透過服務編排架構來降低服務間的耦合：例如像 Workflow、Event Driven Architecture、Broker、Gateway、Service Discovery 等類型的 Middleware 來降低服務間的相依性
* 透過 Service Discovery 或 Gateway 來降低服務相依所帶來的維運複雜度：像是 [SOLID](https://coolshell.cn/articles/4535.html) 的原則、IoC/DIP、SOA 或 Spring Cloud 等架構的[最佳實踐](https://coolshell.cn/articles/5701.html)、分散式系統架構的相關實踐[1](https://coolshell.cn/articles/10910.html)[2](https://docs.microsoft.com/en-us/azure/architecture/patterns/)

### 原則七：對控制邏輯進行全面管理

程式會有兩種邏輯：業務邏輯、控制邏輯。通常控制邏輯的門檻比業務邏輯高很多。

### 原則八：不要遷就老舊系統的技術債務

這邊很喜歡作者的一段話：
> 來找我尋求技術幫助的人都有各種各樣的問題。我都會對他們苦口婆心地說同樣的一句話——“如果你是來找我 case-by-case 解決問題，我興趣不大，因為，你們千萬不要寄希望能夠很簡單的把一輛夏利車改成一輛法拉利跑車，或是把一棟地基沒打好的歪樓搞正。以前欠下的技術債，都得要還，沒打好的地基要重新打，沒建配套設施都要建。這些基礎設施如果不按照正確科學的方式建立的話，你是不可能有一個好的的系統，我也沒辦法幫你 case-by-case 的解決問題……”，一開始，他們都會對我說，沒問題，我們就是要還債，但是，最後發現要還的債真多，有點承受不了，就開始現原形了。

* 與其花大力氣遷就技術債，不如直接還技術債。是所謂的長痛不如短痛。
* 建設沒有技術債的“新城區”，並通過“防腐層 ”的架構模型，不要讓技術債侵入“新城區”。

### 原則九：不要依賴自己的經驗，要依賴於資料和學習

做技術決定時，不要依賴自己的經驗，可以先花時間去研究相關的資料、文件、論文和比較後再做決定。
(謎之聲：有時候有可能連搜集資料的功能都是錯誤的

### 原則十：千萬要小心 X – Y 問題，要追問原始需求

[x-y問題](https://coolshell.cn/articles/10804.html)。客戶永遠不知道自己要的是什麼，結語。

### 原則十一：激進勝於保守，創新與實用並不衝突

進步永遠來自於探索，探索是要付出代價的，但是收益更大
