我的朋友們,如果你在工作中需要每週至少兩次搬動比筆記本更重工具,可以在聊天中這樣來吐槽:“夥計[1],你工作太不努力了。剛過去的一週我工作了4700小時,用螺絲刀在魔多[2]下面挖了一條隧道呢。”
他們說的沒錯。魔多的確令人討厭,而且很顯然挖隧道也比撥弄鍵盤更耗費體力,除非你是一隻螞蟻。但是出於討論的目的,我們是否能認同壓力和瘋狂是壞事呢?嘿,歡迎來到程式設計的世界。
所有的程式設計團隊都是由瘋子組成的
想象你加入了一個工程團隊。你可能剛離開學校踏入社會,還未受塵世的侵染,心中滿腔熱血,創意層出不窮。那些優雅的設計以及他們對於目標、經濟和力量在美學上的協調統一令你振奮不已。
一切從會見Mary開始,她是大都市中一個橋樑專案的主管。Mary又將你介紹給Fred,你需要通過Dave部署的15項安全檢查,因為Dave的毛衣在他的桌上被偷走了一次,顯然不會再發生了。Fred只和木頭打交道,於是你很好奇他為什麼也參與進來了,因為這座大橋需要在高峰期承受裝滿人類的車輛從上面通過,而腳下200英尺便是湍急的河流。Mary表示無須擔心,Fred是來處理人行道的。啥人行道?好吧,Fred已經提交了一份優秀的人行道方案,並且他們準備將其新增到橋樑建造申請中。毫無疑問,他們是無法為人行道安裝護欄的,因為被迫遵循一個嚴格的無護欄原則,這是Phil提出的,然而他並不是工程師。沒有人清楚Phil到底是幹什麼的,但肯定全是和上層管理者協調應酬之類的活。任何一個工程師都不願意去對付那些人,於是就由著Phil吧。同時,Sara發現了幾個“最尖端”[3]的鋪路技術,並且全部加到了大橋的設計中。
這也就意味著在整個工程進展中,需要為每一個技術單獨建設實施,因為不同的技術意味著不同的底層支援和安全考量。Tom和Harry一起共事了多年,但是他們關於使用公制還是英制測量單位的爭論卻如夙怨一般從未停止,最後發展到“誰先拿到這部分的設計就以誰為準”的地步。這可令那些整合施工的人萬分頭痛,於是他們放棄了。無論實施、錘鍊還是焊接,都只按各自手頭處理的部分進行,以勉強應對。另外,這座橋被設計為一座懸索橋,然而並沒有人知道到底如何建造懸索橋。因此工程進行到一半時,他們為其增加了額外的立柱來保證穩定性。但是還剩下懸索沒有處理,它們依然是橋樑的一部分。可惜所有人都不知道到底該屬於哪個元件,有一點是每個人都十分認同的:它們一定很重要。在入職介紹結束後,你被邀請發表一些新想法,可你一個點子都沒有,因為你對橋樑一竅不通,你只是一個發動機工程師。
你敢駕車駛過這座大橋嗎?我想不會。如果它真建造出來了,每個參與的人都會被處決的。這個故事的某些版本其實描繪了你用過的每個程式,銀行軟體、網站以及網際網路上一個無所不在的程式,它號稱能保護個人資訊,然而沒有做到[4]。
所有的程式碼都很爛
獨自在家時,每個程式設計師都偶爾會關掉刺眼的日光燈,小酌一杯蘇格蘭威士忌,放上幾曲輕快的德國電子樂,然後開啟電腦中的一份檔案。對於每個程式設計師,都會有不一樣的檔案。他們有時編寫,有時找尋並儲存。他們對其字斟句酌,又為其美麗而落淚。但是淚水隨即會變得苦澀,因為他們想到了那些漂泊在外的檔案,想到這世界上的美好和真實終將不可避免地土崩瓦解。
這個檔案中的程式碼是優雅的。它有著易讀並且一致的函式和變數命名。它非常簡潔。它沒有包含任何明顯的愚蠢語句。它從來沒有被放逐野外,也無須應對銷售團隊。它完成了單一的工作,並且做得非常漂亮。它僅僅由一個人編寫,從未被他人染指。它讀起來像一篇而立之年的人撰寫的詩歌。
每個程式設計師一開始都創造著這樣完美的六邊形小雪花。然後週五時他們被告知下週二之前需要再完成六百片,於是他們在這兒和那兒投機取巧。比如複製一點雪花,和另外一些粘起來,或者叫一個同事來處理那些他融化的雪花。結果所有程式設計師的程式碼都被傾倒在一起,變成難以捉摸的形狀。這時會有人拿一副畢加索的畫擋在前面,因為沒人願意看著溼漉漉的貓尿灑到你那破碎的雪花上,在日光之下慢慢融化。下週,每個人都會剷起更多的雪堆到上面,以防“畢加索”轟然倒塌。
有一個理論這麼說,你可以通過遵循標準來治癒上述病症,如果“標準”的數量比計算機實際能處理的還要多,就無能為力了。這些標準全都在以各種方式改進著,或者惡化著,僅僅依賴編碼者的個人喜好。因此現實中沒有哪段程式碼能滿足這些標準,除非能夠以一些極其不同的方式做到一些完全相同的事情[5]。即使你對每種涉及到的語言、框架和標準都十分熟悉,任何工作最初的幾周,都要耗費在弄清楚一個程式是如何運作的,因為標準是獨角獸[6]。
前方總有黑暗
我成長的那幾年,臥室中有一個衣櫥,它有著古怪的設計。乍看之下衣櫥很普通,當你走進去想要拿取衣物時,發現右邊的牆上有個凹槽,能做成方便的小擱板。然後你向上看,凹處的背後卻讓出一條路,通向了徹底虛無的絕命空間。沒有光線可以抵達那裡,你也立刻分辨出它們正是那些夜幕降臨時只能依靠手電筒和毛絨玩具與之保持距離的飢餓的怪獸。
這其實就是學習程式設計的過程。你開始接觸一些有用的工具,接著環顧四周,又發現一些更順手的新工具,而在它們卻展現了那些始終徘徊在你噩夢中的無盡的恐懼。
舉例來說,假設你是一個水平一般的web開發者。你熟悉一打程式語言、大量的類庫、標準、協議。你依然需要每週學習更多,並且有數百項檢查要做來檢視它們是否被更新或者已經失效,以保證它們整合到一起還能正常工作。還有某個週末你喝醉後飄飄然想出利用漏洞的壞點子,不知道是否有人已經修復了這個bug。現在你和你的程式碼們都已經處於最新狀態,真是厲害,接著一切都弄砸了。
“什麼鬼!”你吼了出來,隨後開始追查問題。你發現有一天,有個白痴因為另一個白痴定義了1/0等於無窮大,而直接使用1/0作為無窮大的簡寫放到程式碼中。這時一個不那麼白痴的人認定這是一個白痴的行為,其實最初的白痴就應該這麼認定了,可惜他沒有這麼做。因此這個不那麼白痴的人決定做一個混蛋,把直接使用1/0的行為作為錯誤新增到他的編譯器中。並且他不打算告訴任何人這件事,因為他已經是混蛋了。於是你所有的雪花都被尿了一遍,甚至還找不到那隻可惡的貓。
你在這些技術上都可以稱得上是專家,這是件了不起的事。依靠豐富的經驗,你只花了6個小時就找到出錯的地方,如果不是這樣,可能就被離職了。現在又多了一條真理需要收藏進你那已經銘記了百萬條事實的腦袋中,因為太多你依賴的程式都是由混蛋和白痴編寫的。
這僅僅是在你所選擇的領域中發生的事,只能代表電腦科學中所有知識的很小一部分,其中可能有些你都完全沒接觸過。沒有任何一個人能說清楚你那臺服役了5年的MacBook中每件事是如何完成的。為什麼我要你重啟試試?[7]因為我們對於哪裡出錯了連一丁點線索都沒有,而且讓計算機陷入崩潰實在太容易,所以不如讓系統內建的自動化醫生幫我們找出問題所在。程式設計師的電腦比其他人的工作得更好的原因只有一個:他們知道計算機其實是患有精神分裂症和自體免疫性疾病的小孩,當它不好好工作時,不會以棍棒相見。
網際網路完成了太多事,卻使它成為了自身的煉獄
還記得有關瘋子和爛程式碼的故事嗎?網際網路也是這樣,只不過它還要糟糕無數倍。那些美化過的購物網站,可能由兩三個動態頁面組成,實際上背後有一個團隊正不分晝夜地維護著。因為殘酷的真相是這個網站每時每刻都會冒出新問題,在每段程式碼中都是,對於每個使用者都是。就在此刻,某個Facebook的工程師被淹沒在成千上萬的錯誤資訊中,他拼了老命追查問題所在,否則精心偽裝的外表可能就此崩塌。目光轉到Google的辦公室,有個團隊已經三天沒閤眼了。某處一位資料庫程式設計師,已經被堆積如山的激浪[8]空瓶包圍,她的丈夫心想她大概已經死了。如果這群人停止工作,那可是世界性的災難。大多數人甚至不瞭解到底系統管理員(sysadmin)是做什麼的,但是相信我,如果他們所有人都同時午休,即使你為了保護自己的罐頭不被變種人[9]的巡迴樂隊搶走而打光所有子彈,他們也沒空去熟食店買一份速食午餐。
你無法重啟網際網路。數萬億美元依賴著如搖搖欲墜的蜘蛛網般的非正式協議,還有那些“目前這樣就行了”[10]的程式碼,其中你可以找到十年前新增的一句註釋:“TODO: 修改這裡實在太危險,但是我也不知道哪兒出錯了”。我甚至還沒提及那些攻擊網際網路各個部分的黑客軍團,有的是間諜活動,有的為了贏利,還有的只是單純無聊而已。聽說過4chan嗎?4chan可能毀了你的生活和工作,僅僅因為某天下午他們決定不再喜歡你了。但我們對此從不擔心,已經進入核冬天了,再多一個核武器也沒什麼大不了的。[11]
在網際網路上,這麼說是沒有問題的:“你知道,只要你用了合適的技術,在某些時候,某些事情能良好地運作。”隨後,BAM!網際網路就成了現在這個樣子。任何懷揣幾百美元並且擁有一臺電腦的人,都可以搶佔網際網路中的一小塊地盤,肆意上傳那些糟糕的程式碼片段,然後將一條條支流匯入網際網路的幹流,於是這鍋粥中又多了一顆老鼠屎。即使是好程式設計師,也懶得去學習那些晦澀難懂的說明文件,而這正是一些組織用於建立標準而創造的獨角獸。因此人們花費一半的時間重複著毫無意義並且隨時可能崩壞的程式碼,而我們只是努力掩蓋這樣的事實,祈禱不被發現。
網際網路上有這樣一個祕密:在你第一次開啟瀏覽器的5分鐘之後,俄羅斯的小孩就獲取了你的社會安全號[12]。你是否已經在某個網站註冊了?那麼NSA現在開始就能自動追蹤你的地理位置,直到你生命的盡頭。你是否傳送了一封電子郵件?那麼你的郵件地址馬上會出現在奈及利亞的某個廣告牌上。
這些事情並不真切,因為我們從不關心,也不會試圖阻止,而它們又是真實發生的,因為每件事都在出錯,因為所有的程式碼都很爛並且每個人都僅僅只想維持它的運轉。如果你在網際網路上工作,將會有這樣的經歷:祈求你寫下的最後一段程式碼足夠好,才能偷得幾小時的空閒,來享受一頓安心的晚餐或者躺下小憩片刻。
我們並不想瘋,都是被逼的
1 |
ERROR: Attempted to parse HTML with regular expression; system returned Cthulhu. |
[13]很可笑是嗎?不是嗎?如果換成下面這樣:
1 2 3 |
"Is that called arrayReverse?" "s/camel/_/" "Cool thanks." |
[14]這哥們幫上忙了嗎?靠駱駝?這看起來是一個合適的回答嗎?不是吧?很好,你至少還知道耶穌在哪[15]。你還沒有花費過多的生命在閱讀程式碼上,以至於說話都變成了程式碼。人類的大腦並沒有特別善於應對基本邏輯,但是現在有一個工種除了處理犬牙交錯的邏輯,什麼也不幹。大量抽象的條件鏈和語法要求都需要仔細檢查,確保沒有放過遺漏逗號這種錯誤。沒日沒夜地做類似的事情使你處於一個精神失語的狀態,當你盯著別人,都無法分辨他是否已經說完了一句話,因為他臉上並沒有打出分號。你沉浸在這樣一個無意義的世界裡,唯一重要的事是一串數字飄入由符號和另一串數字組成的巨大迷宮,或許從另一端冒出來的是張貓咪的圖片。
人們創造的程式語言已經展現了一種對大腦毀滅性的衝擊。下面是一個程式:
1 2 3 4 5 6 |
#include <iostream> int main( int argc, char** argv ) { std::cout << "Hello World!" << std::endl; return 0; } |
上面的程式和下面這個做了完全相同的事情[16]:
1 |
`r```````````.H.e.l.l.o. .w.o.r.l.di |
還有這段程式[17]:
1 2 3 |
>+++++++++[<++++++++>-]<.>+++++++[<++++>-]<+.+++++++..+++.[-] >++++++++[<++++>-] <.>+++++++++++[<++++++++>-]<-.--------.+++ .------.--------.[-]>++++++++[<++++>- ]<+.[-]++++++++++. |
還有這個[18]:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook? Ook! Ook! Ook? Ook! Ook? Ook. Ook! Ook. Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook? Ook! Ook! Ook? Ook! Ook? Ook. Ook. Ook. Ook! Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook. Ook! Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook. Ook. Ook? Ook. Ook? Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook? Ook! Ook! Ook? Ook! Ook? Ook. Ook! Ook. Ook. Ook? Ook. Ook? Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook? Ook! Ook! Ook? Ook! Ook? Ook. Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook. Ook? Ook. Ook? Ook. Ook? Ook. Ook? Ook. Ook! Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook. Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook. Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook. Ook. Ook? Ook. Ook? Ook. Ook. Ook! Ook. Ook! Ook? Ook! Ook! Ook? Ook! Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook. |
結果某天有人創造了一門程式語言,最終讓程式設計師寫出了這樣的程式碼[19]:
1 2 3 4 |
#:: ::-| ::-| .-. :||-:: 0-| .-| ::||-| .:|-. :|| open(Q,$0);while(){if(/^#(.*)$/){for(split('-',$1)){$q=0;for(split){s/| /:.:/xg;s/:/../g;$Q=$_?length:$_;$q+=$q?$Q:$Q*20;}print chr($q);}}}print"n"; #.: ::||-| .||-| :|||-| ::||-| ||-:: :|||-| .:| |
根據作者的意思,這個程式的作用是:用兩行程式碼解析了上下兩行註釋,讀取其中的瑪雅數字,轉換為ACSII用於組成雜誌的標題,並且渲染出旋轉90度的ASCII藝術字。
此程式獲得了程式設計比賽的冠軍,毫無疑問它做到了。你願意生活在這樣的世界之中嗎?不。這是一個你每天抽掉一盒煙,也不會有人來詢問原因的世界。”他當然每天一盒煙,誰不是呢?“最後每個程式設計師在睡夢結束睜開眼,又完全清醒之前,他們發現整個世界和其中每一份感情都變成了程式碼片段。他們彼此交換著生活的故事,彷彿開啟一天艱辛旅程的睏倦已經稀鬆平常。這是一個避性不談的世界,他們更願意為猩猩編寫一門語言。所有的程式設計師都強迫他們的大腦做著一些本不該做,也無法做得更好的事情,每天10到15小時,每週5到7天,他們中的每一員都正緩緩墜入瘋狂的深淵。
1 |
</rant> |
[20]的確,我不需要具備舉起50磅重物件的能力。而是以此換來了一個機會:在撒旦離開我大敞的顱骨出來就餐時,精心修剪他的毛髮,確保網際網路中的一小段程式碼能夠繼續工作幾天。
- 他們總是要以”夥計“開頭 ↩
- 譯註:指環王中黑魔王索倫管轄的區域 ↩
- 譯註:hemorrhaging-edge,直譯出血邊緣,形容過於前沿而伴有高風險的事物 ↩
- 譯註:記得OpenSSL的故事嗎? ↩
- 譯註:此句中作者可能打掉了一個
in
,有興趣的可以參看原文 ↩ - 譯註:西方神話中獨角獸難於馴服。舊約·約伯記中也有類似描述:
Will the unicorn be willing to serve thee, or abide by thy crib?
↩ - 譯註:
turn it off and on again
出自英劇 – IT狂人 ↩ - 譯註:Mountain Dew,一種功能飲料 ↩
- 譯註:電影Mutants中人類感染病毒變成的殭屍 ↩
- 譯註:2012年Hacker News上一個很火爆的討論 –
There's no shame in code that is simply "good enough"
↩ - 譯註:4chan中有很多極端分子,熱衷於核武器 ↩
- 譯註:類似國內的身份證號 ↩
- 譯註:Cthulhu是克蘇魯神話中的邪神 ↩
- 譯註:sed或者perl中的替換,意為將駝峰寫法換成下劃線 ↩
- 譯註:形容你還沒迷失自己 ↩
- 譯註:Unlambda語言 ↩
- 譯註:Brainfuck語言 ↩
- 譯註:Ook!語言 ↩
- 譯註:這程式碼是The Fifth Obfuscated Perl Contest中,The Old Standby類別的冠軍 ↩
- 譯註:結尾的咆哮,作者已經沉迷了 ↩