譯者 | 劉汪洋
審校 | 重樓?
在審查某個軟件解決方案時,你是否感到其復(fù)雜性超出了實際需求?在對該架構(gòu)或方法進行批評之前,請仔細(xì)考慮其可能的深遠(yuǎn)影響。
“過度架構(gòu)”常常被用來形容某些軟件解決方案的設(shè)計、抽象、實現(xiàn)或部署存在不必要的復(fù)雜性。這種批評通常暗示著這些方面難以理解、不易維護,甚至可能是錯誤的。然而,這類指責(zé)往往缺乏上下文或具體的支持性論述,但卻容易被人們輕信和接受。
那么,為一個解決方案貼上“過度架構(gòu)”的標(biāo)簽究竟意味著什么?
通常情況下,這種標(biāo)簽被視為軟件工程師規(guī)避責(zé)任的一種“萬能借口”,用來解釋因工作量超出預(yù)期或項目時間線延誤而產(chǎn)生的問題。更令人遺憾的是,管理層往往會毫不懷疑地接受這一解釋,特別是在做出相關(guān)決策的工程師缺席時,這種解釋更容易顯得有說服力。
確實,最初實施的架構(gòu)可能與當(dāng)前的技術(shù)棧、業(yè)務(wù)假設(shè)或抽象存在分歧,但你是否有足夠的依據(jù)來明確判斷它是“過度架構(gòu)”?公司自實施以來是否經(jīng)歷了業(yè)務(wù)目標(biāo)或技術(shù)方向的變化?當(dāng)初在設(shè)計時是否考慮了某些非功能性需求?是否有任何提交信息能夠提供進一步的背景支持?
最關(guān)鍵的問題是,你的擔(dān)憂真的能準(zhǔn)確定義“過度架構(gòu)”,還是其實并沒有那么嚴(yán)重?或許我們都不能輕易下結(jié)論。
軟件工程師負(fù)責(zé)開發(fā)軟件
借用哈姆雷特的經(jīng)典獨白:
維護,還是不維護,這是個問題:是心甘情愿地忍受荒唐實現(xiàn)帶來的打擊, 還是拿起武器對抗無盡的麻煩并從頭開始,用一張白紙重新設(shè)計。
雖然哈姆雷特的獨白原意在探討生死問題,這一段改編則成為了對軟件開發(fā)過程的隱喻。軟件工程師往往更傾向于編寫新代碼,而不愿意長期維護他人編寫的代碼。
當(dāng)工程師被分配到維護任務(wù)時,無論是何種形式,他們通常會尋找各種方式來重新設(shè)計、重構(gòu)甚至重寫代碼,以使工作更加有趣。如果代碼的變更頻率過高、圈復(fù)雜度過大,或者代碼已經(jīng)難以維護,那么這種決策無疑是有其合理性的。盡管這可能會令產(chǎn)品負(fù)責(zé)人和Scrum Master感到不快,但有時,歷史遺留問題已無法忽視。
然而,公開稱現(xiàn)有代碼為“過度架構(gòu)”可能為你贏得重新設(shè)計的機會,但也可能引發(fā)更深入的質(zhì)疑,尤其是在以下幾種情況下:
- 工程師不愿深入理解當(dāng)前的實現(xiàn)
- 工程師不充分了解業(yè)務(wù)需求或技術(shù)需求
- 工程師對現(xiàn)有的設(shè)計模式或代碼結(jié)構(gòu)持不同意見
- 工程師不喜歡現(xiàn)有代碼的風(fēng)格、格式,甚至編程語言?
諷刺的是,重寫項目的規(guī)模往往會超出預(yù)期,因為工程師最終不得不理解現(xiàn)有的解決方案才能重新實現(xiàn)它。盡管聲稱自己不是在“重復(fù)造輪子”,但在沒有全面理解的情況下,工程師往往還是得走這條路。你的組織是否真的準(zhǔn)備好迎接API優(yōu)先、微服務(wù)、NoSQL等新技術(shù)的挑戰(zhàn)?
隨著時間線的延長,領(lǐng)導(dǎo)層的挫敗感增加,其他重要工作被推遲或擱置,而這一切的起因往往是工程師堅稱這些改變是必要的。這樣的情景屢見不鮮,許多人甚至曾是始作俑者,但通常這些故事的結(jié)局并不理想。
最終的問題仍然存在:它真的過度架構(gòu)了嗎?
問題架構(gòu)
在軟件工程領(lǐng)域,架構(gòu)類型繁多,如企業(yè)架構(gòu)、系統(tǒng)架構(gòu)、應(yīng)用架構(gòu)、軟件架構(gòu)、云架構(gòu)和集成架構(gòu)等。更為復(fù)雜的是,不同的組織根據(jù)其內(nèi)部需求對這些架構(gòu)學(xué)科進行了獨特的定義,使得明確劃分每種架構(gòu)的職責(zé)和界限變得困難。由于不同的軟件架構(gòu)在不同的組織和上下文中可能有不同的定義和職責(zé)。因此,直接將它們進行比較是不合理的,因為它們之間的差異太大,就像不能簡單地將它們進行直接比較。
盡管如此,我們依然可以嘗試定義“問題”架構(gòu)。我認(rèn)為有三種基本類型的架構(gòu)可能會存在問題。
1. 不同架構(gòu)
“不同架構(gòu)”指的是在解決方案中對于如何處理非功能性需求存在分歧的情況。比如,針對一個面向云的解決方案,究竟應(yīng)該采用云原生還是云無關(guān)的架構(gòu)?穩(wěn)定性和可靠性是否比吞吐量和性能更重要?資源選擇的標(biāo)準(zhǔn)是成本、能力,還是兩者兼顧?對于基礎(chǔ)架構(gòu)的任何擔(dān)憂或抱怨,都必須與成功解決方案所需的重要非功能性需求相平衡。你可能不同意這些需求的優(yōu)先級,但只要這些需求得到了滿足,解決方案便是有效的,無論個人的偏好如何。 即使你認(rèn)同非功能性需求,不同的工程師也可能會提出不同的解決方案:同步與異步、面向?qū)ο蟮睦^承與組合、功能或 CRUD 的 API 端點、SQL 與 NoSQL、API 優(yōu)先與 MVC。
這些選擇本質(zhì)上都是主觀的,解決方案并無絕對的對錯,關(guān)鍵在于滿足需求。 “Hello, World”程序可以通過成千上萬種方式實現(xiàn),每種方式都有其合理性。因此,不同的工程師會以不同的方式解決同一個問題。這種差異并非錯誤,更不一定是“過度架構(gòu)”。如果非功能性需求明確并且得到了實現(xiàn),即使你不同意某些設(shè)計和實現(xiàn),這仍可能是一個成功的架構(gòu)。
2. 錯誤架構(gòu)
識別“錯誤架構(gòu)”通常需要深入分析從概念到部署的整個過程,以找出其中的缺陷。這類架構(gòu)常表現(xiàn)為需求定義不清、代碼質(zhì)量差、項目執(zhí)行不力、時間表不現(xiàn)實,以及架構(gòu)不合理。這些問題往往相互交織,難以單獨解決。具體而言,錯誤架構(gòu)的特點通常包括:
- 未能滿足非功能性需求,甚至根本沒有明確需求。
- 實現(xiàn)所需的技術(shù)技能和背景在組織內(nèi)部不存在。
- 架構(gòu)需要構(gòu)建組織核心能力之外的組件,特別是當(dāng)已有組件能夠滿足需求時。
- 部署的解決方案不穩(wěn)定,需要定期維護以避免中斷。
- 維護和擴展嚴(yán)重依賴于某些不可替代的個人。?
如果你曾參與過失敗的項目,可能會對這些特征感同身受。有時,你可能會發(fā)現(xiàn),所謂的“錯誤架構(gòu)”實際上根本沒有經(jīng)過嚴(yán)謹(jǐn)?shù)募軜?gòu)設(shè)計。更重要的是,這類項目及其最終解決方案通常難以挽救,與其相關(guān)的一切努力往往都是時間的浪費。
3. 過度架構(gòu)
是否存在真正的“過度架構(gòu)”情況?答案是肯定的。某些設(shè)計方案可能過于復(fù)雜,超出了實際需求。例如,一個開關(guān)的設(shè)計可能顯得過于繁瑣,大多數(shù)人會認(rèn)為這是不必要的復(fù)雜化,但魯布·戈德伯格和創(chuàng)客們可能持有不同的看法。以下經(jīng)歷可能是“過度架構(gòu)”的典型案例;當(dāng)然,也可能是錯誤架構(gòu),或者只是一種完全不同的架構(gòu)。
問題陳述
在我擔(dān)任獨立軟件顧問期間,曾被聘請為一位剛離職員工的替補。這位前員工設(shè)計并(大部分)實現(xiàn)了一個自定義框架,用以支持公司第一個真正的Web應(yīng)用程序。然而,留給團隊的只有少量示例實現(xiàn)和幾乎沒有文檔(設(shè)計文檔、使用說明等),剩下的工程師們只能試圖拼湊這些碎片。為了更好地理解那段時期的背景,早期的Web開發(fā)沒有真正的標(biāo)準(zhǔn)或最佳實踐,開源軟件還處于萌芽階段。用戶電腦的性能非常有限,難以運行復(fù)雜的瀏覽器端腳本。瀏覽器供應(yīng)商對HTML標(biāo)準(zhǔn)的解釋也各不相同,這是Internet Explorer主導(dǎo)市場的時期,與現(xiàn)在大不相同。我的任務(wù)是掌握這個框架,理解其內(nèi)部運作,并為后續(xù)的應(yīng)用程序開發(fā)制定路線圖。
理解與內(nèi)化
從宏觀層面看,這一任務(wù)似乎相對簡單:通過Java Servlet應(yīng)用程序(框架)生成HTML,處理請求、響應(yīng)和導(dǎo)航。然而,隨著深入了解,問題逐漸浮現(xiàn)。頁面之間緊密耦合,任何微小的改動都會影響到相鄰頁面。頁面直接生成HTML,這使得在整個應(yīng)用程序中保持一致性極為困難。要改變框架的默認(rèn)行為,需要找到對應(yīng)的鉤子,而這些鉤子往往數(shù)量眾多且混亂不堪。盡管最初的Servlet引擎工作正常,但一旦考慮更換(如使用Tomcat以提高性能),問題就會接踵而至。這些復(fù)雜問題使得項目面臨巨大挑戰(zhàn),成功的希望渺茫,因此必須做出艱難的決定。
決策時刻
我的結(jié)論是:現(xiàn)有框架勉強能夠滿足當(dāng)前需求,但不適合未來開發(fā)。繼續(xù)使用這個框架將使剩余的工程師不堪重負(fù),項目可能永遠(yuǎn)無法完成。經(jīng)理展現(xiàn)出深刻的洞察力,同意及時止損。最終,我們設(shè)計了一個更簡單、更聚焦的框架,三周內(nèi)工程師們就能夠在工作模型上開始應(yīng)用開發(fā),并在兩個月后成功演示了成果。最終,該框架非常成功,被用于多個應(yīng)用程序,直到退役。
最終結(jié)論
將原始框架視為“過度架構(gòu)”的原因包括:
- 非功能性需求的缺失:缺乏對設(shè)計和實現(xiàn)的必要約束。
- 自負(fù)驅(qū)動的設(shè)計:為了展示個人才華,過度追求復(fù)雜性。
- 過于復(fù)雜:難以實施、維護和支持。
- 無競爭優(yōu)勢:架構(gòu)的復(fù)雜性并未帶來競爭優(yōu)勢,反而大大延長了項目的上市時間。?
雖然這種情況也可以被稱為錯誤架構(gòu)或不同的架構(gòu),但這只是語義上的差別。無論如何,我們在改變方向前進行了充分的盡職調(diào)查,通過客觀的分析,而非簡單地將其貼上“過度架構(gòu)”的標(biāo)簽,最終做出了正確的決策。
最后的思考
軟件解決方案的架構(gòu)形式多種多樣,受到諸多外部因素的影響,如業(yè)務(wù)需求、開發(fā)需求、技術(shù)團隊的經(jīng)驗與技能、可用技術(shù)以及組織的成熟度等。這種多樣性是正常且必要的。然而,許多時候,一個架構(gòu)方案會在缺乏對其背景和動機的深入理解的情況下被輕易否定。盡管在某些情況下,重新實現(xiàn)部分或全部解決方案確實有其正當(dāng)理由,但有時這種動機可能源于工程師的個人偏好或私心。
作為負(fù)責(zé)任的軟件工程師,我們應(yīng)該為那些對組織最有利的方案進行辯護,而不僅僅是為技術(shù)或個人興趣服務(wù)。這并不是說技術(shù)需求不重要,而是我們應(yīng)該能夠為所提出的技術(shù)方案提供充分的理由和論據(jù)。 這一過程要求我們進行深入的調(diào)查,詳細(xì)記錄,清晰敘述,并合理辯護。簡單地將某個方案貼上“過度架構(gòu)”的標(biāo)簽遠(yuǎn)遠(yuǎn)不夠。我們必須超越簡單的批評,提出經(jīng)過深思熟慮和充分驗證的判斷,確保每個決定都是在組織的整體利益下做出的。
譯者介紹
劉汪洋,51CTO社區(qū)編輯,昵稱:明明如月,一個擁有 5 年開發(fā)經(jīng)驗的某大廠高級 Java 工程師,擁有多個主流技術(shù)博客平臺博客專家稱號,博客閱讀量 400W+,粉絲 3W+。2022 年騰訊云優(yōu)秀創(chuàng)作者,2022 年阿里云技術(shù)社區(qū)最受歡迎技術(shù)電子書 TOP 10 《性能優(yōu)化方法論》作者,慕課網(wǎng):剖析《阿里巴巴 Java 開發(fā)手冊》、深度解讀《Effective Java》 技術(shù)專欄作者。
原文標(biāo)題:Over-Architected? Maybe, Maybe Not,作者:Scott Sosna