-
晚上八點四十分,沈牧合上了給朝陽唸的第五本繪本。
《猜猜我有多愛你》的最後一頁還攤在床上,彩色的插畫在昏暗的床頭燈下顯得溫暖。朝陽已經睡著了,小臉埋在他臂彎裡,睫毛在眼瞼投下淺淺的陰影,一隻小手還無意識地抓著他襯衫的衣角。睡夢中,他咂了咂嘴,發出細微的、滿足的囈語。
另一側,星辰也睡著了。他睡得很規矩,平躺著,薄被拉到胸口,雙手交疊放在被子外麵。呼吸均勻悠長,眉頭舒展,白天在教室裡的緊繃感完全消失了,隻剩下孩子熟睡時特有的寧靜。他的臉頰貼著洗得發白的枕套,那裡有沈牧今天下午特意曬過的、陽光留下的乾燥氣味。
沈牧維持著側臥的姿勢,一動不動,生怕一點動靜就驚擾了這來之不易的安寧。他的左臂被朝陽枕著,已經有些發麻,右臂越過朝陽小小的身體,輕輕搭在星辰被子的邊緣。這張摺疊床不過一米二寬,要擠下他和兩個半大的孩子,幾乎是不可能的任務。他側著身,後背緊貼著冰涼的牆壁,才能勉強騰出空間。孩子們的體溫透過薄薄的衣衫傳來,溫熱,沉實,像兩簇小小的火苗,烘烤著他胸腔裡冰冷僵硬的角落。
他就這樣靜靜地躺了十分鐘,直到確認兩個孩子都徹底沉入了夢鄉,才極其緩慢、極其小心地將自已的手臂從朝陽的腦袋下抽出來。動作慢得像在拆解一枚精密的炸彈。麻癢的感覺像無數細針順著血液竄上來,他咬緊牙關,冇發出一點聲音。
終於脫身。他光腳踩在地上,冰涼的水泥地激得他腳心一縮。他彎下腰,仔細地給兩個孩子掖好被角,將朝陽那隻伸到被子外的小胳膊輕輕塞回去。做完這些,他才直起身,揉了揉酸澀不堪的後頸和徹底麻木的左臂,血液迴流帶來一陣尖銳的刺痛。
房間裡的寂靜被放大。遠處街道偶爾駛過的夜車聲,樓上住戶隱約的電視音響,水管裡水流過的空洞迴響,還有兩個孩子交錯起伏的、輕柔均勻的呼吸聲。這呼吸聲是這間狹小、潮濕、昏暗的公寓裡,唯一真實而柔軟的錨點。
他走到窗邊那張搖搖晃晃的書桌前,按亮了檯燈。昏黃的光圈勉強照亮桌麵,也映出他眼底濃重的青黑和臉上無法掩飾的疲態。桌上,那台老舊的ThinkPad膝上型電腦已經開啟,螢幕上是一個未完成的程式碼編輯器介麵,旁邊開著任務需求文件和幾個參考網頁。螢幕的光在昏暗裡顯得刺眼。
他坐下,塑料凳子發出輕微的嘎吱聲。先伸手試了試保溫杯的溫度,還是溫的。他擰開蓋子,濃茶苦澀的香氣瀰漫開來。這不是什麼好茶,是超市最便宜的袋泡茶,他放了雙倍分量,泡出的茶湯顏色深褐,入口是尖銳的苦,但能提神。他灌下一大口,灼熱的液體滑過乾澀的喉嚨,苦澀的味道在舌尖炸開,讓他混沌的大腦清醒了半分。
目光重新聚焦到螢幕上。這是一個小程式的開發單子,功能並不複雜,是一個用於小型服裝店庫存管理和會員積分的前端介麵。但甲方要求多,細節繁瑣,且對接人態度急躁。原本三天的工期,因為要接送孩子、陪讀,他隻能壓縮到兩個晚上。截止時間,是明天上午十點。
他活動了一下手指,骨節發出輕微的響聲。然後,雙手放在了鍵盤上。
敲擊聲在寂靜的夜裡清脆地響起。劈啪,劈啪,像雨點打在鐵皮屋頂上,規律,密集,帶著一種孤注一擲的節奏。他的眼睛緊盯著螢幕,手指在鍵盤上快速移動,偶爾停頓,思考,刪掉幾行,重寫。窗外的夜色越來越沉,遠處樓宇的燈火一盞接一盞熄滅,隻有他桌前這一小方光亮,和持續不斷的鍵盤聲,證明著這個角落尚未被睡眠征服。
時間在程式碼的行間無聲流淌。茶涼了,他又去燒水,沖泡,動作輕得像貓。中途星辰似乎夢囈了一句什麼,翻了個身。沈牧立刻停下敲擊,屏息回頭,直到確認兒子隻是無意識的動作,才轉回來,繼續。
淩晨一點十七分。
主體功能已經基本完成,進入除錯階段。沈牧執行測試,一個資料列表的渲染出現了問題。頁麵卡頓,滾動時條目錯位。他皺了皺眉,開始排查。這不是複雜的邏輯錯誤,更像是某個樣式衝突或者資料繫結時機的問題。這種bug有時候很磨人,看似簡單,卻需要耐心地一點點剝離、定位。
他調出開發者工具,一行行檢查程式碼,在幾個關鍵節點設定斷點,觀察資料流和DOM變化。一遍,兩遍。問題似乎出現在某個動態載入的元件上,但具體是哪裡,一時抓不住。
手指敲擊的速度慢了下來,變成了思考時的無意識輕叩。眉頭鎖緊,嘴唇抿成一條直線。他嘗試了幾種常見的解決方案,修改樣式優先順序,調整資料更新時機,重寫渲染函式……問題依舊存在。頁麵在測試環境下依舊卡頓,列表渲染異常。
挫敗感像細微的藤蔓,悄悄爬上心頭。不是因為問題本身有多難,而是時間。窗外的黑暗濃稠如墨,萬籟俱寂,連遠處偶爾的車聲都消失了。隻有他的檯燈,他的螢幕,他越來越沉重的眼皮,和那個頑固的bug。
就在這時,電腦右下角,接單平台的通訊圖示急促地閃爍起來,發出“滴滴”的提示音,在深夜裡格外刺耳。
沈牧心頭一跳,點開。
是甲方對接人,頭像是一個穿著西裝、表情嚴肅的中年男人卡通形象。訊息是五分鐘前發的:
“在?進度如何?明早十點必須準時交付,我們這邊釋出會物料都排好了,就等上線。彆出岔子。”
語氣帶著毫不掩飾的不耐煩和催促。
沈牧深吸一口氣,快速敲字回覆:“在除錯,遇到一個小問題,很快解決。明早十點前一定交付。”
訊息幾乎是秒回:“什麼問題?嚴重嗎?說了要提前測試,不要臨到交付了才說有問題!我們很急的!”
字裡行間透著壓力和責備。
沈牧盯著那行字,螢幕的光映在他冇什麼表情的臉上。他冇有解釋,也冇有道歉,隻是簡短地回了兩個字:“明白。”
然後,他關掉了聊天視窗,將閃爍的圖示最小化。眼不見,心不煩。儘管那無形的壓力,已經透過螢幕,沉甸甸地壓在了他的肩頭。
他重新將全部注意力拉回到那個bug上。濃茶已經無法驅散從骨髓深處滲出的疲憊,太陽穴一抽一抽地疼。他用力揉了揉眉心,起身用冷水洗了把臉。冰冷的水刺激著麵板,帶來短暫的清明。他回到桌前,放棄了之前零碎的嘗試,決定從頭梳理。
他新建了一個空白測試頁,將出問題的元件剝離出來,用最簡化的資料和樣式重新引入。一行行程式碼看過去,像在顯微鏡下檢視細胞。時間一分一秒過去,螢幕右下角的數字無聲跳動:01:45,02:03,02:27……
突然,他的目光停留在某一行樣式引用的類名上。一個極其細微的拚寫錯誤,在整頁程式碼中毫不起眼。他之前幾次檢查都忽略了。這個錯誤的類名導致某個關鍵樣式未被正確應用,進而影響了後續的渲染效能。
他修正了那個字母,儲存,執行。
頁麵流暢地滑出,列表清晰,滾動順滑。bug解決了。
淩晨兩點四十一分。
他盯著完美執行的測試頁麵,有幾秒鐘的空白。冇有如釋重負的喜悅,隻有一種近乎麻木的完成感。他活動了一下僵直的脖頸和肩膀,傳來清晰的骨骼脆響。
他重新開啟主工程,將修正同步,執行完整測試流程。一切正常。他又花了二十分鐘,仔細檢查了一遍程式碼規範、註釋和邊界情況處理。確認無誤後,他將程式碼打包,登入接單平台,找到交付入口,上傳檔案,在備註欄裡簡短說明瞭修改內容和測試結果。
點選“提交”。頁麵跳轉,顯示“交付成功,等待甲方確認驗收”。
他靠在椅背上,塑料椅背發出不堪重負的聲響。緊繃了近六個小時的神經,終於有了片刻鬆緩的機會。極度的疲憊像潮水般席捲上來,眼皮重得幾乎抬不起來。他瞥了一眼螢幕右下角的時間,淩晨三點過七分。
他閉上乾澀發痛的眼睛,想休息幾分鐘。但平台的提示音再次響起,將他從短暫的昏沉邊緣拉回。
是結算通知。甲方已經確認驗收,專案完結。
他點開結算詳情。專案總金額一千二百元。平台抽成百分之十,應得一千零八十元。
但實際結算金額顯示:七百五十六元。
下麵有一行小字備註:“因交付物延遲兩小時零七分,按合同約定扣除30%費用作為違約金。”
沈牧的目光定格在那個數字上。七百五十六。又看向那行備註。延遲兩小時零七分。合同約定……是的,他接單時匆匆掃過那份電子合同,裡麵確實有關於延遲交付的罰款條款,比例不低。他當時隻想著儘快接下這單,想著金額勉強夠付下個月這間公寓的租金,冇仔細看,或者說,冇有資本去挑剔。
他就那樣盯著螢幕,看了很久。螢幕的光映在他冇什麼血色的臉上,眼底一片沉寂的深潭。冇有憤怒,冇有委屈,甚至冇有多少意外。隻有一種瞭然的、冰冷的麻木。
他知道可以爭辯,可以解釋bug的突發性,可以指出自已是在截止時間前交付的(儘管按照合同苛刻的計時方式,確實“延遲”了)。但他更知道,在甲方的立場,在平台的規則麵前,他的任何解釋都蒼白無力。對方要的是結果,是準時,是零風險。他一個靠接散活為生的自由開發者,冇有議價權,冇有拖延的資本。
他冇有在聊天視窗輸入任何一個字。隻是移動滑鼠,點選了“確認結算”。
七百五十六元。加上之前賬戶裡僅剩的一點餘額,剛剛夠支付下個月這間潮濕逼仄的單間公寓的八百元租金,或許還能剩下幾十塊,作為接下來幾天他和孩子們的夥食費。
他關掉了接單平台,關掉了程式碼編輯器,關掉了所有網頁。螢幕上隻剩下漆黑的背景和零散的幾個圖示。
他最後看了一眼床上。兩個孩子依舊睡得香甜。星辰不知何時又翻回了平躺的姿勢,朝陽則整個人都蜷縮到了被子裡,隻露出毛茸茸的頭頂。他們的呼吸聲在寂靜中交織,平穩,安寧,對他剛剛經曆的一場無聲的、代價昂貴的戰役毫無所覺。
沈牧靠在堅硬的椅背上,閉上了乾澀灼痛的眼睛。黑暗中,那清脆的鍵盤敲擊聲彷彿還在耳邊迴響,混合著甲方催促的訊息提示音,最終,都化為了背景裡,兒子們均勻而綿長的呼吸。
這呼吸,是這漫漫長夜裡,唯一真實,也唯一值得的聲響。
明天,不,是幾個小時後,天就會亮。他還要起床,送他們上學。
他靠在椅背上,一動不動,像一尊疲憊凝固的塑像。直到窗外深沉的夜色,開始透出第一縷極其暗淡的、蟹殼青的微光。
-