OOP代碼的格局,是和別的編程模式不同的:首先要有一個(gè)構(gòu)造函數(shù);基類里只定義了函數(shù)的形式,可以隨時(shí)通過派生增加不同的實(shí)現(xiàn)。那些程序員們,每每學(xué)會(huì)了繼承和多態(tài),便可以接一個(gè)項(xiàng)目,——這是十年前的事,現(xiàn)在至少要懂得設(shè)計(jì)模式,——靠柜臺(tái)外站著,寫些代碼換一個(gè)雞蛋灌餅吃;倘若懂一些多線程的知識,便可以在雞蛋灌餅里加火腿腸,或者里脊了,如果懂得語言的實(shí)現(xiàn)原理,那就能做一些底層代碼的優(yōu)化,換一盤炒菜。但這些程序員,多是初級水平,大抵沒有這樣深入。只有懂得內(nèi)存模型的,才能接一些底層的項(xiàng)目,打開調(diào)試器和剖析器,慢慢的坐著優(yōu)化代碼。
我從十二歲起,便在村口的githoverflow工廠里當(dāng)學(xué)徒,師傅說,我邏輯思維太差,怕學(xué)不會(huì)靜態(tài)類型語言,就寫些shell腳本吧。shell腳本雖然容易寫,但語法容易含混不清的地方也不少。字符串和數(shù)組的功能很弱,條件判斷的語法也很奇特,有時(shí)要對特殊字符手動(dòng)做兩重轉(zhuǎn)義,然后通過。在這種情況下,寫腳本也很為難。所以過了幾天,師傅又說我干不了這事。幸虧薦頭的情面大,辭退不得,便改為專管測試的一種無聊職務(wù)了。
我從此便整天的站在測試機(jī)前,專管運(yùn)行測試腳本。雖然沒有什么失職,但總覺得有些單調(diào),有些無聊。師傅是一副兇臉孔,程序員也沒有好聲氣,教人活潑不得;只有夕甲甲到廠里,才可以笑幾聲,所以至今還記得。
夕甲甲是站著編程而手動(dòng)管理內(nèi)存的唯一的程序員。他用的開發(fā)語言語法臃腫;結(jié)構(gòu)雜亂,代碼間時(shí)常夾些#ifdef;一堆亂蓬蓬的充當(dāng)接口的.h文件。雖然是手動(dòng)管理內(nèi)存,可是經(jīng)常出現(xiàn)野指針,要么忘了初始化,要么釋放后沒有設(shè)置成NULL。他寫的代碼,總是滿屏的奇技淫巧,叫人半懂不懂的。因?yàn)樗障Γ挚傆X得自己的技術(shù)天下第一,別人便用“甲乙丙丁”的第一個(gè)字,替他取下一個(gè)綽號,叫做夕甲甲。夕甲甲一到廠,所有的程序員便都看著他笑,有的叫道,“夕甲甲,你的代碼又出新bug了!”他不作答,對柜里說,“來兩個(gè)雞蛋灌餅,一杯豆?jié){。”便把Thinkpad擺好。他們又故意的高聲嚷道,“你一定又把人家的內(nèi)存搞泄漏了!”夕甲甲睜大眼睛說,“你怎么這樣憑空污人清白……”“什么清白?我前天親眼見你搞崩了Windows的內(nèi)存,吊著打。”夕甲甲便漲紅了臉,額上的青筋條條綻出,爭辯道,“內(nèi)存沒釋放不能算泄漏……沒釋放!……程序員的事,能算泄漏么?”接連便是難懂的話,什么“new/delete配對使用”,什么“誰申請誰釋放”之類,引得眾人都哄笑起來:廠內(nèi)外充滿了快活的空氣。
聽人家背地里談?wù)摚准自瓉硪沧x過CS博士,但終于沒有去做學(xué)術(shù),又不會(huì)營生;于是愈過愈窮,弄到將要討飯了。幸而還會(huì)寫點(diǎn)代碼,便替人家做幾個(gè)游戲,換一碗飯吃。可惜他又有一樣壞毛病,便是內(nèi)存泄漏。運(yùn)行不到幾秒,便連程序帶數(shù)據(jù),一齊崩掉。如是幾次,叫他寫游戲的人也沒有了。夕甲甲沒有法,便只好做些最簡單的外包項(xiàng)目。但他在我們廠里,品行卻比別人都好,就是從不留bug;雖然間或一時(shí)不能解決,暫時(shí)記在wiki上,但不出一月,定然修復(fù),從wiki上刪去了夕甲甲的名字。
夕甲甲寫過半頁代碼,漲紅的臉色漸漸復(fù)了原,旁人便又問道,“夕甲甲,你當(dāng)真會(huì)寫代碼么?”夕甲甲看著問他的人,顯出不屑置辯的神氣。他們便接著說道,“你怎的連半行代碼也沒有貢獻(xiàn)給linux內(nèi)核呢?”夕甲甲立刻顯出頹唐不安模樣,臉上籠上了一層灰色,嘴里說些話;這回可是全是“狗屎Linus”之類,一些不懂了。在這時(shí)候,眾人也都哄笑起來:店內(nèi)外充滿了快活的空氣。
在這些時(shí)候,我可以附和著笑,師傅是決不責(zé)備的。而且?guī)煾狄娏讼准祝裁棵窟@樣問他,引人發(fā)笑。夕甲甲自己知道不能和他們談天,便只好向孩子說話。有一回對我說道,“你學(xué)過編程么?”我略略點(diǎn)一點(diǎn)頭。他說,“學(xué)過編程,……我便考你一考。const int *和int const *,有什么區(qū)別?”我想,討飯一樣的人,也配考我么?便回過臉去,不再理會(huì)。夕甲甲等了許久,很懇切的說道,“不知道罷?……我教給你,記著!這些語法應(yīng)該記著。將來做程序員的時(shí)候,寫代碼要用。”我暗想我和程序員的等級還很遠(yuǎn)呢,而且我們師傅也從不用裸指針;又好笑,又不耐煩,懶懶的答他道,“誰要你教,兩個(gè)沒區(qū)別,都是指向常量的指針。如果你想用指針常量,要寫int * const。”夕甲甲顯出極高興的樣子,將手里的破鼠標(biāo)敲著電腦桌,點(diǎn)頭說,“對呀對呀!……const有四種用法,你知道么?”我愈不耐煩了,努著嘴走遠(yuǎn)。夕甲甲剛在Visual Studio里新建一個(gè)空文件,想在里面寫代碼,見我毫不熱心,便又嘆一口氣,顯出極惋惜的樣子。
有幾回,鄰居孩子聽得笑聲,也趕熱鬧,圍住了夕甲甲。他便給他們一人寫了一個(gè)Hello World。孩子看完,仍然不散,眼睛都望著屏幕。夕甲甲著了慌,伸開五指將屏幕罩住,彎腰下去說道,“error了,編譯器報(bào)error了。”直起身又看一看屏幕,自己搖頭說,“error error!哀乎哉?error也。”于是這一群孩子都在笑聲里走散了。
夕甲甲是這樣的使人快活,可是沒有他,別人也便這么過。
有一天,大約是程序員節(jié)前的兩三天,師傅正在慢慢的release代碼,打開wiki,忽然說,“夕甲甲長久沒有來了。還有十九個(gè)bug沒修復(fù)呢!”我才也覺得他的確長久沒有來了。一個(gè)喝酒的人說道,“他怎么會(huì)來?……他打折了腿了。”師傅說,“哦!”“他總?cè)耘f是搞崩內(nèi)存。這一回,是自己發(fā)昏,竟搞崩了GFW的內(nèi)存。他家的內(nèi)存,搞得的嗎?”“后來怎么樣?”“怎么樣?先是去喝茶,后來是打,打了大半夜,再打折了腿。”“后來呢?”“后來打折了腿了。”“打折了怎樣呢?”“怎樣?……誰曉得?許是死了。”師傅也不再問,仍然慢慢的做他的release。
程序員節(jié)過后,函數(shù)式編程是一天比一天熱門,看看連Java都開始支持lambda表達(dá)式;我整天的做測試,也須了解什么是閉包了。一天的下半天,沒有一個(gè)要測試的項(xiàng)目,我正合了眼坐著。忽然間聽得一個(gè)聲音,“來一個(gè)雞蛋灌餅。”這聲音雖然極低,卻很耳熟。看時(shí)又全沒有人。站起來向外一望,那夕甲甲便在柜臺(tái)下對了門檻坐著。他臉上黑而且瘦,已經(jīng)不成樣子;帶一本破Thinkpad,盤著兩腿,下面墊一個(gè)電腦包,用草繩在肩上掛住;見了我,又說道,“來一個(gè)雞蛋灌餅。”師傅也伸出頭去,一面說,“夕甲甲么?你還有十九個(gè)bug沒修呢!”夕甲甲很頹唐的仰面答道,“這……下回修罷。這一回是現(xiàn)場通過,雞蛋要好。”師傅仍然同平常一樣,笑著對他說,“夕甲甲,你又內(nèi)存泄漏了!”但他這回卻不十分分辯,單說了一句“不要取笑!”“取笑?要是不泄漏,怎么會(huì)打斷腿?”夕甲甲低聲說道,“跌斷,跌,跌……”他的眼色,很像懇求師傅,不要再提。此時(shí)已經(jīng)聚集了幾個(gè)人,便和師傅都笑了。我煎了雞蛋灌餅,拿出去,放在門檻上。他打開電腦開始寫代碼,見他滿手是泥,原來他便用這手走來的。不一會(huì),他提交代碼,通過了測試和review,便又在旁人的說笑聲中,坐著用這手慢慢走去了。
自此以后,又長久沒有看見夕甲甲。到了Rust 1.0發(fā)布的時(shí)候,師傅打開wiki說,“夕甲甲還有十九個(gè)bug呢!”到Golang 2.0發(fā)布的時(shí)候,又說“夕甲甲還有十九個(gè)bug呢!”到Scala 3.0發(fā)布的時(shí)候可是沒有說,再到Rust又演進(jìn)了一個(gè)版本也沒有看見他。
我到現(xiàn)在終于沒有見——大約夕甲甲的確死了。
寫于二零一五年夏