談一談我在軟件開(kāi)發(fā)中的最佳實(shí)踐
“描述一個(gè)事物,唯有一個(gè)名詞定義它的概念,唯有一個(gè)動(dòng)詞揭露它的行為,唯有一個(gè)形容詞表現(xiàn)它的特征。要做的,就是用心去尋找那個(gè)名詞、那個(gè)動(dòng)詞、那個(gè)形容詞……”
——?福樓拜 (Gustave Flaubert)
我想講個(gè)故事。
很久很久以前(一般講故事都是這樣開(kāi)頭吧), 兩個(gè)老工程師在一起聊天,談各自生涯中最自豪的工程。其中一個(gè)先講述了他的杰作:
“?我們建造的橋,橫跨一個(gè)峽谷,峽谷很寬很深。我們花了兩年時(shí)間研究地質(zhì),選擇材料。聘請(qǐng)了最好的工程師團(tuán)隊(duì)來(lái)設(shè)計(jì)方案,而這又花了五年時(shí)間。?我們簽下了最大的工程隊(duì),委托他們建造基礎(chǔ)結(jié)構(gòu)、塔墩、收費(fèi)亭,以及用于連接橋梁和高速公路的道路。橋面下層是鐵路,我們甚至還修了自行車(chē)道。?那座橋花費(fèi)了我數(shù)年的心血?!?/p>
另外一個(gè)聽(tīng)完之后,陷入了沉思,過(guò)了一會(huì)兒,說(shuō)到:
“?有一天晚上,我和一個(gè)朋友喝了點(diǎn)伏特加,然后我倆扔了一根繩子,越過(guò)一個(gè)河谷。呃…… 就是一根繩子,兩頭系在兩顆樹(shù)上。?河谷兩邊各有一個(gè)村莊,起初,有人加了個(gè)滑輪,用來(lái)傳遞包裹。然后,有人拉起了第二根繩子,勉強(qiáng)可以走走,雖然很危險(xiǎn),但小伙子們很喜歡。?后來(lái),一群人重新修建了一下,使得更牢固。于是,女人們也開(kāi)始從上面走,每天帶著她們的農(nóng)產(chǎn)品過(guò)橋。?就這樣,在橋的另一邊形成了一個(gè)市場(chǎng)。因?yàn)榈胤介_(kāi)闊,造了很多房子,慢慢地發(fā)展成了一個(gè)鎮(zhèn)子。?繩索橋被木橋替代,這樣就可以走馬車(chē)了。?后來(lái),鎮(zhèn)上的人們修了一座真正的石橋。再然后,人們又把石料改成了鋼材。?如今,那座鋼構(gòu)懸索橋依然佇立在那里。”
前一個(gè)工程師沉默良久,說(shuō)到:“ 有意思。我那座橋建成大約十年后,被拆除了。事實(shí)證明我們選錯(cuò)了地點(diǎn),建好的橋沒(méi)人用。據(jù)說(shuō)有幾個(gè)野路子的家伙,在下游幾英里處,拉了一根繩子,所有人都從那走?!?/p>
金門(mén)大橋(舊金山)
我很喜歡這個(gè)故事。故事的出處,在一款消息隊(duì)列產(chǎn)品——?ZeroMQ?的官方指南第6章里。
說(shuō)完故事,我想聊聊軟件開(kāi)發(fā)中,常??梢月?tīng)到的一個(gè)概念 ——?Best Practice?:最佳實(shí)踐。Wikipedia 上對(duì)其解釋為:
A best practice is a method or technique that has been generally accepted as superior to any alternatives because it produces results that are superior to those achieved by other means or because it has become a standard way of doing things.
(最佳實(shí)踐是一種:因其產(chǎn)生的結(jié)果優(yōu)于其它選擇下的結(jié)果,或其已經(jīng)成為一種做事的標(biāo)準(zhǔn),從而被普遍認(rèn)可優(yōu)于任何替代方案的方法或技術(shù)。)
這個(gè)概念源于管理學(xué),然后在 IT 界泛濫。簡(jiǎn)而言之,就是所謂“正確的做法”。
最佳實(shí)踐本身是美好的存在,猶如夜空中的一輪明月,照亮黑暗中的方向,指引著摸索前行的凡人。
但凡事有度,子曰:“過(guò)猶不及?!?/p>
我今天想說(shuō)的,就是這月亮的背面。(傳說(shuō)中,月球背面隱藏著…… 噓~)
潮汐鎖定導(dǎo)致月球永遠(yuǎn)以同一面朝向地球
首先,最佳實(shí)踐容易帶來(lái)思想包袱,讓人無(wú)法專注于解決問(wèn)題本身。
總是希望采用最好的技術(shù)方法,不愿意在不正確的做法上浪費(fèi)時(shí)間,導(dǎo)致瞻前顧后,甚至裹足不前。此時(shí)的最佳實(shí)踐,已然成為了一種毒藥,一旦偏離了問(wèn)題本身這個(gè)出發(fā)點(diǎn),就會(huì)不知不覺(jué)走進(jìn)“宏大構(gòu)想”的思維陷阱。把簡(jiǎn)單的問(wèn)題復(fù)雜化,阻礙了邁出第一步,直到能規(guī)劃出“包羅萬(wàn)象”的解決方案后才肯動(dòng)手,拖延癥就這樣來(lái)了,時(shí)間卻走了。
你想好了未來(lái)每一天怎么過(guò)嗎…… 沒(méi)想好? 那……不活了?
其次,對(duì)最佳實(shí)踐的執(zhí)念容易讓人鉆牛角尖,將目標(biāo)的重心帶偏。
過(guò)度關(guān)注實(shí)施過(guò)程是否符合標(biāo)準(zhǔn)化,忽視了項(xiàng)目中其它重要的東西,比如用戶體驗(yàn),比如實(shí)際需求。就像故事里講的那樣:第一座大橋,幾乎是教科書(shū)般的標(biāo)準(zhǔn)化路數(shù),可產(chǎn)品落地后和客戶需求卻差了好幾英里;第二個(gè)看上去很野路子,但精準(zhǔn)地解決了痛點(diǎn),從始自終都是緊緊圍繞實(shí)際需求迭代,每一次的進(jìn)步都可以產(chǎn)生效用,這才叫殺手級(jí)應(yīng)用。
這讓我想起了?Plan-9?的傳說(shuō)。
你聽(tīng)說(shuō)過(guò) Plan-9 OS 嗎? 一款由貝爾實(shí)驗(yàn)室的極客們打造的用于完善 UNIX 不足的操作系統(tǒng)。什么不足?在 UNIX 的哲學(xué)中,有一條叫做 “一切皆文件” ,但實(shí)際上UNIX本身并沒(méi)有嚴(yán)格遵從這一條。于是,Plan-9 OS 完美實(shí)現(xiàn)了這一點(diǎn)。然后呢……? 沒(méi)有然后了。它從沒(méi)進(jìn)過(guò)市場(chǎng),所以如果你沒(méi)聽(tīng)說(shuō)過(guò)它,一點(diǎn)也不奇怪。Plan-9 OS 沒(méi)有解決任何現(xiàn)實(shí)問(wèn)題,沒(méi)人在乎 “一切皆不皆文件”。
這種執(zhí)念的另一種表現(xiàn)就是工程師思維,沉迷于奇技淫巧中無(wú)法自拔,程序員尤其容易中招。
比如性能優(yōu)化。“優(yōu)秀的程序員應(yīng)該榨干每一字節(jié)內(nèi)存”,聽(tīng)起來(lái)很熟悉,不是嗎?但經(jīng)濟(jì)學(xué)上來(lái)講,邊際效應(yīng)決定了一次項(xiàng)目中,越優(yōu)化性價(jià)比越低。有一個(gè)很容易被忽略的事實(shí):硬件其實(shí)比程序員要便宜。
再比如對(duì)設(shè)計(jì)模式的崇拜。設(shè)計(jì)模式當(dāng)然是好東西,但如果像強(qiáng)迫癥一樣使用它們,堅(jiān)持用上它們才是正確的編程,就會(huì)導(dǎo)致按圖索驥,強(qiáng)行讓問(wèn)題去適應(yīng)設(shè)計(jì)模式,而不是讓解決方案針對(duì)問(wèn)題,這就本末倒置了。
我有個(gè)基友,C++ 極客。畢業(yè)后入了騰訊,積累了巨額財(cái)富后,自己創(chuàng)業(yè)了。當(dāng)然,當(dāng)老板可比寫(xiě) C++ 難多了,于是現(xiàn)在又去積累巨額財(cái)富了。想當(dāng)年和那廝聊天,言必出設(shè)計(jì)模式,沒(méi)事侃正則,再?zèng)]事就研究 GC 策略 (好像玩 C++ 的普遍這德性) 。前不久看他代碼,差點(diǎn)沒(méi)認(rèn)出來(lái),這家伙畫(huà)風(fēng)一轉(zhuǎn),現(xiàn)在連接口都懶得多用(估計(jì)看到這,某些狂熱分子肯定在破口大罵:你什么意思,你說(shuō)你沒(méi)用面向接口編程?)那位兄臺(tái)甚至都懶得多聊,輕描淡寫(xiě)來(lái)一句,“沒(méi)心思,以后有需要再加。”
順便扯一句,那哥們最近負(fù)責(zé)開(kāi)發(fā)一款手游,他跟老板匯報(bào)的時(shí)候,預(yù)估的研發(fā)周期要12個(gè)月,然后老板跟他說(shuō):“好,12月出公測(cè)。” (哈~ 估計(jì)他肯定舌頭打結(jié)把“12個(gè)月”說(shuō)成了“12月”)??吹竭@的你,是否回憶起了你的老板?
這也是我接下來(lái)想說(shuō)的關(guān)于最佳實(shí)踐的另一個(gè)問(wèn)題:項(xiàng)目實(shí)施。
工作數(shù)年,大小項(xiàng)目經(jīng)歷若干,慢慢體會(huì)到,一個(gè)項(xiàng)目的開(kāi)發(fā)順利與否,并不在于技術(shù)選型是否為最佳實(shí)踐,更多的時(shí)候,取決于開(kāi)發(fā)方案和技術(shù)儲(chǔ)備之間的平衡。做項(xiàng)目畢竟是要講方案落地的,如果最佳實(shí)踐中的技術(shù)成本,超出了開(kāi)發(fā)者的落實(shí)能力,那就是坑,這時(shí)盲從最佳實(shí)踐無(wú)異于挖墳。如果是一個(gè)人的項(xiàng)目,抽時(shí)間惡補(bǔ)一通,興許能填填坑,這取決于IQ。但要是一個(gè)團(tuán)隊(duì),那就不是什么 IQ,EQ,QQ 的問(wèn)題了,這中間產(chǎn)生的學(xué)習(xí)成本,集體培訓(xùn)成本,反復(fù)溝通成本,大量的初級(jí)錯(cuò)誤,千奇百怪的代碼,互相沖突引發(fā)的焦躁情緒,等等。這些負(fù)面的東西如果不能妥善的處理,足以抵消掉最佳實(shí)踐帶來(lái)的好處。別忘了,deadline 正在迫近。
我自己曾經(jīng)在一個(gè)項(xiàng)目組里,強(qiáng)行推行?Git?做源代碼管理,當(dāng)時(shí)組里共9人,有7人只會(huì) SVN,但我堅(jiān)持 Git 是 “最佳實(shí)踐”。要不說(shuō)年少無(wú)知少不更事呢,罷了,后來(lái)的事情我不想回憶了…… 那次項(xiàng)目之后,我再也不在一群只會(huì) SVN 的隊(duì)伍里提 Git 了。
一個(gè)人做軟件已經(jīng)很難,比這更難的,是一群人做軟件。
當(dāng)塵埃落定,驀然回首,最佳實(shí)踐很可能沒(méi)你想象中那么重要。它更多的是一種精神層面的求道,并非物質(zhì)世界的必要。
扎克伯格 ( Mark Zuckerberg ) 于2004年在哈佛柯克蘭公寓 ( Kirkland House ) 里寫(xiě)出?TheFacebook?的時(shí)候 ( 次年更名為Facebook ) ,用的是 “世界上最好的編程語(yǔ)言” PHP。這門(mén)可能是業(yè)界被吐槽次數(shù)最多的語(yǔ)言一直支撐著FB帝國(guó)的誕生,直到席卷全球。Stack Overflow?的聯(lián)合創(chuàng)始人 Jeff Atwood 曾公開(kāi)揶揄 Facebook 是一家 “召集全球頂級(jí)程序員在 Windows XP 上寫(xiě) PHP ” 的公司。但這無(wú)所謂,24年前的馬克也不糾結(jié)。一直等到需要的時(shí)候 (2010年),F(xiàn)acebook自己動(dòng)手研發(fā)了一個(gè)編程語(yǔ)言 —— Hack,來(lái)解決 PHP 帶來(lái)的危機(jī)。
《社交網(wǎng)絡(luò)》
最佳實(shí)踐,關(guān)鍵在時(shí)機(jī)(Timing)。
如果說(shuō)用 Facebook 這個(gè) “根本不存在” 的網(wǎng)站來(lái)舉例,純屬虛構(gòu)的話,那我們來(lái)說(shuō)點(diǎn)真實(shí)的例子,Web 技術(shù)的基石——HTML。由20世紀(jì)最重要的100人之一的?Tim Berners-Lee?創(chuàng)造的 HTML,其發(fā)明之偉大,足以單獨(dú)開(kāi)篇博文來(lái)贊美了,這里就不贅述了。
這樣一個(gè)造福全人類的神作,本身的設(shè)計(jì)結(jié)構(gòu)絕非完美,甚至可以用混亂不堪來(lái)形容。沒(méi)有嚴(yán)格統(tǒng)一的約束,形同虛設(shè)的規(guī)范,標(biāo)準(zhǔn)化進(jìn)程的難產(chǎn)。以至于在很長(zhǎng)一段時(shí)間內(nèi),連自身元素的定義,都可以向?yàn)g覽器廠商妥協(xié)。但是,種種被人詬病的存在,絲毫不影響 HTML 改變世界的腳步。你我今天能相會(huì)于園,皆仰賴它的誕生。
同樣的例子還發(fā)生在 Web 世界另一個(gè)巨擎上——JavaScript。當(dāng)今世界,Web 前端技術(shù)已經(jīng)水銀瀉地般肆虐整個(gè)開(kāi)發(fā)界,前端框架百花齊放、JS 衍生品鱗次櫛比。所有這一切的背后,全都源于上世紀(jì)90年代橫空出世的 JavaScript。
那么,JavaScript是最佳實(shí)踐嗎?
別逗了,如果有什么語(yǔ)言可以和剛才說(shuō)到的 PHP 競(jìng)爭(zhēng)一下誰(shuí)被罵的次數(shù)更多,那非 JavaScript 莫屬。這個(gè)僅花了十天設(shè)計(jì)出來(lái)的語(yǔ)言,打一出身就被貼上了怪胎的標(biāo)簽。混亂的標(biāo)準(zhǔn),多樣的實(shí)現(xiàn),安全漏洞,語(yǔ)法隨意,反人類……?總之,JavaScript 和最佳實(shí)踐半毛錢(qián)關(guān)系都扯不上,但它卻是撐起當(dāng)今互聯(lián)網(wǎng)半壁江山的擎天柱。
所以,用最接地氣地話來(lái)說(shuō),不管黑貓白貓,逮著耗子就是最佳實(shí)踐貓。
彼之蜜糖,吾之砒霜。所謂最佳實(shí)踐,其定義本身往往也是分歧的源頭。什么是最佳?這個(gè)最佳是獨(dú)一無(wú)二的嗎?世界上有很多很多現(xiàn)實(shí)問(wèn)題,可能根本就沒(méi)有所謂的最佳實(shí)踐。
請(qǐng)聽(tīng)題,世界上最好的編程語(yǔ)言是哪個(gè)?
第二題,世界上最好的文本編輯器是哪個(gè)?
朋友,這天還聊得下去嗎……
最后,說(shuō)一個(gè)我自己的故事。
很久很久以前,為了找一款滿意的文本編輯器,我干了一件可能是前無(wú)古人,后不知道有沒(méi)有來(lái)者的蠢事 —— 我打開(kāi) Wikipedia,搜索 “ text editor ” ,然后轉(zhuǎn)到一個(gè)叫做 “ List of text editors ” 的頁(yè)面,接下來(lái)的一個(gè)月,我?guī)缀醢旬?dāng)時(shí)那個(gè)頁(yè)面上,所有我能下載安裝的文本編輯器,全部試用了一遍……
嗯?你問(wèn)我為什么這么做?呵呵,不把全世界的文本編輯器遍歷一遍,我怎么知道哪個(gè)是最好的?
這事細(xì)節(jié)我不想再提了,我也不想回憶了。要不說(shuō)年少無(wú)知少不更事呢,時(shí)至今日,我想不出比這更愚蠢的事了。WTF~~
這個(gè)頁(yè)面上的表格行數(shù)逐年增多
如今,再有人問(wèn)我最好的編程語(yǔ)言或者最好的文本編輯器的問(wèn)題的話,我會(huì)說(shuō):
“朋友,要打架嗎?”
這兩個(gè)問(wèn)題的最佳實(shí)踐,唯有暴力。