Tungsten Fabric SDN — SmartNIC vRouter
608
2025-03-31
標(biāo)準(zhǔn)來源于目標(biāo)
前文說過,評價架構(gòu)好壞是一個很主觀的東西。既然大家寫出來的程序都能跑,憑什么就說你架構(gòu)好,我的架構(gòu)就差?拿出來大家評評理,張三說好,李四說不行,王五說將就……究竟誰說了算?現(xiàn)在已經(jīng)不是一個迷信權(quán)威的時代了,所以不管你多少光環(huán)加持,你都得說出子丑寅卯來,都得服眾才行。
我覺得,這種現(xiàn)象的產(chǎn)生,拋開“同行相輕”和“流派之爭”之類無厘頭的東西,一個很重要的原因就是沒有明確判斷標(biāo)準(zhǔn)。所以在網(wǎng)上,常常就出現(xiàn)這樣一種很熱鬧很奇葩很無奈的現(xiàn)象:我和你說性能,你跟我說安全;我跟你說安全,你跟我說擴展;我跟你說擴展,你跟我說維護;我跟你說維護,你跟我說成本……
這是一個很簡單的道理,沒有標(biāo)準(zhǔn),就無法進行評判!所以,如果不能統(tǒng)一一個評判架構(gòu)優(yōu)劣的標(biāo)準(zhǔn),我們永遠無法達成一致。你說有標(biāo)準(zhǔn)啊,性能安全可擴展……但這樣還是不行,標(biāo)準(zhǔn)過多,一樣等同于沒有標(biāo)準(zhǔn)。假設(shè)以100分為滿分,性能占多少分?安全占多少分?可擴展又占多少分?因為要想提高性能,就可能就要犧牲可擴展性;要想安全,就會犧牲性能;要想……就會……;哪一方面更重要,哪一些可以犧牲?如果不是胸有成竹的話,最后還是會左支右絀手忙腳亂,亂成一鍋粥。
所以我再提出一個觀點:以是否實現(xiàn)架構(gòu)師的設(shè)計目標(biāo)為標(biāo)準(zhǔn)。如果說一個系統(tǒng)的架構(gòu),最終實現(xiàn)了架構(gòu)師的設(shè)計目標(biāo),我們就可以說這是一個好架構(gòu);如果說沒有能實現(xiàn)架構(gòu)師的目標(biāo),這就是一個不那么好的架構(gòu)。
“等一下等一下”,你要是反應(yīng)夠敏銳的話,肯定會跳起來,“這是不是太主觀(兒戲)了?我隨便一堆爛代碼,然后告訴你,‘是啊,我設(shè)計的目的就是讓他爛,越難越好’,按你的邏輯,這樣也行?”(⊙_⊙),嗯,你要是這樣玩兒我還真沒辦法。但是話又說回來,要讓一堆代碼能跑又還夠“爛”,也還不是一件容易的事,你覺得呢?
總之,我希望大家能明白我的意思:架構(gòu)師開始一個新項目,應(yīng)當(dāng)設(shè)立一個適當(dāng)?shù)脑O(shè)計目標(biāo);然后通過架構(gòu),努力實現(xiàn)其預(yù)定目標(biāo)。如果最終系統(tǒng)的運行,符合其設(shè)計預(yù)期,我們就可以說:這個架構(gòu)不錯還行!反正,架構(gòu)就出了問題。
我們的目標(biāo)
軟件行業(yè)有各種各樣的系統(tǒng),每一種系統(tǒng)的開發(fā)都可能會有不同的目標(biāo)。比如**發(fā)射的系統(tǒng),我們可以想象,目標(biāo)(甚至是基本要求)肯定是:1、穩(wěn)定(絕對不能走火);2、迅速反應(yīng)(不允許按下發(fā)射按鈕后一分鐘**才開始發(fā)射)。你可能覺得這種要求很好啊!任何系統(tǒng)不都是應(yīng)該滿足這樣要求的嗎?比如我在淘寶買T恤,結(jié)果給我發(fā)一條丁字褲,這怎么行?一個網(wǎng)頁半天打不開還有理了?我還真得答一句,它就是有理了。“存在即合理”,這里的合理,合理在成本。我們目前日常使用到的絕大部分軟件,都是有bug的,而且是一堆的bug,但我們?nèi)匀辉谑褂盟鼈儭H绻阆胧褂孟瘛?*發(fā)射”一樣穩(wěn)定精確迅捷的軟件,可能最后的結(jié)果只有一個:你用不起。(請自行腦補)
所以,其實我們是做了一個妥協(xié),“便宜點,將就用吧”。我們?yōu)榱诉_到我們的基本目的,犧牲掉一些“無關(guān)緊要”的東西。對于很多追求卓越的程序員來說,這種犧牲妥協(xié)是難以接受的。“白玉微瑕,你讓我怎么能夠接受?”——但很多時候,你必須接受。這個問題這個觀點,我們會在整個系列中不斷的提及。請試著接受;如果你暫時還不能接受,請牢記:沒有犧牲,就沒有勝利!
那么,我們的策略是:特色突出、整體均衡。說得更直白一點:有亮點,沒硬傷。這就夠了!而我們的亮點就是:可維護性。(注意:不是可擴展,可維護性包含可擴展,但不僅僅是可擴展)
為什么是可維護性
幸或者不幸,我進入軟件行業(yè)之后,絕大部分的工作是幾乎所有程序員都不齒厭惡的維護。我曾經(jīng)維護過一個有十年歷史的、糅合了C、VB、java、C#各種語言在內(nèi)的一個物流系統(tǒng)的部件。我在那家公司工作了一年多,說實話,直到我離職,對整個系統(tǒng),我連邊都沒摸到——這個系統(tǒng)太大了,而且連我們公司都只是其主營公司眾多外包公司中的一個。
在我花了兩周的時間找到一個bug的位置之后,我以為我終于明白了為什么會說:“維護和開發(fā)的花費比是80:20”。但這只是我以為——現(xiàn)實更加殘忍:差不多一個月后,我又花了一個星期的時間,找到了另外一個bug的根源,正是我fix前一個bug所產(chǎn)生的。我淚流滿面,有沒有?腦子里一下就蹦出個詞:“按下了葫蘆浮起了瓢”!總之,如果fix前一個bug就會導(dǎo)致后一個bug;如果fix后一個bug,就會導(dǎo)致前面的bug。我忘了最后是怎么處理這個問題的,依稀記得是讓項目經(jīng)理去和稀泥去了。因為這不是一個很關(guān)鍵很常用的功能,所以最后大概是不了了之吧。
后來我了解到,很多的開發(fā)項目,是這樣一個流程:一群人根據(jù)文檔開始開發(fā),幾個月后通過驗收上線;然后開發(fā)團隊解散,留下一兩個項目組里最菜的菜鳥做“維護”。Game Over!皆大歡喜。這種現(xiàn)象,在各種外包團隊(尤其是以項目計價的廉價外包團隊)中更加的突出(這或許也是大家普遍歧視外包公司的一個原因?)
既然是這樣一種開發(fā)模式,很多開發(fā)人員根本體會不到維護的痛苦。在他們看來,“維護嘛,修修補補,加一兩個if...else而已,讓我們開發(fā)人員做更高大上的工作吧!”但他們也不是總這么幸運,有時候,他們會被弄去“填坑”。據(jù)說最通常的做法,就是在“老坑”周圍再挖一堆“新坑”,填平之前的老坑即可。周而復(fù)始,直到有一天,“受不了啦!我們重寫吧!”——等等,為什么不重構(gòu)?呵呵,好問題,你覺得呢?
很多程序員把這種困境歸咎于“需求變更”。如果不是那些傻逼客戶一天到晚的改需求,我一定會做出一個完美的作品!
或許是因為我是半路出家的原因,和很多程序員相反,我覺得:不是需求變更驅(qū)動著軟件的不斷更改,而是“軟件可以隨意更改”的這種特性刺激了不斷的需求變更。你裝修好的房子,是不是住一段時間之后就會覺得這里那里不合適?這里少了一個插座,陽臺上該加一個龍頭,櫥柜用著不順手……“要是能改改就更好了!”,只是這樣的改動太費力,所以大多數(shù)時間我們都還是算了。但軟件可以!理論上怎么改都可以。想想軟件真的是一種很特殊的商品——它是可以交付“半成品”的。你先用著,如果有問題我再改改,有新需求我再改改,一直可以改到面目全非。沒有在其他傳統(tǒng)行業(yè)里待過的程序員無法理解,“可以隨意更改”是一種多么出色的特質(zhì)。這意味著產(chǎn)品可以自我進化,應(yīng)對各種變化,可以永生!想象這樣一臺“汽車”,開始可以在馬路上跑,過段時間改一下就可以在水里游,再拆裝一下可以當(dāng)摩托拉風(fēng),堵車的時候展開翅膀……這是什么樣一種屌爆天的體驗啊?
所以,“擁抱變化”絕不是一句口號,這是一種胸懷。
作為示例的這兩個系統(tǒng),我是希望能用他們一輩子的。但我甚至無法想象一年之后他們會是什么樣子——他們需要接受市場的檢驗,應(yīng)對技術(shù)的升級換代,會有各種想象不到的變化。所以,可維護性無疑是必須放到首位的。
為了可維護
明確了架構(gòu)的首要目標(biāo),我們就可以做一些基礎(chǔ)的選擇了。比如開發(fā)語言,可是是面向?qū)ο蟮腃#,不需要“性能卓越”的C。
說道“面向?qū)ο蟆保赡苡行┩瑢W(xué)就會比較high,腦子里就會冒出“抽象”、“封裝”、“設(shè)計模式”等各種高大上的東西出來。但我不得不提醒你們:首先,這些都是微觀層面考慮的東西,而架構(gòu)是宏觀的;然后,這些都不是架構(gòu),而是潤滑黏合支持架構(gòu)的東西;最后,在其他條件不變的情況下,系統(tǒng)中這些東西用得越少,說明架構(gòu)越好。
我們以“設(shè)計模式”為例。大家在學(xué)習(xí)設(shè)計模式的過程中有沒有這樣一種困惑,“這樣繼承封裝多態(tài)亂七八糟的繞來繞去的干嘛?”我花了很長一段時間才明白,要理解設(shè)計模式,必須要明白三個字:“不得已”。是迫不得已,才用設(shè)計模式來解決一些特定的問題,而不是說正常的代碼就應(yīng)該這樣寫!這種迫不得已,有很多種原因。個人覺得最容易理解的就是“適配器模式”,因為出現(xiàn)了接口的沖突,所以我們不得不進行適配。但一個很自然的問題就是:為什么不直接改接口讓他們自然融洽呢?這不是一種更自然更直觀的解決方案嗎?答案很有可能就是因為架構(gòu)——大的架構(gòu)已經(jīng)確立,局部必須服從整體。那么,如果一個完全理想化的架構(gòu),是不是根本就不應(yīng)該出現(xiàn)這種問題接口沖突的問題,因而根本就不需要這種設(shè)計模式?
所以,我說設(shè)計模式之類的東西是潤滑劑是黏合劑,他們的作用是彌補架構(gòu)的局部缺陷,更好的支撐架構(gòu)。更極端的一種說法可以送給癡迷于設(shè)計模式的同學(xué):設(shè)計模式是藥,沒病就不要吃藥!
那么,為了可維護性,架構(gòu)中究竟應(yīng)該注意些什么?這是一個很大的話題,開篇我們只說一點。
模塊有大有小,大可以是一個分層一個項目,小可以是一個方法一個類。我們通常的做法是由大到小,逐步細分。
模塊的劃分是相當(dāng)?shù)目简灱軜?gòu)能力的。良好的模塊劃分,能夠讓我們方便的安排人手、合理的組織項目進度、迅速的定位代碼……各種好處說都說不完。所以還是說說不好的模塊劃分有什么問題更容易一些,嗯,這個好像根本就不要說,想想你在一堆亂七八糟的代碼里不斷的F11的情形吧!
我個人認為,模塊劃分的難度在于“整齊”和“靈活”之間取舍。通常來說,大的模塊我們都是“一刀切”,著重強調(diào)的是“整齊”,比如口熟能詳?shù)腢I層、BLL層和DAL層,但這種“一刀切”的做法,更多的是一種無奈。我們的人類的思維局限決定了我們在考慮復(fù)雜問題時無法深入到每一個細節(jié),所以只能先“大而化之”的把一個復(fù)雜問題先進行簡單化。這樣帶來的一個嚴重的副作用就是,限制了代碼的靈活性;而靈活性,正是應(yīng)對復(fù)雜變化的有效武器。所以,在更小一些的模塊(比如說:類)里,我們引入了豐富多彩的抽象繼承設(shè)計模式等一系列充滿各種靈活性的機制,以彌合“一刀切”造成的問題。這一松一緊一張一弛中“度”的掌握,就只能說是一種藝術(shù)了。
模塊劃分,籠統(tǒng)的說教用處不大,我們將在后面的文章中結(jié)合具體情況逐一說明。但我希望大家能夠明白:模塊劃分是必須的——這種必須,是一種無可奈何的選擇。所以,喜歡從頁面直接寫sql到數(shù)據(jù)庫的同學(xué),老大讓你把你的代碼拆成幾段放到不同地方的時候,不要嫌麻煩;喜歡把一個簡單項目切成七層的同學(xué),先仔細想不想這樣做是不是真的有必要。
為了代碼能夠長期有效的維護,我們還需要做很多工作,比如良好的文檔、完善的項目管理流程。但我想說的,還是不是這個,而是代碼之外的因素對項目架構(gòu)的影響。比如開發(fā)團隊的背景能力偏好,一群C#程序員,你一定要整個node.js,這純粹是給自己找不痛快。除了這些稍稍用腦袋想一想就能明白的東西,有一件事,很多程序員并沒有意識到。
架構(gòu)的一個天然目的就是:讓代碼更智能讓程序員更傻瓜。換一張說法就是,架構(gòu)要“創(chuàng)造便利,讓程序員更關(guān)注業(yè)務(wù)”。
這可能是一個讓程序員感到悲哀的事實。正如機械師不停的發(fā)明,讓機器變得越來越聰明,取代流水線上的工人,最終取代了他們自己。從某種意義上說,我們都是自掘墳?zāi)沟娜恕R粋€良好的架構(gòu),就應(yīng)該是讓每一個普通開發(fā)人員,都是一個個盡量廉價隨時可以替換的螺絲釘,這樣才能保證系統(tǒng)永遠健康正常的運行下去。告訴你這個事實可能讓你一整天都不開心,但接受這個事實之后能幫助你在工作中變得更加的“心平氣和”。螺絲釘就要有螺絲釘?shù)挠X悟;更何況,當(dāng)好一顆螺絲釘也不是一件很容易的事。
(未完待續(xù))
架構(gòu)設(shè)計 項目管理
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。