程序員啟示錄
最近因?yàn)轫?xiàng)目需要在看一個(gè)開源項(xiàng)目的源碼,這個(gè)開源項(xiàng)目據(jù)說(shuō)在內(nèi)部開發(fā)孵化了 6 年之久,前幾年才開源出來(lái)。 我在看設(shè)計(jì)文檔和源碼中發(fā)現(xiàn),它的高層設(shè)計(jì)的一致性是比較好的,但到了源碼實(shí)現(xiàn)就顯得凌亂了些。 既然是時(shí)間跨度如此長(zhǎng)的項(xiàng)目,想必參與這個(gè)項(xiàng)目的程序員也不止一批人了,處于不同階段的程序員都有可能參與,這樣也能理解實(shí)現(xiàn)上的凌亂了。 看著這些有一定時(shí)間沉淀的代碼,有些代碼可能誕生于差不多我剛工作的年頭,有些又是最近才加上的。 不免讓我回想起作為程序員,與這些代碼一起在時(shí)間中的成長(zhǎng)與沉淀。
剛工作的第二年,我接手了一個(gè)比較大的項(xiàng)目中的一個(gè)主要模塊。 在我熟悉了整個(gè)模塊后,開始往里面增加功能時(shí),有點(diǎn)受不了原本的 DAO 層,那是基于原生的 JDBC 封裝的。 每次新增一個(gè) DAO 都需要復(fù)制粘貼一串看起來(lái)很類似的代碼,久了難免生出厭煩的情緒。
當(dāng)時(shí) Hibernate 剛興起,覺(jué)得它的設(shè)計(jì)理念優(yōu)雅,代碼寫出來(lái)也簡(jiǎn)潔,所以說(shuō)干就干就決定用 Hibernate 的實(shí)現(xiàn)取代原本的實(shí)現(xiàn)。 重新實(shí)現(xiàn)原來(lái)所有的 DAO 層類,這說(shuō)多不多說(shuō)少不少也有好幾百個(gè) DAO 類,導(dǎo)致連續(xù)加了一周的班。 這是個(gè)純粹的搬磚體力活,弄完了還沒(méi)松口氣又有了新問(wèn)題,Hibernate 在某些場(chǎng)景下又出現(xiàn)了性能問(wèn)題。 斷斷續(xù)續(xù)把這些新問(wèn)題處理好,著實(shí)讓我累了一陣子,后來(lái)反思這個(gè)決策感覺(jué)確實(shí)不太妥當(dāng)。 替換帶來(lái)的好處僅僅是每次新增個(gè) DAO 時(shí)少寫幾行代碼,卻帶來(lái)很多當(dāng)時(shí)未知的風(fēng)險(xiǎn)。
年輕的程序員對(duì)新技術(shù)充滿好奇,而且有顆沖動(dòng)的心。 對(duì)新技術(shù),我知道,我了解、我熟悉、我深諳,但我還是需要克制,等待合適的時(shí)機(jī)。 寫到這里,想起了《勇敢的心》梅爾·吉普森看著對(duì)方?jīng)_過(guò)來(lái),喊著 Hold~Hold~ 的場(chǎng)景。
在更早的時(shí)候,我在廣東省中國(guó)銀行寫過(guò)一個(gè)小程序,就是給所有廣東省中國(guó)銀行的信用卡客戶發(fā)郵件賬單。 按現(xiàn)在各大銀行信用卡客戶上億的規(guī)模,即使只是每月發(fā)賬單郵件的程序也不能算小了。 只是當(dāng)時(shí)廣東中行信用卡剛起步,***個(gè)月只有不到 10 萬(wàn)客戶,所以算小程序。
那個(gè)年代都是全棧工程師啊,連賬單頁(yè)面模板的樣式都是我自己設(shè)計(jì)的,***次還犯了個(gè)小錯(cuò)誤就是金額展示沒(méi)有靠右對(duì)齊。 而且程序就部署在信用卡部的一個(gè)業(yè)務(wù)人員的獨(dú)立配置的辦公電腦上。 每月出賬,核心交易系統(tǒng)下發(fā)賬單格式文件,業(yè)務(wù)人員手工導(dǎo)入格式文件生成模板郵件,然后就開始發(fā)送了。 所以,這個(gè)小程序就是個(gè)單機(jī)程序,為了方便業(yè)務(wù)人員操作,我寫了個(gè) GUI 界面。 ***次用 Java swing 寫 GUI,為了展示發(fā)送進(jìn)度,后臺(tái)線程每發(fā)送成功一封郵件,通知頁(yè)面線程更新進(jìn)度條。
當(dāng)時(shí)正在學(xué) Java JDK 還沒(méi)有標(biāo)配 concurrent 包,都是原生的,覺(jué)得 java 線程編程很高端。 所以我選擇線程間通信的方案來(lái)讓后臺(tái)發(fā)送線程和前臺(tái)頁(yè)面刷新線程通信,一股濃濃的炫技心理。 后來(lái)導(dǎo)致了界面動(dòng)不動(dòng)就卡住等一系列問(wèn)題,因?yàn)楦鞣N線程提前通知,遺漏通知等情況,代碼越改越難懂。 其實(shí)用個(gè)共享狀態(tài),定時(shí)輪詢即可滿足的,而且代碼實(shí)現(xiàn)會(huì)簡(jiǎn)單的多。 回頭想想,成長(zhǎng)的路上不免見獵心喜、手上拿個(gè)錘子看到哪里都是釘子。 話說(shuō)回來(lái),我還挺懷念當(dāng)初設(shè)計(jì)的那個(gè)賬單模板,可惜現(xiàn)在找不到了。 感覺(jué)比現(xiàn)在建行給我發(fā)的那個(gè)傻大黑粗的表格看起來(lái)好些吧,傳統(tǒng)銀行在用戶體驗(yàn)上的路上還有多遠(yuǎn)的路要走?
我現(xiàn)在正看的開源代碼也看到一些炫技的痕跡,具體說(shuō)就是關(guān)于狀態(tài)機(jī)的使用。 狀態(tài)機(jī)程序是不符合直線邏輯思維的,類似 GOTO 語(yǔ)句,程序會(huì)突然發(fā)生跳轉(zhuǎn),所以理解狀態(tài)機(jī)程序比一般程序要難。 而狀態(tài)機(jī)程序又通過(guò)自定義的的內(nèi)存消息來(lái)驅(qū)動(dòng),更加一層復(fù)雜性。 在我理解,狀態(tài)機(jī)程序最適合的場(chǎng)景有真實(shí)映射領(lǐng)域狀態(tài)變遷,什么叫真實(shí)領(lǐng)域狀態(tài)?比如,你紅綠燈就表達(dá)了真實(shí)領(lǐng)域的三種狀態(tài)。 另外一個(gè)主要用途就是做協(xié)議解析,反應(yīng)解析器當(dāng)前的運(yùn)行狀態(tài)。 凡是使用狀態(tài)機(jī)來(lái)表達(dá)程序設(shè)計(jì)實(shí)現(xiàn)中的偽狀態(tài),往往都添加了不必要的復(fù)雜性。
有時(shí)我經(jīng)常會(huì)在一些開源項(xiàng)目中看到一些過(guò)度設(shè)計(jì)和實(shí)現(xiàn)的復(fù)雜性,而這些項(xiàng)目還都是一些行業(yè)***的大公司開源的。 在程序員的成長(zhǎng)路徑上,越是高階的晉升中,行業(yè)里喜歡采用專家評(píng)審制,評(píng)委會(huì)傾向性的關(guān)注項(xiàng)目中的技術(shù)難點(diǎn)以及技術(shù)含量。 制度的傾向性也有可能導(dǎo)致人為制造技術(shù)含量,而不一定是匹配項(xiàng)目的***方案。 所以程序的技術(shù)含量和深度未必體現(xiàn)在表面,我「看山是山看水是水,看山不是山看水不是水,看山還是山看水還是水」。 轉(zhuǎn)了一圈回來(lái),機(jī)鋒盡斂,大巧若拙,深在深處,淺在淺處,這也是我所理解的 KISS 原則。
在很多科幻小說(shuō)和電影中都有很多關(guān)于未來(lái)假設(shè),多分支可能的存在。 在科幻電影《Coherence》中假設(shè)了一種一個(gè)人存在的多版本可能,碰巧在某天重疊了。 我挺喜歡這個(gè)設(shè)定的,它來(lái)自于「薛定諤的貓」的理論實(shí)驗(yàn),就是關(guān)于未來(lái)已經(jīng)存在很多可能版本,我們走過(guò)的部分就形成了唯一的穩(wěn)定版本。 我走了很遠(yuǎn),停下來(lái)回顧時(shí)間線上很早的自己,得到這星星點(diǎn)點(diǎn)的啟示。 而現(xiàn)在的駐足與回顧,都不過(guò)是借此啟示幫助我們更好的邁出不論或大或小的下一步。