這些感悟并非來(lái)自于具體的技術(shù)實(shí)現(xiàn),而是關(guān)于我在架構(gòu)設(shè)計(jì)和實(shí)施過(guò)程中所體會(huì)到的一些軟性經(jīng)驗(yàn)和領(lǐng)悟。我希望通過(guò)這些分享,能夠激發(fā)大家對(duì)于架構(gòu)設(shè)計(jì)和技術(shù)實(shí)踐的思考,幫助大家更好地理解和應(yīng)用架構(gòu)原則和方法。
一、“提出問(wèn)題”難于“解決問(wèn)題”
在我看來(lái),我最近的一個(gè)重要感悟是:提出問(wèn)題要比解決問(wèn)題更具挑戰(zhàn)性。作為一個(gè)工程師,我通常習(xí)慣于解決問(wèn)題,因?yàn)檫@是我們的工作之一。但是,我意識(shí)到我很少主動(dòng)提出問(wèn)題,尤其是從用戶的角度出發(fā)去提出問(wèn)題或需求。我發(fā)現(xiàn),這種不主動(dòng)提出問(wèn)題的傾向可能導(dǎo)致團(tuán)隊(duì)內(nèi)部的溝通障礙,特別是與產(chǎn)品經(jīng)理等其他團(tuán)隊(duì)成員的交流。
有時(shí)候我們會(huì)抱怨產(chǎn)品經(jīng)理不懂技術(shù),提出的需求不夠?qū)I(yè)。但是,我開始思考,作為工程師,我是否應(yīng)該更加積極地從用戶的角度出發(fā),去了解用戶真正的困惑,并提出合理的需求來(lái)解決它們。或者,我是否可以親身體驗(yàn)用戶的場(chǎng)景,然后提出全新的問(wèn)題并解決它們。
我認(rèn)為,我們不僅僅應(yīng)該是解決問(wèn)題的人,還應(yīng)該是提出問(wèn)題的人,主動(dòng)去思考如何能夠讓業(yè)務(wù)更加先進(jìn)。盡管設(shè)計(jì)架構(gòu)、編寫代碼解決問(wèn)題是一項(xiàng)很棒的工作,但是當(dāng)我嘗試主動(dòng)提出問(wèn)題和改進(jìn)用戶需求時(shí),我發(fā)現(xiàn)這其實(shí)是一項(xiàng)更加困難的任務(wù)。我覺(jué)得這種思維轉(zhuǎn)變,對(duì)于我個(gè)人的職業(yè)發(fā)展和團(tuán)隊(duì)的成功都是非常重要的。
二、決定“不要什么”比“要做什么”更難
在我看來(lái),我最近的第二個(gè)重要感悟是:決定“不要什么”比“要做什么”更具挑戰(zhàn)性。或許這是因?yàn)槿诵缘谋举|(zhì)是貪婪的,所以在項(xiàng)目或架構(gòu)設(shè)計(jì)中,我們常常傾向于盡可能包含更多功能和需求,特別是對(duì)于非功能性需求更是如此。
當(dāng)我們審查一個(gè)架構(gòu)設(shè)計(jì)說(shuō)明書時(shí),往往會(huì)看到對(duì)高可用性、高性能、高擴(kuò)展性、高可維護(hù)性等需求的強(qiáng)調(diào),幾乎所有的架構(gòu)設(shè)計(jì)都會(huì)列出這些非功能性需求。這些需求似乎成了一個(gè)共識(shí)的列表,認(rèn)為所有的架構(gòu)都必須滿足這些需求。當(dāng)然,功能性需求更是不勝枚舉,產(chǎn)品經(jīng)理會(huì)不斷地添加。
然而,回過(guò)頭來(lái)仔細(xì)思考,什么是架構(gòu)?實(shí)際上,在很多層面上,架構(gòu)是一種權(quán)衡和平衡的結(jié)果。作為一個(gè)架構(gòu)師,你應(yīng)該是那個(gè)能夠明確說(shuō)出“不要”的人。在現(xiàn)實(shí)中,很多東西是無(wú)法兼得的。比如,是盡早發(fā)布產(chǎn)品,還是等到所有功能都完善再發(fā)布;又比如,在一致性和性能之間需要取舍,我們是選擇強(qiáng)一致性,還是犧牲一致性以換取更高的性能等。CAP 原則就是這樣一個(gè)關(guān)于權(quán)衡的準(zhǔn)則。
因此,作為架構(gòu)師,我強(qiáng)烈建議大家在架構(gòu)設(shè)計(jì)的初期就確定一些原則。例如,數(shù)據(jù)一致性優(yōu)先級(jí)最高,或者盡早發(fā)布基礎(chǔ)功能版本優(yōu)于延遲發(fā)布完善功能產(chǎn)品等。當(dāng)面臨沖突時(shí),我們可以利用這些原則進(jìn)行取舍和決策。
三、非功能性需求決定架構(gòu)
在我看來(lái),我最近的第三個(gè)重要感悟是:非功能性需求決定架構(gòu)。在很多人眼中,做架構(gòu)的第一步是收集各種功能性需求,因?yàn)樽罱K的產(chǎn)品是為用戶服務(wù)的。
然而,事實(shí)并非如此。一個(gè)優(yōu)秀的架構(gòu)實(shí)際上是由非功能性需求所驅(qū)動(dòng),而不是由功能性需求所驅(qū)動(dòng)。你會(huì)發(fā)現(xiàn),對(duì)于一個(gè)功能,可以有很多種不同的架構(gòu)方案來(lái)實(shí)現(xiàn),但是你為什么選擇某個(gè)方案,其實(shí)是由非功能性需求來(lái)決定的。
大家都非常清楚什么是非功能性需求,包括性能、伸縮性、可擴(kuò)展性、可維護(hù)性等,甚至還包括團(tuán)隊(duì)的結(jié)構(gòu)、技術(shù)水平、發(fā)布周期要求等等。通過(guò)這些需求來(lái)篩選可用的方案,最終找到一個(gè)合適的架構(gòu)。
因此,非功能性需求在架構(gòu)設(shè)計(jì)中扮演著至關(guān)重要的角色,可以說(shuō)是決定性因素之一。設(shè)計(jì)完架構(gòu)后,如果缺少某個(gè)功能性需求,我們很容易意識(shí)到并且可以進(jìn)行補(bǔ)充,它不會(huì)對(duì)架構(gòu)產(chǎn)生根本性的影響。但如果我們忽略了某個(gè)非功能性需求,那么在未來(lái)可能會(huì)導(dǎo)致嚴(yán)重的問(wèn)題,甚至需要重寫架構(gòu)。例如,如果架構(gòu)中的數(shù)據(jù)一致性問(wèn)題無(wú)法解決,或者在設(shè)計(jì)階段沒(méi)有充分考慮性能問(wèn)題,那么所有的功能性實(shí)現(xiàn)都會(huì)變得毫無(wú)意義。這基本上就是重構(gòu),甚至可以說(shuō)不應(yīng)該叫重構(gòu),而是應(yīng)該叫重新創(chuàng)建或者重寫,因?yàn)槟阈枰獜氐字匦略O(shè)計(jì)整個(gè)架構(gòu)。
實(shí)際上在架構(gòu)領(lǐng)域,大家對(duì)這點(diǎn)也是有共識(shí)的。比如下圖中這個(gè) Micro-Kernel 的架構(gòu)模式來(lái)自《面向模式的軟件架構(gòu)》的第一卷,它一大特點(diǎn)就是有比較好的可擴(kuò)展性,同時(shí)通過(guò) Plugin 之間的隔離,能夠提高系統(tǒng)的可用性。
“簡(jiǎn)單"并不容易
在我看來(lái),我最近的第四個(gè)重要感悟是:“簡(jiǎn)單”并不容易。許多架構(gòu)師都會(huì)強(qiáng)調(diào)保持簡(jiǎn)單,但很多時(shí)候我們會(huì)混淆簡(jiǎn)單和容易。簡(jiǎn)單是指簡(jiǎn)潔、清晰,而容易是指易于實(shí)現(xiàn)、理解或操作。我們應(yīng)該努力保持簡(jiǎn)潔,而不是追求輕松的實(shí)現(xiàn)。
正如喬布斯所說(shuō),簡(jiǎn)單有時(shí)比復(fù)雜更難,因?yàn)樗枰獙?duì)問(wèn)題、事物的深入研究,才能找到真正簡(jiǎn)潔的解決方案。簡(jiǎn)單實(shí)際上是一種巧妙的設(shè)計(jì)和思考。
舉例來(lái)說(shuō),布隆過(guò)濾器就是一個(gè)簡(jiǎn)單而高效的重復(fù)數(shù)據(jù)過(guò)濾算法,它巧妙地解決了一個(gè)問(wèn)題。如果想要使某件事情變得簡(jiǎn)單,就需要進(jìn)行大量深入的工作。例如,簡(jiǎn)化架構(gòu)很大程度上取決于我們對(duì)技術(shù)、開發(fā)過(guò)程以及不同業(yè)務(wù)場(chǎng)景的深入理解,而不僅僅是架構(gòu)本身的設(shè)計(jì)容易與否。
因此,保持簡(jiǎn)單并不容易,它需要我們深入理解問(wèn)題的本質(zhì),并找到最優(yōu)雅、最有效的解決方案。
舉個(gè)例子,我們來(lái)回顧一下軟件生命周期中各個(gè)階段的成本消耗占比。
可以看到,在整個(gè)軟件生命周期中,成本消耗最高的并不是設(shè)計(jì)、編碼這些階段,而是維護(hù)階段。也就是說(shuō),如果你讓維護(hù)變得簡(jiǎn)單,這會(huì)是最有性價(jià)比的。
五、永遠(yuǎn)不要停止編碼
在我看來(lái),我最近的第五個(gè)重要感悟是:永遠(yuǎn)不要停止編碼。這一點(diǎn)非常重要,特別是對(duì)于一個(gè)架構(gòu)師來(lái)說(shuō),要牢記自己始終是一名程序員。作為架構(gòu)師,我們可能設(shè)計(jì)了一個(gè)高層次的架構(gòu),但實(shí)際上,代碼才是軟件的最終實(shí)現(xiàn)形式。每個(gè)程序員在架構(gòu)落地的過(guò)程中的實(shí)現(xiàn),都可能影響最終的架構(gòu)呈現(xiàn)。
此外,如果你停止編碼,最大的影響不是技術(shù)上的滯后或代碼編寫速度變慢,而是你可能會(huì)逐漸失去對(duì)編程的敬畏之心,忘記作為程序員的體驗(yàn),特別是編碼過(guò)程中的那些挑戰(zhàn)與痛苦。你可能會(huì)陷入一些不切實(shí)際的幻想,做出一些不切實(shí)際的設(shè)計(jì),這才是最大的問(wèn)題。
我們都熟悉 JAVA 的創(chuàng)始人 James Gosling,在亞馬遜擔(dān)任杰出工程師的職位,相當(dāng)于高級(jí)副總裁,但他依然堅(jiān)持編碼。他每年編寫的代碼量是驚人的,常常超過(guò) 10 萬(wàn)行。這個(gè)事實(shí)告訴我們,無(wú)論職位有多高,作為一個(gè)技術(shù)人員,始終保持對(duì)編碼的熱愛(ài)和投入是至關(guān)重要的。
六、風(fēng)險(xiǎn)優(yōu)先
在我看來(lái),我最近的第六個(gè)重要感悟是:風(fēng)險(xiǎn)優(yōu)先。
讓我們先思考一個(gè)問(wèn)題:為什么要進(jìn)行架構(gòu)設(shè)計(jì)?在我看來(lái),架構(gòu)設(shè)計(jì)的主要目的是轉(zhuǎn)化、降低、甚至避免整個(gè)開發(fā)過(guò)程中的風(fēng)險(xiǎn)。作為架構(gòu)師,我們的一個(gè)主要責(zé)任就是在項(xiàng)目的早期階段識(shí)別出系統(tǒng)可能存在的風(fēng)險(xiǎn),并通過(guò)我們的設(shè)計(jì)來(lái)轉(zhuǎn)化、消除這些風(fēng)險(xiǎn)。
我們經(jīng)常提到的原型方法或者架構(gòu)切片的快速迭代方式,實(shí)際上也是在早期盡量測(cè)試風(fēng)險(xiǎn),評(píng)估我們的架構(gòu)是否能夠解決相關(guān)問(wèn)題,特別是那些非功能性需求的實(shí)現(xiàn)風(fēng)險(xiǎn)。這些風(fēng)險(xiǎn)往往不像功能性需求那樣容易在項(xiàng)目初期被發(fā)現(xiàn),但是修正它們的成本通常比修正功能性需求要大得多,甚至可能導(dǎo)致整個(gè)項(xiàng)目的失敗。
比如敏捷開發(fā),很多人認(rèn)為敏捷開發(fā)只是更快地開發(fā)出一個(gè)產(chǎn)品,然后快速地將其交付到市場(chǎng)上,但這只是敏捷的一部分。另一個(gè)很重要的方面是,如果一個(gè)項(xiàng)目注定要失敗,那么就要盡早地讓它失敗,絕對(duì)不能將風(fēng)險(xiǎn)留到最后。這也是敏捷方法的一種體現(xiàn)。
在這里,我想推薦一本書《Just Enough Software Architecture(恰如其分的軟件架構(gòu))》。這是一本非常流行的架構(gòu)書籍,強(qiáng)調(diào)了架構(gòu)設(shè)計(jì)的目的是為了化解軟件實(shí)現(xiàn)中的風(fēng)險(xiǎn)。如果項(xiàng)目中的所有風(fēng)險(xiǎn)都可以通過(guò)未來(lái)的重構(gòu)來(lái)解決,那么你根本就不需要進(jìn)行架構(gòu)設(shè)計(jì),直接等待重構(gòu)即可。這也是我非常贊同的觀點(diǎn):風(fēng)險(xiǎn)優(yōu)先。
從“問(wèn)題”開始,而不是“技術(shù)”
我最近的第七個(gè)重要感悟是:從“問(wèn)題”開始,而不是“技術(shù)”。
作為技術(shù)人員,我們往往會(huì)很樂(lè)意學(xué)習(xí)新技術(shù),并且一旦掌握了這些技術(shù),就會(huì)有強(qiáng)烈的欲望去應(yīng)用它們。有時(shí)候我們甚至?xí)杏X(jué)自己被某個(gè)技術(shù)所“上身”,迫不及待地想要將其應(yīng)用到工作中,而忽略了當(dāng)前手頭上的問(wèn)題是否適合用這個(gè)技術(shù)來(lái)解決。或許你也有類似的經(jīng)歷。
冷靜下來(lái)想想,我們每個(gè)人都明白,應(yīng)該從實(shí)際需求、用戶問(wèn)題出發(fā),而不是一味地從技術(shù)角度考慮。然而,在實(shí)際工作中,我們常常不自覺(jué)地忽略了這一點(diǎn)。就像拿著一把錘子,看到什么都想當(dāng)作釘子來(lái)敲。
然而,這種做法可能會(huì)帶來(lái)很大的害處。讓我來(lái)分享一個(gè)故事,來(lái)自我之前工作過(guò)的一個(gè)團(tuán)隊(duì)。
在那個(gè)團(tuán)隊(duì)中,有一位工程師維護(hù)著一個(gè)簡(jiǎn)單的服務(wù),使用 MySQL 作為數(shù)據(jù)存儲(chǔ)。后來(lái),他對(duì)當(dāng)時(shí)新出的 DynamoDB 產(chǎn)生了興趣,并學(xué)習(xí)了相關(guān)知識(shí)。結(jié)果發(fā)生了以下情況:他決定使用 DynamoDB 替換 MySQL,但這卻成為了一個(gè)噩夢(mèng)的開始。很快就發(fā)現(xiàn) DynamoDB 并不能很好地支持事務(wù)特性,而且性能極差的客戶端類庫(kù)導(dǎo)致了性能問(wèn)題,效率大大降低。
于是,他又嘗試使用最終一致性技術(shù),采用消息隊(duì)列來(lái)實(shí)現(xiàn)。但隨之而來(lái)的是,實(shí)現(xiàn)相同功能的復(fù)雜性大大增加,維護(hù)成本也由一個(gè)人變成了整個(gè)團(tuán)隊(duì)。
這個(gè)故事告訴我們,我們對(duì)技術(shù)的熱情有時(shí)會(huì)讓事情變得更加復(fù)雜,甚至?xí)?lái)額外的煩惱。我們應(yīng)該始終從問(wèn)題出發(fā),而不是被技術(shù)所驅(qū)動(dòng)。
八、過(guò)度繁忙使你落后
我最近的第八個(gè)重要感悟是:過(guò)度繁忙使你落后。
對(duì)于IT人員來(lái)說(shuō),忙碌已經(jīng)成為了一種習(xí)慣,加班似乎也成了公司高效的標(biāo)志,“996”甚至變成了一種常態(tài)。但是我們有時(shí)候需要反思一下,有多久沒(méi)有在業(yè)余時(shí)間看與技術(shù)相關(guān)的書了?我曾經(jīng)在公司里問(wèn)過(guò)這個(gè)問(wèn)題,百分之百的人都告訴我,下班后已經(jīng)很晚了,回到家基本上沒(méi)有時(shí)間再看書,刷一下手機(jī),就可以直接睡覺(jué)了。這是一個(gè)非常值得我們?nèi)ニ伎嫉膯?wèn)題。
作為技術(shù)人員,如果你不更新你的知識(shí),或者繁忙讓你沒(méi)有時(shí)間更新知識(shí),那會(huì)有什么樣的結(jié)果呢?讓我分享一個(gè)有趣的現(xiàn)象,我遇到過(guò)不少程序員,有些是之前的同事,有些是朋友。他們換了一份新工作,一開始進(jìn)入那家公司時(shí)會(huì)說(shuō),“這個(gè)公司我不是特別看好,我了解一下它的技術(shù),就準(zhǔn)備跳槽了。”可是過(guò)了兩三年,我再問(wèn)他們,“為什么還在這里,還沒(méi)跳槽?”結(jié)果他們告訴我,“我覺(jué)得現(xiàn)在的招聘形勢(shì)不太好,不太好找新的機(jī)會(huì)。”幾年下來(lái),他們對(duì)公司越來(lái)越“忠誠(chéng)”了。實(shí)際上,在一個(gè)公司忙碌工作幾年,沒(méi)有留出時(shí)間學(xué)習(xí),導(dǎo)致他們失去了跳槽的能力和勇氣。當(dāng)他們想要重新回到市場(chǎng)時(shí),卻發(fā)現(xiàn)自己已經(jīng)落伍了,技術(shù)已經(jīng)過(guò)時(shí)了,甚至已經(jīng)被淘汰了。
在這個(gè)高速發(fā)展的時(shí)代,如果因?yàn)檫^(guò)度忙碌,導(dǎo)致你沒(méi)有時(shí)間學(xué)習(xí)和更新自己的知識(shí),那必然會(huì)讓你落后。即使你不跳槽,呆在同一家公司里,公司的業(yè)務(wù)不斷發(fā)展,數(shù)據(jù)量會(huì)越來(lái)越大,用戶需求也會(huì)越來(lái)越復(fù)雜。如果你長(zhǎng)期不更新知識(shí),掌握的技能沒(méi)有發(fā)生變化,你會(huì)覺(jué)得越來(lái)越難以應(yīng)付,最終只能通過(guò)不斷地加班來(lái)應(yīng)對(duì)。
另外,還有一種可能是,你不更新知識(shí),不深入思考,那么很大概率,你所創(chuàng)造的技術(shù)和業(yè)務(wù)喪失了領(lǐng)先性,沒(méi)有領(lǐng)先優(yōu)勢(shì),只能被動(dòng)緊緊跟隨競(jìng)爭(zhēng)對(duì)手。而緊緊跟隨就意味著你只能加班,這將導(dǎo)致更多的忙碌,更少的時(shí)間用來(lái)學(xué)習(xí)和提升自己的技能。這實(shí)際上是一個(gè)惡性循環(huán),你花越多的時(shí)間去忙碌,就越?jīng)]有時(shí)間去學(xué)習(xí),去提高自己的工作技能,最終只能靠加班來(lái)追趕,結(jié)果就更加忙碌,更加沒(méi)有時(shí)間學(xué)習(xí),最終你將陷入一個(gè)無(wú)法自拔的惡性循環(huán)中。
當(dāng)我在某個(gè)領(lǐng)域工作了一段時(shí)間后,比如三五年之后,我會(huì)逐漸變得對(duì)該領(lǐng)域的業(yè)務(wù)越來(lái)越熟悉,解決問(wèn)題也會(huì)變得更加順手。但與此同時(shí),我也會(huì)意識(shí)到能夠?qū)W習(xí)到的新知識(shí)和技能會(huì)逐漸減少。有些人可能會(huì)建議我離開這個(gè)舒適區(qū),嘗試去另一個(gè)領(lǐng)域,以激發(fā)學(xué)習(xí)新知識(shí)的動(dòng)力。但我覺(jué)得并不需要這么做。
我認(rèn)為,即使留在原來(lái)的領(lǐng)域,我也可以通過(guò)一些方法來(lái)持續(xù)學(xué)習(xí)和成長(zhǎng)。我可以有意識(shí)地?cái)[脫舒適感,擠出時(shí)間來(lái)重新學(xué)習(xí),然后嘗試以不同的方式解決問(wèn)題。即使在相同的領(lǐng)域中,我也可以探索新的方法和技術(shù),從而提升自己的能力。
通過(guò)持續(xù)學(xué)習(xí)和不斷探索,我可以在工作中保持活力,并不斷地提升自己的競(jìng)爭(zhēng)力。這種積極的學(xué)習(xí)態(tài)度和探索精神對(duì)于我的職業(yè)發(fā)展是非常重要的,它能夠讓我保持在一個(gè)不斷成長(zhǎng)的狀態(tài)中。
作者丨 greencoatman
來(lái)源丨公眾號(hào):二進(jìn)制跳動(dòng)(ID:gh_6fead375a876)