.NET Core實戰項目之CMS 第九章 設計篇-白話架構設計

前面兩篇文章給你們介紹了咱們實戰的CMS系統的數據庫設計,源碼也已經上傳到服務器上了。今天咱們就好聊聊架構設計,在開始以前先給你們分享一下這幾天我一直在聽的《從零開始學架構》裏面關於架構設計的定義以及架構設計的三大原則,但願能對你們有所啓發。有着這些基礎以後,咱們再基於此搭建咱們的項目框架吧!若是你在閱讀的過程當中有任何的問題,歡迎你們在留言區進行留言,或者加入.NET Core實戰項目羣637326624跟大夥一塊兒交流經驗。html

本文已收錄至《.NET Core實戰項目之CMS 第一章 入門篇-開篇及整體規劃程序員

做者:依樂祝算法

原文地址:http://www.javashuo.com/article/p-bbnomwrg-ca.html數據庫

寫在前面

程序員的成長繞不開架構設計,有時架構設計就像鴻溝同樣擋在程序的晉升之路上,只要跨過去就能夠海闊天空,但很多技術能力很強的程序員卻依然不能徹底掌握架構設計,包括我本身在內,在實踐過程當中常常把握不住重點、分不清主次;或者說沒有完全掌握架構設計的原則,在設計上猶豫不定。本文是我在觀看了李運華老師從零開始學架構後的一些見解,文章最後會給出如何查看原做的方法。文章大部份內容也都是摘錄自李運華的文章,固然,中間穿插了不少本身的認識在裏面。目的就是給你們分享一下架構方面的知識,但願本篇的內容分享能對你有所啓發!編程

架構的定義

對於技術人員來講,「架構」是一個再常見不過的詞了。咱們會對新員工培訓整個系統的架構,參加架構設計評審,學習業界開源系統(例如,MySQL、Hadoop)的架構,研究大公司的架構實現(例如,微信架構、淘寶架構)……雖然「架構」這個詞常見,但若是深究一下「架構」到底指什麼呢?相信大部分人也許並不必定可以準確地回答。例如:安全

  • 架構和框架是什麼關係?有什麼區別?
  • Windows有架構,SQL Server 有架構,.NET Core也有架構,使用 .NET Core開發、SQL Server 存儲、跑在 Windows 上的業務系統也有架構,那麼咱們應該關注哪一個架構呢?
  • 微信有架構,微信的登陸系統也有架構,微信的支付系統也有架構,當咱們談微信架構時,究竟是在談什麼架構?

要想準確地回答這幾個問題,關鍵在於梳理幾個有關係而又類似的概念,包括:系統與子系統、模塊與組件、框架與架構。服務器

系統與子系統

咱們先來看維基百科定義的「系統」。微信

系統泛指由一羣有關聯的個體組成,根據某種規則運做,能完成個別元件不能單獨完成的工做的羣體。它的意思是「整體」「總體」或「聯盟」。數據結構

關鍵內容提煉:架構

  1. 關聯:系統是由一羣有關聯的個體組成的,沒有關聯的個體堆在一塊兒不能成爲一個系統。例如,把一個發動機和一臺 PC 放在一塊兒不能稱之爲一個系統,把發動機、底盤、輪胎、車架組合起來才能成爲一臺汽車。
  2. 規則:系統內的個體須要按照指定的規則運做,而不是單個個體各自爲政。規則規定了系統內個體分工和協做的方式。例如,汽車發動機負責產生動力,而後經過變速器和傳動軸,將動力輸出到車輪上,從而驅動汽車前進。
  3. 能力:系統能力與個體能力有本質的差異,系統能力不是個體能力之和,而是產生了新的能力。例如,汽車可以載重前進,而發動機、變速器、傳動軸、車輪自己都不具有這樣的能力。

維基百科定義的「子系統」

子系統也是由一羣有關聯的個體所組成的系統,多半會是更大系統中的一部分。

其實子系統的定義和系統定義是同樣的,只是觀察的角度有差別,一個系統多是另一個更大系統的子系統。

按照這個定義,系統和子系統比較容易理解。咱們以微信爲例來作一個分析。

  1. 微信自己是一個系統,包含聊天、登陸、支付、朋友圈等子系統。
  2. 朋友圈這個系統又包括動態、評論、點贊等子系統。
  3. 評論這個系統可能又包括防刷子系統、審覈子系統、發佈子系統、存儲子系統。
  4. 評論審覈子系統再也不包含業務意義上的子系統,而是包括各個模塊或者組件,這些模塊或者組件自己也是另一個維度上的系統。例如,MySQL、Redis 等是存儲系統,但不是業務子系統。

模塊與組件

模塊和組件兩個概念在實際工做中很容易混淆,咱們常常可以聽到相似這樣的說法:

  • MySQL 模塊主要負責存儲數據,而 ElasticSearch模塊主要負責數據搜索。
  • 咱們有安全加密組件、有審覈組件
  • App 的下載模塊使用了第三方的組件

形成這種現象的主要緣由是,模塊與組件的定義並很差理解,也不能很好地進行區分。

二者在維基百科上的定義:

軟件模塊(Module)是一套一致而互相有緊密關連的軟件組織。它分別包含了程序和數據結構兩部分。現代軟件開發每每利用模塊做爲合成的單位。模塊的接口表達了由該模塊提供的功能和調用它時所需的元素。模塊是可能分開被編寫的單位。這使它們可再用和容許人員同時協做、編寫及研究不一樣的模塊。
軟件組件定義爲自包含的、可編程的、可重用的、與語言無關的軟件單元,軟件組件能夠很容易被用於組裝應用程序中。

從邏輯的角度來拆分系統後,獲得的單元就是「模塊」;從物理的角度來拆分系統後,獲得的單元就是「組件」。劃分模塊的主要目的是職責分離;劃分組件的主要目的是單元複用。其實,「組件」的英文 component 也可翻譯成中文的「零件」一詞,「零件」更容易理解一些,「零件」是一個物理的概念,而且具有「獨立且可替換」的特色。

框架與架構

框架是和架構比較類似的概念,且二者有較強的關聯關係,因此在實際工做中,這兩個概念有時咱們容易分不清楚。

框架與架構的區別:

軟件框架(Software Framework)一般指的是爲了實現某個業界標準或完成特定基本任務的軟件組件規範,也指爲了實現某個軟件組件規範時,提供規範所要求之基礎功能的軟件產品。

關鍵部分提煉:

  1. 框架是組件規範:例如,MVC 就是一種最多見的開發規範
  2. 框架提供基礎功能的產品:例如,WebApi 是 MVC 的開發框架,除了知足 MVC 的規範,.NET Core WebApi 提供了不少基礎功能來幫助咱們實現功能,包括Http請求,過濾器([HttpGet])等不少基礎功能。

軟件架構指軟件系統的「基礎結構」,創造這些基礎結構的準則,以及對這些結構的描述。

單純從定義的角度來看,框架和架構的區別仍是比較明顯的,框架關注的是「規範」,架構關注的是「結構」。框架的英文是 Framework[ˈfreɪmwɜ:rk],架構的英文是 Architecture[ˈɑ:rkɪtektʃə(r)]。EF 的英文文檔標題就是「Entity framework」。

從新定義架構

參考維基百科的定義,架構從新定義爲:軟件架構指軟件系統的頂層結構。

首先,「系統是一羣關聯個體組成」,這些「個體」能夠是「子系統」「模塊」「組件」等;架構須要明確系統包含哪些「個體」。

其次,系統中的個體須要「根據某種規則」運做,架構須要明確個體運做和協做的規則。

第三,維基百科定義的架構用到了「基礎結構」這個說法,我改成「頂層結構」,能夠更好地區分系統和子系統,避免將系統架構和子系統架構混淆在一塊兒致使架構層次混亂。

總結提煉上述概念

  • 架構是頂層設計;
  • 框架是面向編程或配置的半成品;
  • 組件是從技術維度上的複用;
  • 模塊是從業務維度上職責的劃分;
  • 系統是相互協同可運行的實體。

架構設計三原則

合適原則、簡單原則、演化原則,架構設計時遵循這幾個原則,有助於作出最好的選擇。

合適原則

合適原則宣言:「合適優於業界領先」。

優秀的技術人員都有很強的技術情結,當他們作方案或者架構時,總想不斷地挑戰本身,想達到甚至優於業界領先水平是其中一個典型表現,由於這樣纔可以展示本身的優秀,才能在年終 KPI 績效總結裏面驕傲地寫上「設計了 XX 方案,達到了和 Google 相同的技術水平」「XX 方案的性能測試結果大大優於阿里集團的 YY 方案」。
但現實是,大部分這樣想和這樣作的架構,最後可能都以失敗了結!
爲何會這樣呢?

再好的夢想,也須要腳踏實地實現!這裏的「腳踏實地」主要體如今下面幾個方面。

  1. 將軍難打無兵之仗

大公司的分工比較細,一個小系統可能就是一個小組負責,好比說某個通訊大廠,作一個 OM 管理系統就有十幾我的,阿里的中間件團隊有幾十我的,而大部分公司,整個研發團隊可能就 100 多人,某個業務團隊可能就十幾我的。十幾我的的團隊,想作幾十我的的團隊的事情,並且還要作得更好,不能說絕對不可能,但難度是可想而知的。

沒那麼多人,卻想幹那麼多活,是失敗的第一個主要緣由。

  1. 羅馬不是一天建成的

業界領先的不少方案,其實並非一堆天才某個時期靈機一動,而後加班加點就作出來的,而是通過幾年時間的發展才逐步完善和初具規模的。阿里中間件團隊 2008 年成立,發展到如今已經有十年了。咱們只知道他們抗住了多少次「雙 11」,作了多少優秀的系統,但經歷了什麼樣的挑戰、踩了什麼樣的坑,只有他們本身知道!這些挑戰和踩坑,都是架構設計很是關鍵的促進因素,單純靠拍腦殼或者頭腦風暴,是不可能和真正實戰相比的。

沒有那麼多積累,卻想一步登天,是失敗的第二個主要緣由。

  1. 冰山下面纔是關鍵

可能有人認爲,業界領先的方案都是天才創造出來的,因此本身也要造一個業界領先的方案,以此來證實本身也是天才。確實有這樣的天才,但更多的時候,業界領先的方案其實都是「逼」出來的!簡單來講,「業務」發展到必定階段,量變致使了質變,出現了新的問題,已有的方式已經不能應對這些問題,須要用一種新的方案來解決,經過創新和嘗試,纔有了業界領先的方案。GFS 爲什麼在 Google 誕生,而不是在 Microsoft 誕生?我認爲 Google 有那麼龐大的數據是一個主要的因素,而不是由於 Google 的工程師比 Microsoft 的工程師更加聰明。

沒有那麼卓越的業務場景,卻幻想靈光一閃成爲天才,是失敗的第三個主要緣由。

因此,真正優秀的架構都是在企業當前人力、條件、業務等各類約束下設計出來的,可以合理地將資源整合在一塊兒併發揮出最大功效,而且可以快速落地。這也是不少 BAT 出來的架構師到了小公司或者創業團隊反而作不出成績的緣由,由於沒有了大公司的平臺、資源、積累,只是生搬硬套大公司的作法,失敗的機率很是高。

簡單原則

簡單原則宣言:「簡單優於複雜」。

軟件架構設計是一門技術活。所謂技術活,從歷史上看,不管是瑞士的鐘表,仍是瓦特的蒸汽機;不管是萊特兄弟發明的飛機,仍是摩托羅拉發明的手機,無一不是愈來愈精細、愈來愈複雜。所以當咱們進行架構設計時,會天然而然地想把架構作精美、作複雜,這樣才能體現咱們的技術實力,也纔可以將架構作成一件藝術品。

因爲軟件架構和建築架構表面上的類似性,咱們也會潛意識地將對建築的審美觀點移植到軟件架構上面。咱們驚歎於長城的宏偉、泰姬陵的精美、悉尼歌劇院的藝術感、迪拜帆船酒店的豪華感,所以,對於咱們本身親手打造的軟件架構,咱們也但願它宏偉、精美、藝術、豪華……總之就是不能寒酸、不能簡單。

團隊的壓力有時也會有意無心地促進咱們走向複雜的方向,由於大部分人在評價一個方案水平高低的時候,複雜性是其中一個重要的參考指標。例如設計一個主備方案,若是你用心跳來實現,可能你們都認爲這太簡單了。但若是你引入 ZooKeeper 來作主備決策,可能不少人會認爲這個方案更加「高大上」一些,畢竟 ZooKeeper 使用的是 ZAB 協議,而 ZAB 協議自己就很複雜。其實,真正理解 ZAB 協議的人不多(我也不懂),但並不妨礙咱們都知道 ZAB 協議很優秀。

剛纔我聊的這些緣由,會在潛意識層面促使初出茅廬的架構師,不自覺地追求架構的複雜性。然而,「複雜」在製造領域表明先進,在建築領域表明領先,但在軟件領域,卻偏偏相反,表明的是「問題」。

軟件領域的複雜性體如今兩個方面:

  1. 結構的複雜性

結構複雜的系統幾乎毫無例外具有兩個特色:

  • 組成複雜系統的組件數量更多;
  • 同時這些組件之間的關係也更加複雜。

結構上的複雜性存在的第一個問題是,組件越多,就越有可能其中某個組件出現故障,從而致使系統故障。這個機率能夠算出來,假設組件的故障率是 10%(有 10% 的時間不可用),那麼有 3 個組件的系統可用性是(1-10%)×(1-10%)×(1-10%)= 72.9%,有 5 個組件的系統可用性是(1-10%)×(1-10%)×(1-10%)×(1-10%)×(1-10%)=59%,二者的可用性相差 13%。

結構上的複雜性存在的第二個問題是,某個組件改動,會影響關聯的全部組件,這些被影響的組件一樣會繼續遞歸影響更多的組件。這個問題會影響整個系統的開發效率,由於一旦變動涉及外部系統,須要協調各方統一進行方案評估、資源協調、上線配合。

結構上的複雜性存在的第三個問題是,定位一個複雜系統中的問題老是比簡單系統更加困難。首先是組件多,每一個組件都有嫌疑,所以要逐一排查;其次組件間的關係複雜,有可能表現故障的組件並非真正問題的根源。

  1. 邏輯的複雜性

意識到結構的複雜性後,咱們的第一反應可能就是「下降組件數量」,畢竟組件數量越少,系統結構越簡。最簡單的結構固然就是整個系統只有一個組件,即系統自己,全部的功能和邏輯都在這一個組件中實現。

不幸的是,這樣作是行不通的,緣由在於除告終構的複雜性,還有邏輯的複雜性,即若是某個組件的邏輯太複雜,同樣會帶來各類問題。

邏輯複雜的組件,一個典型特徵就是單個組件承擔了太多的功能。以電商業務爲例,常見的功能有:商品管理、商品搜索、商品展現、訂單管理、用戶管理、支付、發貨、客服……把這些功能所有在一個組件中實現,就是典型的邏輯複雜性。

邏輯複雜幾乎會致使軟件工程的每一個環節都有問題,假設如今淘寶將這些功能所有在單一的組件中實現,能夠想象一下這個恐怖的場景:

  • 系統會很龐大,多是上百萬、上千萬的代碼規模,「clone」一次代碼要 30 分鐘。
  • 幾10、上百人維護這一套代碼,某個「菜鳥」不當心改了一行代碼,致使整站崩潰。
  • 需求像雪片般飛來,爲了應對,開幾十個代碼分支,而後各類分支合併、各類分支覆蓋。
  • 產品、研發、測試、項目管理不停地開會討論版本計劃,協調資源,解決衝突。
  • 版本太多,天天都要上線幾十個版本,系統每隔 1 個小時重啓一次。
  • 線上運行出現故障,幾十我的撲上去定位和處理,一間小黑屋都裝不下全部人,整個辦公區鬧翻天。
  • ……

不用多說,確定誰都沒法忍受這樣的場景。

可是,爲何複雜的電路就意味更強大的功能,而複雜的架構卻有不少問題呢?根本緣由在於電路一旦設計好後進入生產,就不會再變,複雜性只是在設計時帶來影響;而一個軟件系統在投入使用後,後續還有源源不斷的需求要實現,所以要不斷地修改系統,複雜性在整個系統生命週期中都有很大影響。

功能複雜的組件,另一個典型特徵就是採用了複雜的算法。複雜算法致使的問題主要是難以理解,進而致使難以實現、難以修改,而且出了問題難以快速解決。

以 ZooKeeper 爲例,ZooKeeper 自己的功能主要就是選舉,爲了實現分佈式下的選舉,採用了 ZAB 協議,因此 ZooKeeper 功能雖然相對簡單,但系統實現卻比較複雜。相比之下,etcd 就要簡單一些,由於 etcd 採用的是 Raft 算法,相比 ZAB 協議,Raft 算法更加容易理解,更加容易實現。

綜合前面的分析,咱們能夠看到,不管是結構的複雜性,仍是邏輯的複雜性,都會存在各類問題,因此架構設計時若是簡單的方案和複雜的方案均可以知足需求,最好選擇簡單的方案。《UNIX 編程藝術》總結的 KISS(Keep It Simple, Stupid!)原則同樣適應於架構設計。

演化原則

演化原則宣言:「演化優於一步到位」。

軟件架構從字面意思理解和建築結構很是相似,事實上「架構」這個詞就是建築領域的專業名詞,維基百科對「軟件架構」的定義中有一段話描述了這種類似性:

從和目的、主題、材料和結構的聯繫上來講,軟件架構能夠和建築物的架構相比擬。

例如,軟件架構描述的是一個軟件系統的結構,包括各個模塊,以及這些模塊的關係;建築架構描述的是一幢建築的結構,包括各個部件,以及這些部件如何有機地組成成一幢完美的建築。

然而,字面意思上的類似性卻掩蓋了一個本質上的差別:建築一旦完成(甚至一旦開建)就不可再變,而軟件卻須要根據業務的發展不斷地變化!

  • 古埃及的吉薩大金字塔,4000 多年前完成的,到如今仍是當初的架構。
  • 中國的明長城,600 多年前完成的,如今保存下來的長城仍是當年的結構。
  • 美國白宮,1800 年建成,200 年來進行了幾回擴展,但總體結構並沒有變化,只是在旁邊的空地擴建或者改造內部的佈局。

對於建築來講,永恆是主題;而對於軟件來講,變化纔是主題。軟件架構須要根據業務的發展而不斷變化。設計 Windows 和 Android 的人都是頂尖的天才,即使如此,他們也不可能在 1985 年設計出 Windows 8,不可能在 2009 年設計出 Android 6.0。

若是沒有把握「軟件架構須要根據業務發展不斷變化」這個本質,在作架構設計的時候就很容易陷入一個誤區:試圖一步到位設計一個軟件架構,指望無論業務如何變化,架構都穩如磐石。

爲了實現這樣的目標,要麼照搬業界大公司公開發表的方案;要麼投入龐大的資源和時間來作各類各樣的預測、分析、設計。不管哪一種作法,後果都很明顯:投入巨大,落地遙遙無期。更讓人沮喪的是,就算跌跌撞撞拼死拼活終於落地,卻發現不少預測和分析都是不靠譜的。

考慮到軟件架構須要根據業務發展不斷變化這個本質特色,軟件架構設計其實更加相似於大天然「設計」一個生物,經過演化讓生物適應環境,逐步變得更增強大:

  • 首先,生物要適應當時的環境。
  • 其次,生物須要不斷地繁殖,將有利的基因傳遞下去,將不利的基因剔除或者修復。
  • 第三,當環境變化時,生物要可以快速改變以適應環境變化;若是生物沒法調整就被天然淘汰;新的生物會保留一部分原來被淘汰生物的基因。

軟件架構設計一樣是相似的過程:

  • 首先,設計出來的架構要知足當時的業務須要。
  • 其次,架構要不斷地在實際應用過程當中迭代,保留優秀的設計,修復有缺陷的設計,改正錯誤的設計,去掉無用的設計,使得架構逐漸完善。
  • 第三,當業務發生變化時,架構要擴展、重構,甚至重寫;代碼也許會重寫,但有價值的經驗、教訓、邏輯、設計等(相似生物體內的基因)卻能夠在新架構中延續。

架構師在進行架構設計時須要牢記這個原則,時刻提醒本身不要貪大求全,或者盲目照搬大公司的作法。應該認真分析當前業務的特色,明確業務面臨的主要問題,設計合理的架構,快速落地以知足業務須要,而後在運行過程當中不斷完善架構,不斷隨着業務演化架構。

即便是大公司的團隊,在設計一個新系統的架構時,也須要遵循演化的原則,而不該該認爲團隊人員多、資源多,無論什麼系統上來就要一步到位,由於業務的發展和變化是很快的,無論多牛的團隊,也不可能完美預測全部的業務發展和變化路徑。

本節總結

架構即決策。架構須要面向業務需求,並在各類資源(人、財、物、時、事)約束條件下去作權衡、取捨。而決策就會存在不肯定性。採用一些高屋建瓴的設計原則有助於去消除不肯定,去逼近解決問題的最優解。

1 合適原則

架構無優劣,但存合適性。「汝之蜜糖,吾之砒霜」;架構必定要匹配企業所在的業務階段;不要面向簡歷去設計架構,高大上的架構不等於適用;削足適履與打腫充胖都不符合合適原則;所謂合適,必定要匹配業務所處階段,可以合理地將資源整合在一塊兒併發揮出最大功效,並可以快速落地。

2 簡單原則

"我沒有時間寫一封短信,因此只好寫一封長信"。其實,簡單比複雜更加困難。面對系統結構、業務邏輯和複雜性,咱們能夠編寫出複雜的系統,但在軟件領域,複雜表明的是「問題」。架構設計時若是簡單的方案和複雜的方案均可以知足需求,最好選擇簡單的方案。可是,事實上,當軟件系統變得太複雜後,就會有人換一個思路進行重構、升級,將它從新變得簡單,這也是軟件開發的大趨勢。 簡單原則是一個樸素且偉大的原則,Google的MapReduce系統就採用了分而治之的思想,而背後就是將複雜問題轉化爲簡單問題的典型案例。

3 演化原則

大到人類社會、天然生物,小到一個細胞,彷佛都遵循這一普世原則,軟件架構也不例外。業務在發展、技術在創新、外部環境在變化,這一切都是在告誡架構師不要貪大求全,或者盲目照搬大公司的作法。應該認真分析當前業務的特色,明確業務面臨的主要問題,設計合理的架構,快速落地以知足業務須要,而後在運行過程當中不斷完善架構,不斷隨着業務演化架構。懷胎須要十月,早一月或晚一月都很危險。

總結

今天我帶着你們記錄一下李運華老師從零開始學架構的關於架構的概念以及架構的三個原則,但願對您有所啓發!若是你想學習更多關於架構方面的知識也能夠訂閱李老師的課程,文章最後我會給出微信二維碼!好了,下篇咱們就基於這些思想設計最適合咱們實際的.NET Core CMS系統的開發框架吧!
這裏免費給李老師打個廣告,畢竟本篇文章摘錄了不少李老師的內容!
http://gk.link/a/101w9

1544107087000

相關文章
相關標籤/搜索