寫書小記

我的書《Node.js開發指南》將要在7月10日左右出版上市,回想過去一年花費的心血,不禁感慨良多。藉此良機,我記錄了一下過去一年的些許經歷,向大家大致介紹一下這本書是如何誕生的。

我已經忘了是從什麼時候開始接觸到Node.js的了,大概是2009年末或2010年初吧,那時Node.js還不像現在這麼火,祗是剛剛誕生的衆多前途未卜的新技術框架之一。一言以蔽之,Node.js就是一個讓JavaScript運行在瀏覽器之外的東西。說起JavaScript,市場上JavaScript的書幾年前就已經氾濫了,許多書的一個共同特徵就是介紹以瀏覽器爲基礎的JavaScript,大多都是花很少篇幅介紹JavaScript語言本身,花大量篇幅放在DOM、BOM的分析或jQuery這樣的框架上。想想看這也是理所應當的,如果在當時不介紹瀏覽器中的開發,學習JavaScript有什麼用呢?

說起Node.js,它本質上並不是什麼新東西,服務端的JavaScript十幾年前就有了,異步程序設計也不是什麼新思路,祗是把它們結合起來放在服務器端,多少看來像一個異端。我呢,雖然對前端開發有所涉獵,但並不工於此道,偏偏我又對JavaScript這個語言有所偏好,Node.js簡直就是爲我量身定做的了。不知爲何,Node.js這個「異端」就這麼火起來了。2010年是Node.js飛速發展的一年,它從一開始的默默無聞突然間變得大紅大紫,這是我接觸之初都始料未及的。2011年它的發展更是迅猛,衆多巨頭都加入了支持,甚至連開源宿敵微軟都伸出了橄欖枝,這讓Node.js實現了真正的完全跨平臺。

任何一個新技術在誕生之初遇到的最大的障礙就是文檔的匱乏,這一點祗有喜歡嘗試的人纔有所體會。早期的Node.js文檔非常糟糕,沒有任何教程,也沒有成熟的「解決方案」供參考。遇到問題以後上Google搜索一般都是沒有答案的,能依靠的祗有去郵件列表詢問。詢問還不一定有結果,所以很多時候要閱讀源代碼。

2011年7月,我剛剛放暑假,想想閒來無事,不如寫一個Node.js的入門教程。想到便做,於是我打開當當網,在上面搜索了關鍵詞Node.js,期望能有什麼已經出版了的書以供參考,但沒有任何結果,影印版也沒有,這並不令我意外。我又上Amazon.com搜索,令我始料未及的是竟然纔祗有一個搜索結果,那便是當時還未上市的《Node Web Development》。在我的印象中,凡是在國內買不到的書在Amazon上肯定有英文版,但這次竟然Amazon也沒有!看來這個技術實在是太新了,導致市場上還沒什麼書。當下我的心中便萌生了一個大膽想法,我何不寫第一本書呢?

這個想法簡直太猖狂了!看看很多書的作者都是大學教授,或者產業界的領軍人物,有無數的經驗。而我呢,纔不過一個大二的學生,寫的書會有人看嗎?甚至連能不能出版都是個問題。此外我除了有一個維護了五年的博客以外,沒有任何寫作經驗,要寫一本書談何容易?也算是初生之犢不畏虎,我當時就決定大膽去嘗試了,反正大不了就放到網上大家看唄。儘管完全不知從何下手,但想起某些國外的書上作者寫着自己是用LaTeX寫成的,所以就從學LaTeX下手吧。於是我花了一個星期看各種LaTeX的入門資料,學會了編輯一些簡單的文檔,看了許多高人留下的宏包和模板,但LaTeX的繁複還是遠超我的預期,想排版出一本書真是太難了。挫敗感第一次擊敗了我,五分鐘熱度過了以後,我對寫書也提不起興趣了。後來我纔知道作者其實不用太關心排版的,出版社有專業的編輯,而且他們都用Word……不過我找到了更好的工具Sphinx,此後的整本書都是用它寫成的。

一放就是一個多月,當我再次提起興趣的時候,是我開始加入Accounts9的開發。之前雖然也用Node.js寫過不少好玩的東西,但都是自己折騰,這是第一次用Node.js開發真正要應用起來的東西。實際項目開發的過程中讓我學到了許多以前沒有注意到的細節,我對Node.js的興趣重新被點燃,於是我準備好好研究一下Node.js。我從Amazon花了幾十美元買了全世界惟一的一本關於Node.js的書《Node-Web-Development》,到貨以後便如飢似渴地讀完了所有的篇章。令我有些失望的是,這本書寫得並不怎麼樣,而且版本太老,Node.js在誕生之初的變化是極快的,許多API如過眼煙雲,換一個版本就改頭換面了。這畢竟也難以苛責作者,總要有人做先驅嘛。好在Node.js版本在0.6以後API已經趨於穩定,不會再「翻天覆地」了。靜言思之,我發現面對的是一片未經開墾的處女地,因爲祗要是第一本書,無論好壞總會有人買單。

冷靜下來,我決定先擬定一個提綱,然後就開始動筆。我花了一個月寫了兩章,分別是「Node.js簡介」和「JavaScript高級特性」,前者是一個對Node.js的綜述性介紹,而後者則是針對服務器端開發的需求講解JavaScript,與大多數圍繞瀏覽器介紹JavaScript的書有很大不同。寫了兩章以後,熱度再次減退了,因爲暑假已經結束,各種課業的壓力紛至沓來。儘管寫成一本書很有成就感,但遠水不解近渴,於是我又被擊敗了,寫書之事又擱置了下來。

有道是「無巧不成書」,世事偏偏就是那麼巧。有一次我和一個學姐(徐可可)一起吃飯,聊到她的家教工作,她說道她的一個學生家長是某個什麼出版社的。我一聽精神爲之一振,便向她介紹了我已經擱置了的寫書計劃。她聽完以後也挺感興趣的,答應幫我詢問具體出版事宜。後來得知,這位在出版社工作的學生家長竟然就是圖靈出版公司的總編謝工。圖靈出版公司啊,我仰慕已久,不知道讀過他們的多少好書(《C++ Primer》、《JavaScript高級程序設計》、《黑客與畫家》……)。通過她我與圖靈的另一位總編楊海玲取得了聯繫,並且在CNode社區的北京交流會上見面認識了。楊海玲也是IT出版界赫赫有名的人物,她在來到圖靈公司之前,她曾經是機械工業出版社下華章公司那一套黑皮的「計算機科學叢書」的出版負責人,像《算法導論》什麼的當年都是她翻譯引進的。我斗膽把寫好的兩章稿子和提綱交給了她,忐忑不安地期待評價。幾天以後,我得到了不錯的反饋,簡直像是給我注入了一針強心劑,我又有動力繼續創作了。

轉眼到了寒假,我開始把全部精力投入寫書當中,回到學校時我的書也完成了接近一半。但隨着寫作的進度深入,終於遇到了瓶頸——有些章節我實在不知道該怎麼寫。再加上又一學期開始了,我寫作的進程再次漸漸陷入了停滯。這次我清醒地認識到必須在找點激勵了,於是我找到圖靈,簽訂了出版協議。現在,有合同約定我要在4月1日之前交稿,我便不得不克服困難了。事實再次驗證,往往是期限即將到來的那幾天工作是最有動力的,我最終還是按照合同約定交稿了。寫作到後期時,我找了不少人幫助審稿,在審稿的過程中我發現原本自己認爲寫得不錯的地方還有很大改進的餘地。我比較嚮往的出版方式是持久地修訂,而不是一次性交稿,但限於目前的現實條件,這還做不到。

並不是說交稿以後就沒事了,我還要和編輯共同審教、排版,後期的排版過程中我又發現了一些錯誤。所以說,一個出版公司的好壞很大程度上看編輯後期是否認真,圖靈在這方面可以說是佼佼者。再到後來圖靈還幫我設計了幾個封面,最終我選中了下圖這個方案:

感謝對這本書提出寶貴意見的我的朋友們,他們是牟瞳、李垚周越鍾音蕭騏、楊旭東、孫嘉龍范澤一、宋文杰、續本達田勁鋒孟亞蘭和李宇亮。他們爲本書的結構、內容、語言表述等方面給出了許多有建設性的建議。感謝CNodeJS社區的賈超和田永強,微軟亞洲研究院的楊懋,以及VMware公司的柴可夫。他們不僅幫助審閱了本書,還解決了許多技術問題,給這本書提出了許多改進方案。還要感謝我的朋友徐可可、圖靈教育出版公司的楊海玲、謝工、王軍花以及其他各位編輯,他們給我提供了許多幫助和鼓舞,沒有他們的激勵,我很難頂着巨大的學業壓力堅持寫完這本書。

特別要感謝的是弓辰開發的Rime輸入法,我依靠它完成了本書的創作。本書寫作的時候是準確的傳統漢字,出版時按照版署要求轉換爲了簡化字(通過OpenCC)。

最後引書中的一段文字: 在過去JavaScript一直不被人重視,很大程度上是因爲它太低效了——不僅速度慢,還佔用大量内存。但如今Javascript的效率卻令人驚訝。歷史總是如此相似,正如沒有Shockley發明晶體管就沒有電子科技革命一樣,如果沒有2008年以來的JavaScript引擎革命,Node.js就不會這麼快地誕生。

2008年Mozilla Firefox的一次改動,使Firefox 3.0的JavaScript性能大幅提升,從而引發了JavaScript引擎之間的效率競賽。緊接着WebKit開發團隊宣告了Safari 4新的JavaScript引擎SquirrelFish(後來改名 Nitro)可以大幅度提升腳本執行速度。Google Chrome剛剛誕生就因它的JavaScript性能而備受稱讚,但隨着WebKit的Squirrelfish Extreme和Mozilla的TraceMonkey技術的出現,Chrome的JavaScript引擎速度被超越了,於是Chrome 2發佈時使用了更快速的V8引擎。V8一出場就以其一騎絕塵般的速度打敗了所有對手,一度成爲JavaScript引擎之王者。於是其他瀏覽器開發者的重新開始奮力追趕,與以往不同的是,Internet Explorer也加入了這次競賽,並取得了不俗的成績。

時至今日,各個JavaScript引擎的效率已經不相上下,通過不同引擎根據不同測試基準測得的結果各有千秋。更有趣的是,在不知不覺中JavaScript的效率已經超越了其他所有傳統的腳本語言,並帶動了解釋器的革新運動。JavaScript已經成爲了當今速度最快的腳本語言之一,昔日「醜小鴨」終於成了如今驚艷絕俗的白天鵝。

這是單獨介紹本書的頁面:Node.js開發指南

推薦一個神級輸入法——Rime

用了那麼多年的輸入法,一直沒有一個讓我滿意的。早年我是從 Windows 95 自帶的「全拼輸入法」開始使用的,印象最深刻的就是一次只能打一個字,還有完全不搭邊的聯想。後來 Windows 98 以後改用「智能 ABC」,相比全拼真是質的飛躍。現在輸入法中的看似平常的功能,如聲母簡拼、用戶詞庫、以詞定字、模糊音等等幾乎都發軔於「智能 ABC」。後來接觸到網絡以後,我學會了使用「拼音加加」和「紫光拼音」,這兩者除了詞庫大了不少以外與「智能 ABC」相比並沒有什麼飛躍。直到「搜狗拼音」的誕生,我纔對輸入法有了更深的理解。搜狗拼音應該是第一個把自然語言處理算法應用到輸入法中的產品,通過大規模的統計語言模型實現了「智能組句」功能,爾後被「Google 拼音」和「QQ 拼音」複製,不過都在同一水平。

我是一個對輸入法有特殊要求的人,因爲我要輸入繁體字。早期的拼音輸入法沒有一個支持繁體中文的,最早是「微軟拼音」率先支持了繁體,但它亂用異體字,真的是把「回」的四種寫法在不同詞中用全了。搜狗拼音和Google 拼音後來也支持了繁體,不過簡直太爛了,幾乎是基於字的轉換,完全不考慮簡繁一對多的情況。雖然現在支持了一些,但還是錯漏百出,用起來極其不舒服。我嘗試過使用註音輸入法,好處在於沒錯誤,而且支持聲調,但是太不靈活了,不支持簡拼和打長詞,因此我開發了 ibus-bopomofo 註音輸入法,試圖把拼音輸入法的一些好特性移植過去。另一個問題是臺灣的註音輸入法打出的字都是「臺灣正體」,最大問題是「着」「著」不分工,而且使用了「為」「裡」「台」等俗字。後來我乾脆轉到了形碼的陣營,先後學習了鄭碼、五筆和倉頡輸入法。可是當我習慣音碼以後,再轉到形碼絕非一日之功,雖然我一直練習,可打字速度還是達不到拼音的三分之一。難道普天之下就沒有一個能準確打出繁體的拼音輸入法嗎?

Rime

一直以來,這個答案是否定的,畢竟開發輸入法本來就是一件費力不討好的事,況且有這種需求的人又不多,有誰會去開發呢?一切還得靠自己。可惜我書到用時方恨少,讓我開發一個這麼複雜的輸入法可幹不了。直到不久前佛振的Rime終於誕生,我的願望纔成了現實。

Rime全名是「中州韻輸入法引擎」,它不僅僅是一個輸入法,而是一個輸入法算法框架。Rime的基礎架構十分精良,一套算法支持了拼音、雙拼、註音、五筆、倉頡等所有音碼和形碼輸入法,遠比基於碼表的各種「輸入法生成器」優秀許多。Rime默認提供了兩個拼音輸入法「朙月拼音」和「地球拼音」,兩者都可以輸入準確的繁體和簡體,而且「地球拼音」還支持聲調輸入。Rime還支持了許多種方言拼音,如吳語、粵語,甚至中古漢語。

更超出我預料的是,Rime還是跨平臺的!Rime針對Windows、Linux、Mac三大平臺提供了不同的發行版,核心算法不變,還能和系統完美融合,真乃絕妙。佛振還給Rime的發行版起了好聽的名字,Windows發行版叫做「小狼毫」,Mac發行版叫做「鼠鬚管」,Linux發行版叫做「中州韻」。

廢話少說,讓我們用截圖說話:

「幹」「干」「乾」涇渭分明。

「饑」和「飢」都不會錯哦。

「出」「齣」分工正確。

「才」「纔」不一樣。

帶聲調的「地球拼音」。

註音符號輸入法。

支持七萬Unicode漢字的倉頡,還帶提示。

粵語拼音。

吳語拼音。

簡化字也是可以用的(由 OpenCC 強力驅動)。

「臺灣正體」模式,滿足臺灣人的用字需求。

用完以後我真是對Rime佩服得五體投地了,真可謂神級輸入法!更多的簡繁一對多問題,歡迎大家嘗試這個表 https://github.com/BYVoid/OpenCC/blob/master/data/scheme/st_multi.txt

Rime 下載地址 http://code.google.com/p/rimeime/wiki/Downloads

順便給 360 殺毒使用者提個醒,由於該輸入法作者沒給 360 交保護費,被 360 殺毒某些版本列入「未知木馬」(還未知就叫木馬,恐嚇用戶啊),請使用者冷暖自知。

關於作者佛振

大概在兩年前,我開發 OpenCC 和 ibus-pinyin 的時候認識了 rime 的作者佛振。他是我認識的第一位輸入法開發專家,也是最令我佩服的一位。我曾經在 Ubuntu 10.10 Release Party 上與他有過一面之緣,當時爲之手寫註音符號的能力所震驚,至今自愧弗如。作者佛振不僅編程能力高超,而且對中文有很深厚的造詣,這樣的一個人開發了若干年的輸入法,豈有不好用之理?兩年以來,他始終以不變的熱情投入到開源輸入法開發的工作當中,纔發明出了這麼好用的一個輸入法。誠心向佛振致敬!

註:本文通過rime小狼毫「地球拼音」輸入方案錄入。