為什么架構(gòu)師都在偷偷練系統(tǒng)思維?
兄弟們,有沒有發(fā)現(xiàn)那些在技術(shù)圈里叱咤風(fēng)云的頂級架構(gòu)師,一個個都跟開了掛似的,總能把復(fù)雜的系統(tǒng)玩得團團轉(zhuǎn)?他們設(shè)計的系統(tǒng),不僅穩(wěn)定可靠,還能輕松應(yīng)對各種變化。難道他們有什么秘密武器?嘿嘿,別猜了,今天咱就來揭秘一個他們偷偷修煉的 "武功秘籍"—— 系統(tǒng)思維。
一、啥是系統(tǒng)思維?先從生活說起
您先別急著聽技術(shù),咱先從生活里的例子說起,這樣更容易懂。比如說,您要裝修一套房子。如果您沒有系統(tǒng)思維,可能就會這兒想裝個豪華的吊燈,那兒想弄個漂亮的背景墻,結(jié)果裝完了發(fā)現(xiàn),電路走得亂七八糟,空間利用也不合理,住起來那叫一個別扭。但如果您有系統(tǒng)思維,就會先考慮整個房子的布局,水電怎么走,家具怎么擺放,風(fēng)格怎么統(tǒng)一,甚至還要考慮以后的生活需求變化。這就是系統(tǒng)思維,說白了,就是把一個東西看成一個整體,考慮它各個部分之間的關(guān)系,以及它和外部環(huán)境的關(guān)系。
放到咱們的技術(shù)世界里,一個軟件系統(tǒng)就好比一套房子,它由無數(shù)個模塊、組件、接口等等組成。系統(tǒng)思維就是讓咱們從整體的角度去看待這個系統(tǒng),理解各個部分是怎么相互作用的,怎么和外部的環(huán)境(比如用戶、其他系統(tǒng))交互的,還要考慮這個系統(tǒng)未來的發(fā)展和變化。
二、系統(tǒng)思維為啥這么重要?看看這些坑就知道了
(一)避免 "頭疼醫(yī)頭,腳疼醫(yī)腳" 的尷尬
咱舉個簡單的例子。假設(shè)您負責(zé)一個 Java 開發(fā)的電商系統(tǒng),某天用戶反饋下單的時候特別慢。沒系統(tǒng)思維的人,可能直接就去優(yōu)化下單模塊的代碼,一頓操作猛如虎,結(jié)果發(fā)現(xiàn)效果不明顯,甚至還影響了其他功能。為啥呢?因為下單慢可能不僅僅是下單模塊的問題,可能是數(shù)據(jù)庫查詢太慢,可能是網(wǎng)絡(luò)傳輸有延遲,也可能是其他模塊在下單的時候做了一些不必要的操作,占用了資源。
而有系統(tǒng)思維的架構(gòu)師,就會先從整個系統(tǒng)的角度去分析。他們會查看下單的整個流程,看看各個環(huán)節(jié)是怎么交互的,有沒有瓶頸。比如,下單需要調(diào)用庫存系統(tǒng)查詢庫存,調(diào)用支付系統(tǒng)準(zhǔn)備支付,可能還需要記錄日志、發(fā)送消息等等。通過分析整個流程,他們可能會發(fā)現(xiàn),是庫存系統(tǒng)的接口響應(yīng)太慢,導(dǎo)致下單模塊被阻塞。這時候,他們就會從系統(tǒng)的層面去解決問題,比如給庫存系統(tǒng)的接口加緩存,或者優(yōu)化庫存系統(tǒng)的數(shù)據(jù)庫查詢,而不是只盯著下單模塊。
(二)應(yīng)對復(fù)雜系統(tǒng)的 "神器"
現(xiàn)在的軟件系統(tǒng)越來越復(fù)雜,尤其是互聯(lián)網(wǎng)公司的系統(tǒng),動不動就是分布式、微服務(wù)、海量數(shù)據(jù)。就說一個簡單的電商系統(tǒng)吧,可能有用戶中心、商品中心、訂單中心、支付中心、物流中心等等多個微服務(wù),每個微服務(wù)又可能有多個實例,部署在不同的服務(wù)器上,還要和第三方的支付平臺、物流平臺交互。
在這樣復(fù)雜的系統(tǒng)里,如果沒有系統(tǒng)思維,就好比在一個巨大的迷宮里瞎轉(zhuǎn),根本找不到方向。而系統(tǒng)思維能讓咱們看清整個系統(tǒng)的架構(gòu),理解各個微服務(wù)之間的調(diào)用關(guān)系,知道數(shù)據(jù)是怎么流動的,明白每個組件在系統(tǒng)中扮演的角色。這樣,當(dāng)系統(tǒng)出現(xiàn)問題的時候,咱們就能快速定位到根源;當(dāng)需要擴展系統(tǒng)的時候,咱們就能知道從哪里入手,怎么設(shè)計才能保證系統(tǒng)的穩(wěn)定性和可擴展性。
(三)讓技術(shù)方案更 "接地氣"
很多時候,咱們做技術(shù)的容易陷入一個誤區(qū),就是只關(guān)注技術(shù)本身,而忽略了業(yè)務(wù)需求和實際場景。比如,有的開發(fā)者為了追求技術(shù)的 "高大上",在一個簡單的業(yè)務(wù)場景下,非要用復(fù)雜的分布式架構(gòu),結(jié)果導(dǎo)致系統(tǒng)維護成本極高,還經(jīng)常出問題。
系統(tǒng)思維能讓咱們把技術(shù)和業(yè)務(wù)結(jié)合起來,從業(yè)務(wù)的角度去考慮技術(shù)方案。咱們會想,這個技術(shù)方案能不能滿足業(yè)務(wù)的需求,能不能適應(yīng)業(yè)務(wù)的變化,投入產(chǎn)出比是否合理。比如,在設(shè)計一個數(shù)據(jù)存儲方案的時候,有系統(tǒng)思維的架構(gòu)師會考慮業(yè)務(wù)的數(shù)據(jù)量、訪問頻率、一致性要求等等,然后選擇合適的數(shù)據(jù)庫(是用 MySQL、Redis,還是 MongoDB),而不是盲目地追求最新最酷的技術(shù)。
三、系統(tǒng)思維的核心要素:玩轉(zhuǎn)系統(tǒng)的 "金鑰匙"
(一)整體性:把系統(tǒng)看成一個有機的整體
這是系統(tǒng)思維的核心。一個系統(tǒng)不是各個部分的簡單相加,而是各個部分相互作用、相互依賴形成的一個有機整體。就像咱們的身體,各個器官只有協(xié)調(diào)工作,才能讓身體正常運轉(zhuǎn)。
在軟件系統(tǒng)中,整體性體現(xiàn)在很多方面。比如,架構(gòu)設(shè)計的時候,要考慮各個模塊之間的協(xié)作,不能讓某個模塊過于強大,導(dǎo)致其他模塊依賴過深;在代碼設(shè)計的時候,要考慮代碼的可維護性和可擴展性,不能只關(guān)注當(dāng)前的功能實現(xiàn),而忽略了未來的變化。
舉個 Java 開發(fā)的例子,假設(shè)咱們有一個用戶服務(wù)模塊,里面包含了用戶的注冊、登錄、信息修改等功能。如果沒有整體性思維,可能會把這些功能都寫在一個巨大的類里,代碼變得非常臃腫。而有整體性思維的開發(fā)者,會把用戶服務(wù)拆分成不同的類,比如用戶注冊類、用戶登錄類、用戶信息管理類,每個類負責(zé)不同的功能,通過接口來交互,這樣整個模塊就更加清晰、易維護。
(二)關(guān)聯(lián)性:看清各個部分之間的關(guān)系
系統(tǒng)中的各個部分不是孤立存在的,而是相互關(guān)聯(lián)的。這種關(guān)聯(lián)可能是數(shù)據(jù)的傳遞,可能是功能的依賴,也可能是資源的共享。
在分布式系統(tǒng)中,關(guān)聯(lián)性體現(xiàn)得尤為明顯。比如,微服務(wù)之間通過 API 進行調(diào)用,一個微服務(wù)的故障可能會影響到多個其他微服務(wù)。這時候,咱們就需要考慮如何設(shè)計容錯機制,比如重試、熔斷、降級等,來保證系統(tǒng)的穩(wěn)定性。
再比如,在數(shù)據(jù)庫設(shè)計中,表與表之間通過外鍵關(guān)聯(lián),形成一個關(guān)系型數(shù)據(jù)庫。如果咱們不考慮表之間的關(guān)聯(lián)性,隨意設(shè)計表結(jié)構(gòu),可能會導(dǎo)致數(shù)據(jù)冗余、查詢效率低下等問題。而有系統(tǒng)思維的設(shè)計師,會根據(jù)業(yè)務(wù)需求,合理設(shè)計表之間的關(guān)系,確保數(shù)據(jù)的一致性和完整性。
(三)層次性:給系統(tǒng)分層次,理清脈絡(luò)
任何一個復(fù)雜的系統(tǒng),都可以分成不同的層次,每個層次有自己的功能和職責(zé)。比如,在軟件架構(gòu)中,常見的有表現(xiàn)層、業(yè)務(wù)邏輯層、數(shù)據(jù)訪問層等。
分層的好處是顯而易見的。它可以讓系統(tǒng)結(jié)構(gòu)更加清晰,便于開發(fā)和維護;可以降低各個層次之間的耦合度,提高系統(tǒng)的可擴展性;還可以讓不同層次的開發(fā)者專注于自己的工作,提高開發(fā)效率。
拿 Java 的 Spring 框架來說,它就很好地體現(xiàn)了層次性。表現(xiàn)層可以用 Spring MVC 來處理用戶的請求和響應(yīng),業(yè)務(wù)邏輯層用 Spring 的 Service 來實現(xiàn)具體的業(yè)務(wù)邏輯,數(shù)據(jù)訪問層用 MyBatis 或者 Hibernate 來操作數(shù)據(jù)庫。各個層次之間通過接口來交互,互不干擾,這樣整個系統(tǒng)就更加靈活、易擴展。
(四)動態(tài)性:系統(tǒng)是不斷變化的,要能適應(yīng)變化
世界上唯一不變的就是變化,軟件系統(tǒng)也是如此。用戶的需求在不斷變化,技術(shù)在不斷發(fā)展,系統(tǒng)所處的環(huán)境也在不斷變化。因此,系統(tǒng)思維要求咱們具備動態(tài)性,能夠預(yù)見系統(tǒng)可能發(fā)生的變化,并設(shè)計出能夠適應(yīng)變化的架構(gòu)。
比如,隨著業(yè)務(wù)的發(fā)展,系統(tǒng)的數(shù)據(jù)量和訪問量可能會急劇增加,這時候咱們就需要考慮如何對系統(tǒng)進行擴容,是增加服務(wù)器的數(shù)量,還是對系統(tǒng)進行分布式架構(gòu)改造;當(dāng)出現(xiàn)新的技術(shù)和框架時,咱們要考慮是否適合自己的系統(tǒng),是否需要進行技術(shù)升級。
在 Java 開發(fā)中,動態(tài)性還體現(xiàn)在代碼的設(shè)計上。咱們可以使用設(shè)計模式,比如策略模式、工廠模式、觀察者模式等,來讓代碼更加靈活,能夠輕松應(yīng)對需求的變化。比如,當(dāng)需要增加一種新的支付方式時,使用策略模式可以在不修改原有代碼的基礎(chǔ)上,輕松添加新的支付策略類。
四、頂級架構(gòu)師是怎么練系統(tǒng)思維的?偷偷告訴你他們的 "套路"
(一)從整體出發(fā),畫好系統(tǒng)架構(gòu)圖
頂級架構(gòu)師在設(shè)計系統(tǒng)的時候,首先會從整體出發(fā),畫好系統(tǒng)架構(gòu)圖。這不是簡單地畫幾個框和箭頭,而是要詳細描述系統(tǒng)的各個組成部分、它們之間的關(guān)系、數(shù)據(jù)的流動方向、技術(shù)選型等等。
畫架構(gòu)圖的過程,其實就是梳理系統(tǒng)思維的過程。通過畫架構(gòu)圖,咱們可以清晰地看到系統(tǒng)的整體結(jié)構(gòu),發(fā)現(xiàn)各個部分之間的潛在問題,比如是否存在單點故障,是否有性能瓶頸,是否容易擴展等等。
在畫 Java 系統(tǒng)的架構(gòu)圖時,可以使用一些工具,比如 Visio、PlantUML 等。對于分布式系統(tǒng),還可以畫出微服務(wù)的調(diào)用關(guān)系圖、數(shù)據(jù)庫的分片架構(gòu)圖等。
(二)多拆解經(jīng)典系統(tǒng),學(xué)習(xí)別人的經(jīng)驗
站在巨人的肩膀上才能看得更遠。頂級架構(gòu)師會經(jīng)常拆解經(jīng)典的系統(tǒng),比如淘寶、京東、微信等大型系統(tǒng)的架構(gòu),學(xué)習(xí)它們是如何應(yīng)對高并發(fā)、海量數(shù)據(jù)、復(fù)雜業(yè)務(wù)的。
拆解經(jīng)典系統(tǒng)的時候,要從整體到局部,先了解系統(tǒng)的整體架構(gòu),然后分析各個模塊的設(shè)計思路,再研究具體的實現(xiàn)細節(jié)。比如,淘寶的分布式架構(gòu)是如何實現(xiàn)負載均衡和故障轉(zhuǎn)移的,微信的消息系統(tǒng)是如何保證高可用性和實時性的。
通過拆解經(jīng)典系統(tǒng),咱們可以學(xué)習(xí)到很多系統(tǒng)思維的應(yīng)用方法,比如如何進行分層設(shè)計、如何處理分布式系統(tǒng)中的一致性問題、如何設(shè)計可擴展的架構(gòu)等等。同時,還可以借鑒它們的經(jīng)驗教訓(xùn),避免在自己的項目中走彎路。
(三)在實踐中不斷迭代,總結(jié)經(jīng)驗教訓(xùn)
系統(tǒng)思維不是天生就有的,而是在實踐中不斷培養(yǎng)和鍛煉出來的。頂級架構(gòu)師會在每個項目中不斷實踐系統(tǒng)思維,從需求分析、架構(gòu)設(shè)計、開發(fā)實現(xiàn)到系統(tǒng)維護,每個環(huán)節(jié)都運用系統(tǒng)思維去思考。
在項目結(jié)束后,他們會進行總結(jié)復(fù)盤,分析系統(tǒng)設(shè)計中存在的問題,比如哪些地方考慮不周全,哪些技術(shù)方案不夠合理,哪些模塊的耦合度太高等等。通過總結(jié)復(fù)盤,不斷改進自己的系統(tǒng)思維,提高自己的架構(gòu)設(shè)計能力。
比如,在一個 Java 項目中,可能會發(fā)現(xiàn)某個模塊的異常處理不夠完善,導(dǎo)致系統(tǒng)出現(xiàn)了一些不可預(yù)知的錯誤。這時候,就要從系統(tǒng)的角度去分析,為什么會出現(xiàn)這種情況,如何在架構(gòu)設(shè)計和代碼實現(xiàn)中避免類似的問題。
(四)培養(yǎng)跨領(lǐng)域思維,拓寬知識面
軟件系統(tǒng)不是孤立存在的,它和業(yè)務(wù)、運營、運維等各個領(lǐng)域都有著密切的關(guān)系。頂級架構(gòu)師會培養(yǎng)跨領(lǐng)域思維,了解業(yè)務(wù)需求、運營模式、運維成本等方面的知識,這樣才能設(shè)計出更符合實際需求的系統(tǒng)。
比如,了解業(yè)務(wù)需求可以讓架構(gòu)師更好地把握系統(tǒng)的核心功能和發(fā)展方向,設(shè)計出更具業(yè)務(wù)價值的架構(gòu);了解運維知識可以讓架構(gòu)師在設(shè)計系統(tǒng)時考慮到運維的便利性,比如如何進行監(jiān)控、如何進行部署和升級等。
在 Java 技術(shù)領(lǐng)域,跨領(lǐng)域思維還體現(xiàn)在對其他技術(shù)棧的了解。比如,了解前端技術(shù)可以讓架構(gòu)師更好地設(shè)計前后端的交互接口,了解數(shù)據(jù)庫技術(shù)可以讓架構(gòu)師更好地優(yōu)化數(shù)據(jù)存儲方案。
五、給咱 Java 開發(fā)者的小貼士:在代碼中踐行系統(tǒng)思維
(一)寫代碼前先想清楚整體結(jié)構(gòu)
很多開發(fā)者拿到需求就開始寫代碼,想到哪兒寫到哪兒,結(jié)果代碼寫得亂七八糟,后期維護起來痛苦不堪。咱們在寫代碼前,先想想這個功能在整個系統(tǒng)中處于什么位置,和其他模塊有什么關(guān)系,需要遵循哪些設(shè)計原則。
比如,要實現(xiàn)一個用戶登錄功能,先考慮它需要和用戶數(shù)據(jù)庫交互,可能需要調(diào)用短信驗證碼服務(wù)或者第三方登錄服務(wù),還要考慮登錄后的權(quán)限管理。然后,設(shè)計出合理的類和接口,讓這個功能模塊既滿足當(dāng)前需求,又易于擴展。
(二)注意代碼的可維護性和可擴展性
系統(tǒng)思維要求咱們的代碼能夠適應(yīng)變化,所以在寫代碼的時候,要注意代碼的可維護性和可擴展性。盡量使用面向?qū)ο蟮脑O(shè)計思想,封裝重復(fù)的代碼,提取公共的模塊,使用設(shè)計模式來優(yōu)化代碼結(jié)構(gòu)。
比如,當(dāng)有多個地方需要進行日志記錄時,不要在每個地方都寫重復(fù)的日志代碼,而是封裝一個日志工具類,供各個模塊調(diào)用;當(dāng)需要實現(xiàn)不同的業(yè)務(wù)邏輯時,可以使用策略模式,讓不同的策略類實現(xiàn)相同的接口,方便后續(xù)添加新的策略。
(三)多和團隊成員溝通,了解系統(tǒng)全貌
很多開發(fā)者只關(guān)注自己負責(zé)的模塊,對整個系統(tǒng)的其他部分了解甚少。這樣很難培養(yǎng)系統(tǒng)思維,因為看不到系統(tǒng)的整體結(jié)構(gòu)和各個模塊之間的關(guān)系。
咱們要多和團隊成員溝通,了解系統(tǒng)的整體架構(gòu),了解其他模塊的功能和接口。這樣,在開發(fā)自己的模塊時,就能更好地考慮和其他模塊的交互,避免出現(xiàn)接口不兼容、數(shù)據(jù)不一致等問題。同時,通過和團隊成員的交流,還能學(xué)習(xí)到他們的系統(tǒng)思維和設(shè)計經(jīng)驗。
六、總結(jié):系統(tǒng)思維,讓你從普通開發(fā)者到頂級架構(gòu)師的蛻變
說了這么多,相信您已經(jīng)對系統(tǒng)思維有了一定的了解。系統(tǒng)思維不是什么高深莫測的東西,它其實就體現(xiàn)在咱們?nèi)粘5拈_發(fā)工作中,體現(xiàn)在對每個需求的分析、每個模塊的設(shè)計、每一行代碼的編寫中。
頂級架構(gòu)師之所以厲害,就是因為他們把系統(tǒng)思維練到了骨子里,能夠從整體的、關(guān)聯(lián)的、層次的、動態(tài)的角度去看待和解決問題。對于咱們 Java 開發(fā)者來說,只要咱們在實踐中不斷培養(yǎng)和鍛煉系統(tǒng)思維,注重從整體出發(fā)設(shè)計系統(tǒng),關(guān)注各個部分之間的關(guān)系,適應(yīng)系統(tǒng)的變化,就一定能不斷提升自己的技術(shù)水平,向頂級架構(gòu)師的方向邁進。
所以,別再羨慕那些頂級架構(gòu)師了,從現(xiàn)在開始,偷偷練起你的系統(tǒng)思維吧!相信不久的將來,你也能成為別人眼中的 "大神"。