成為一個(gè)優(yōu)秀架構(gòu)師,你必須了解的30條設(shè)計(jì)原則
眾所周知,架構(gòu)師的角色,更偏向于策劃、而非指揮,塑造、而非支配,其存在的意義,在于引導(dǎo)大家討論、而非自己主宰一切。
但是,具體應(yīng)該如何執(zhí)行呢?本文作者整理了 30 個(gè)公認(rèn)的架構(gòu)原則,來(lái)幫助大家解決此問題。也許有的原則,你從未聽說,但你看完就能快速學(xué)會(huì)。
相信你學(xué)會(huì)了,工作起來(lái)也會(huì)事半功倍,或許還可幫你避免很多無(wú)用的加班!
本文作者叫 Srinath Perera,是一位計(jì)算機(jī)科學(xué)家、軟件架構(gòu)師、作家。他是 Apache 的核心成員,擁有 15 年分布式系統(tǒng)編程經(jīng)驗(yàn),設(shè)計(jì)了 Apache Axis2 以及 WSO2 流處理器。
在 WSO2,我參與架構(gòu)評(píng)審的時(shí)間已長(zhǎng)達(dá)八年之久。WSO2 的產(chǎn)品非常豐富,比如 WSO2 ESB 、WSO2 API Manager 以及 WSO2 SP 都人盡皆知。在過去八年中,我們對(duì)許多產(chǎn)品和功能進(jìn)行了討論、設(shè)計(jì)、改進(jìn)和重新設(shè)計(jì)。
我們?cè)谠O(shè)計(jì)軟件的過程中,把握的一個(gè)關(guān)鍵點(diǎn)是:軟件架構(gòu)并非由架構(gòu)師負(fù)責(zé)設(shè)計(jì)。我們的架構(gòu)不是由架構(gòu)師制定,然后交給其他人來(lái)實(shí)施。
相反,架構(gòu)的設(shè)計(jì)任務(wù)由真正編寫代碼的團(tuán)隊(duì)負(fù)責(zé)。架構(gòu)師負(fù)責(zé)對(duì)工程師設(shè)計(jì)的架構(gòu)進(jìn)行修復(fù)、完善和改進(jìn)。我們的架構(gòu)團(tuán)隊(duì)是指導(dǎo)員和把關(guān)人,而非獨(dú)裁者。
在短期內(nèi),由一位架構(gòu)師來(lái)制定架構(gòu)的確既快捷又實(shí)惠。但是,從長(zhǎng)遠(yuǎn)來(lái)看,我們會(huì)組建一個(gè)團(tuán)隊(duì),讓他們自己不斷思考、改善架構(gòu),并從他們的錯(cuò)誤中來(lái)提升自己。
當(dāng)我們專注于團(tuán)隊(duì)時(shí),他們自然會(huì)隨著時(shí)間的推移而變得更好。架構(gòu)團(tuán)隊(duì)的首要任務(wù)是:盡可能保證架構(gòu)容易執(zhí)行。此外,架構(gòu)評(píng)審也存在缺陷。
就像 Paul (@pzfreo)描述的架構(gòu)評(píng)審那樣:架構(gòu)師參與進(jìn)來(lái),聽一會(huì),發(fā)表一點(diǎn)評(píng)論然后就走了。作為一名架構(gòu)師,你對(duì)架構(gòu)發(fā)表自己的看法和意見無(wú)可厚非。但是,如果你不夠投入和細(xì)心,你的意見可能會(huì)讓團(tuán)隊(duì)感到困惑,團(tuán)隊(duì)就無(wú)法確定正確的做法到底是什么。
接下來(lái)我會(huì)將 30 個(gè)架構(gòu)原則一一列出,其中一些原則是眾所周知的,而有些則源于我的個(gè)人經(jīng)驗(yàn)和心血。
基本原則
- 原則1:KISS (Keep it simple,sutpid) 和保持每件事情都盡可能的簡(jiǎn)單,用最簡(jiǎn)單的解決方案來(lái)解決問題。
- 原則 2:YAGNI(你不需要它)原則 ,只在需要時(shí)構(gòu)建。
- 原則 3:先學(xué)會(huì)爬,然后再學(xué)會(huì)走,最后學(xué)會(huì)跑。換句話說,先保證能夠正常運(yùn)行,然后優(yōu)化它使其更好,最后逐漸讓它變得完美。使用迭代開發(fā),采用敏捷開發(fā)模式。為每個(gè)功能制定一個(gè)開發(fā)周期(最多 2 周),然后不斷迭代。
- 原則 4:自動(dòng)化測(cè)試是構(gòu)建穩(wěn)定、高質(zhì)量產(chǎn)品的唯一方法。通過自動(dòng)化測(cè)試提升創(chuàng)造力,所有一切都可以自動(dòng)化!在設(shè)計(jì)時(shí)應(yīng)當(dāng)好好考慮自動(dòng)化。
- 原則 5:注重投資回報(bào)率(ROI)并將最多的注意力放在最重要的地方。
- 原則 6:了解用戶并相應(yīng)地平衡資源。大多數(shù)產(chǎn)品都有數(shù)千個(gè)最終用戶,大致需要 20 個(gè)開發(fā)人員和 100 個(gè) DevOps 人員。不要花費(fèi)數(shù)月的時(shí)間來(lái)構(gòu)建一個(gè)不太可能使用 DevOps 的用戶界面(他們更喜歡腳本)。這是原則 5 的特例。
- 原則 7:功能的設(shè)計(jì)和測(cè)試盡可能獨(dú)立。如果在設(shè)計(jì)時(shí)考慮到這一點(diǎn),長(zhǎng)遠(yuǎn)來(lái)看,它將省去很多麻煩,否則只有一切構(gòu)建完成時(shí)你才可以開始測(cè)試整個(gè)系統(tǒng)。此外,遵循這個(gè)原則,版本發(fā)布也會(huì)更加順利。
- 原則 8:警惕搜索引擎中花里胡哨的架構(gòu)方案。我們天生都喜歡令人奪目的設(shè)計(jì)。如果你按捺不住, 就可能把太多根本不需要的功能和解決方案引入到你的架構(gòu)中。
功能選擇
- 原則 9:想要準(zhǔn)確知道用戶如何使用我們的產(chǎn)品是很難的。所以我們要推行 MVP(最小可行產(chǎn)品)。該理念的核心在于:先制定一些用例,完成用例所涉及的相關(guān)功能,立即發(fā)布產(chǎn)品,然后根據(jù)反饋和經(jīng)驗(yàn)對(duì)產(chǎn)品進(jìn)行優(yōu)化。
- 原則 10:盡可能減少功能,如有疑問則將其刪除。許多功能可能從未使用,你只需為其留一個(gè)擴(kuò)展接口即可。
- 原則 11:聽取客戶的意見,看他們想要什么功能。
- 原則 12:當(dāng)客戶要求的功能影響到其他模塊時(shí),要勇于和客戶辯論。從大局出發(fā),嘗試找到另一種方法來(lái)處理問題。就像 Fords 所說的那樣“每當(dāng)我問顧客需要什么的時(shí)候,他們總是會(huì)說需要跑得更快的馬”。請(qǐng)記住,你才是專家。你應(yīng)該主導(dǎo)一切,做出正確和專業(yè)的決定。雖然用戶可能當(dāng)時(shí)有些疑惑,但最終他們會(huì)感謝你的。
服務(wù)端設(shè)計(jì)和并發(fā)
- 原則 13:要知道一個(gè) Server 是如何運(yùn)行的,從硬件到操作系統(tǒng),直到編程語(yǔ)言。優(yōu)化 IO 調(diào)用的數(shù)量是你通往較好架構(gòu)的首選之路。
- 原則 14:遵循 Amdhal 的同步定律。線程之間共享的可變數(shù)據(jù)會(huì)降低程序速度。如果可以,請(qǐng)使用并發(fā)數(shù)據(jù)結(jié)構(gòu),并且僅在必要時(shí)使用同步。盡可能少地使用鎖。如果你打算在線程鎖期間阻塞,請(qǐng)確保自己足夠了解具體細(xì)節(jié),因?yàn)檫@里存在極大的隱患。
- 原則 15:如果你的設(shè)計(jì)是基于事件驅(qū)動(dòng)的非阻塞架構(gòu),那就不要阻塞線程或者在線程中執(zhí)行 IO 操作。一旦這樣做,系統(tǒng)將慢如蝸牛。
分布式系統(tǒng)
- 原則 16:無(wú)狀態(tài)系統(tǒng)具有良好的擴(kuò)展性。我們要盡可能了解和使用無(wú)分享架構(gòu)。
- 原則 17:除非你能夠掌控客戶端和服務(wù)器的所有代碼,否則消息傳遞失敗的情況在所難免。盡量減少你的系統(tǒng)依賴的因素(例如使用原則 18 )。
- 原則 18:盡可能實(shí)施冪等操作。這樣它就很容易恢復(fù),你至少可以保證交付沒問題。
- 原則 19:了解 CAP 定理??蓴U(kuò)展的事務(wù)(分布式事務(wù))是很難的 。盡可能使用補(bǔ)償,基于 RDBMS 的事務(wù)很難擴(kuò)展。
- 原則 20:分布式系統(tǒng)共識(shí)不支持?jǐn)U展,也無(wú)法進(jìn)行組通信,不支持群集范圍內(nèi)的可靠消息傳遞。其最大節(jié)點(diǎn)限制大約是八個(gè)節(jié)點(diǎn)。
- 原則 21:在分布式系統(tǒng)中,你很難隱藏分布式系統(tǒng)中的延遲和故障。(參見分布式計(jì)算的謬誤解釋 )。
用戶體驗(yàn)
- 原則 22:了解你的用戶以及他們的目標(biāo):他是新手、專家還是臨時(shí)用戶?他對(duì)計(jì)算機(jī)科學(xué)了解多少?極客看重?cái)U(kuò)展功能,開發(fā)人員關(guān)注示例和腳本,普通人則更在乎界面。
- 原則 23:好的產(chǎn)品應(yīng)當(dāng)不需要用戶手冊(cè),用戶應(yīng)該一看就會(huì)用。
- 原則 24:當(dāng)你無(wú)法在兩個(gè)選項(xiàng)之間做出決定時(shí),請(qǐng)不要通過配置選項(xiàng)的方式來(lái)呈現(xiàn)問題。這會(huì)給用戶和架構(gòu)師帶來(lái)麻煩。對(duì)于系統(tǒng)如何運(yùn)作的細(xì)節(jié),他們沒有你了解,他們?cè)趺茨茏龀鰶Q定呢?比較好的方案是找到一個(gè)每次都有效的選擇;其次是自動(dòng)做出選擇;第三個(gè)方案是添加配置參數(shù)并設(shè)置合理的默認(rèn)值。
- 原則 25:始終具有合理的配置默認(rèn)值。
- 原則 26:設(shè)計(jì)不良的配置會(huì)制造麻煩,始終配置幾個(gè)示例值。
- 原則 27:詢問用戶配置值的時(shí)候,注意選擇用戶無(wú)需即可設(shè)置的值(例如,不要問用戶需要的最大緩存條目數(shù)量,而是要問他想要用于緩存的內(nèi)存數(shù)量)
- 原則 28:如果發(fā)現(xiàn)未知配置,則拋出錯(cuò)誤。永遠(yuǎn)不要忽視它。在調(diào)試過程中,無(wú)提示的配置錯(cuò)誤會(huì)浪費(fèi)我們很多調(diào)試時(shí)間。
難點(diǎn)
- 原則 29:嘗試新語(yǔ)言很容易,但要正確使用卻很難。除非公司愿意組建一個(gè)十人團(tuán)隊(duì)并花一年的時(shí)間來(lái)學(xué)習(xí),否則盡量不要這樣做。如果你仍不死心,請(qǐng)閱讀有關(guān)語(yǔ)言設(shè)計(jì)的五個(gè)問題后再做定奪。
- 原則 30:可組合的拖放 UI 很難實(shí)現(xiàn),除非團(tuán)隊(duì)準(zhǔn)備投入 10 人/年的資源,否則不要去做。
最后,談一下我的感受。在理想情況下,一個(gè)平臺(tái)應(yīng)當(dāng)由多個(gè)正交組件組成,每個(gè)組件負(fù)責(zé)一個(gè)方面(例如,安全性、消息傳遞、注冊(cè)、調(diào)解、分析,等等)。使用這些功能構(gòu)建的系統(tǒng)將是很好的。
不幸的是,現(xiàn)實(shí)中我們很難達(dá)到這樣的狀態(tài)。因?yàn)樵陧?xiàng)目初始狀態(tài)時(shí),很多事情是不確定的,你無(wú)法做到這樣的獨(dú)立性,現(xiàn)在我認(rèn)為在開始的時(shí)候適當(dāng)?shù)闹貜?fù)是必要的,當(dāng)你嘗試鏟除他們的時(shí)候,你會(huì)發(fā)現(xiàn)引入了新的復(fù)雜性,分布本身就意味著復(fù)雜。有時(shí)候治愈的過程要比疾病本身更加的糟糕。
總結(jié)
作為一個(gè)架構(gòu)師,我們應(yīng)該像園丁一樣思考、塑造、策劃和去除雜草而不是定義和構(gòu)建。雖然在短期內(nèi),由一位架構(gòu)師來(lái)制定架構(gòu)的確既快捷又實(shí)惠。但是,從長(zhǎng)遠(yuǎn)來(lái)看,團(tuán)隊(duì)的力量才是強(qiáng)大的。
如果你不夠投入和細(xì)心,你只指出錯(cuò)誤,但是不道明錯(cuò)誤原因,那么你的意見可能會(huì)讓團(tuán)隊(duì)感到困惑。避免這種情況的一種方法是擁有一套普遍接受的原則,這些原則是討論架構(gòu)時(shí)遵循的基本點(diǎn),也是初學(xué)者學(xué)習(xí)架構(gòu)的好資源。所以想成為一名優(yōu)秀的架構(gòu)師,還是需要長(zhǎng)期的磨練以及時(shí)間的驗(yàn)證,當(dāng)然隨時(shí)保持學(xué)習(xí)的狀態(tài)也是非常重要的。當(dāng)你學(xué)會(huì)更多知識(shí),你便會(huì)更清晰的解決各種復(fù)雜的架構(gòu)問題。