天天看點

GNU Emacs 體系架構評論

轉載至http://zhan.renren.com/iemacs?tagId=7957&from=template&checked=true

GNU Emacs 是自由軟體協會的旗艦産品,也是自由軟體之父 Richard Stallman博士的得意之作。自十幾年前問世以來,其基本體系架構一直保持穩定,人們在這個基礎架構之上不斷添磚加瓦,逐漸将 GNU Emacs 建構成一個壯觀的軟體系統。    使用者越來越多,功能越來越強,又沒有專有軟體開發所特有的集中的管理,GNU Emacs的基本體系卻能長期保持穩定不變,這在信奉“唯一不變的就是變化本身”的十倍速時代,幾乎可以說是一個傳奇。究竟GNU Emacs是依靠什麼秘方常盛不衰?

恐怕隻有對自由軟體及GNU Emacs 有深入了解的人才能為我們揭開。 為此我采訪了洪峰先生。

關心中國自由軟體事業的朋友都應該知道洪峰先生。洪先生不僅是中國自由軟體事業的主要推動者和上司者,還是一名真正的黑客。在他身上,黑客的理想主義氣質和實幹家的魄力與務實精彩地融合在一起。這篇訪談以技術探讨開始,涉及了很多内容。相信不論是從技術上還是從思想上,洪先生在這篇談話中表露出來的東西都能夠給我們的讀者帶來更深刻的思考。

孟: 洪峰老師,您好!我手上有一本《GNU Emacs Lisp程式設計入門》,您是這本書的審校,還為它寫了“譯者序”。您的序言裡有這麼一段:“斯托曼的一個天才構想就是利用C 語言編寫與硬體直接作用的GNU Emacs子產品(如顯示子產品),而絕大多數文本編輯子產品則統統是利用Lisp語言來編寫。..這

一幾乎無限的靈活性是其他編輯器很難做到的。在GNU Emacs 中,Emacs 的Lisp代碼子產品和C 代碼子產品組織良好,它們互相取長補短,相得益彰。..斯托曼的這一天才的泛對稱設計思想極富藝術性,具有方法論研究的永久價值。” 你這段話其實講的是軟體的體系設計思想。不過在序言中似乎您欲言又止,沒能展開談,是以特别希望您能就這個問題着重講一講。我們先從Emacs 談起吧!從程式設計者的角度,您怎麼描述Emacs 的總體結構?您認為它屬于層次結構還是元件結構,或者是一種獨創的結構?

洪:首先,我想告訴你,曆史上出現過很多Emacs的版本,GNU Emacs 是其中的一個,也是影響最大的一個。是以我們的談話就集中在GNU Emacs 上面。下面如果不特别說明,我說的Emacs 就是指GNU Emacs。Emacs 采用的體系結構是自底向上的層次結構,大體上分成兩層:底層的C 代

碼(被封裝了),高層的Emacs Lisp 代碼(是開放的)。這個結構是RMS 獨創的。

孟:您說底層的C 代碼是被封裝了,而上層的Emacs Lisp 是開放的。我有一個問題,為什麼開放的上層不使用C來構造呢?那樣不是更直接,而且執行效率更高嗎?

洪:注意C 和Lisp 兩者的差別:C 是編譯型的強類型的語言,這意味着它的代碼必須以二進制格式運作,特點是運作效率高。但是Emacs 上層的編輯工作主要的資料是文本,而文本的本質就是Lisp 中的符号清單,當然也可以使用C 代碼來處理文本,但是如果你想對操作文本的C 代碼進行改動時必須按照“ 編輯-編譯- 連結-調試”循環的步驟來改。對于一個功能強大的編輯器,這是不可忍受的。

一個例子是使用 C 語言編寫的 Vim,它的運作速度很快,但是一點也不靈活,談不上有什麼擴充性。(這裡VIM的愛好者應該會有話說的吧:)

注意,Emacs Lisp 的代碼有兩種形式,一種是純文字形式存在的.el 檔案,還有一種是編譯過的.elc 檔案,這是一種位元組碼格式的檔案,運作起來速度很快。(Java的位元組碼的思想就來自于Lisp。),是以一些經過時間檢驗的Emacs Lisp代碼可以使用位元組碼方式運作,大大提高速度,而其他的Emacs Lisp 代碼就使用解釋方式運作,以求得擴充性。 當 Emacs Lisp 以解釋方式運作時,它不需要C 那種“編輯-編譯-連結-調試”的步驟,而是“閱讀-求值-列印”的步驟,也就是說,新設計的程式的效果馬上就可以看到,結合Emacs 編輯工作,你的編輯功能馬上就可以生效并投入使用。

孟:僅僅是下層用C,上層用Lisp,也并不一定就可以産生強健而靈活的系統吧!我特别關心一個問題,兩層之間如何結合,如何互相作用?這個問題設計不好,會适得其反。GNU Emacs在兩個層次結合上肯定有特别卓越的設計,您能分析分析嗎?

洪:Lisp語言有一個強大的功能就是支援宏的運算。宏在Lisp 中是使用者自定義的特殊表,按照C 程式員的思路了解,宏就是使用者自定義函數。對于宏,Lisp 處理時分成兩步完成,先展開,再求值。是以,Lisp 可以使用宏來模仿C。 C 函數肯定需要零個或者多個參數,是以Lisp可以利用宏将Lisp 代碼變成C 函數可以了解的參數(即展開),然後将控制交給C 程式(做求值),C 計算完成後,再将結果傳回給Lisp,回到編輯狀态。《Introduction to Emacs Lisp Programming》書中就給出了一個實際的例子,你可以仔細研究一下。

孟:您在序言中提到的“泛對稱”是什麼?您覺得Emacs 設計的美感展現在哪些方面?您認為這種美感是可以模仿的嗎?

洪:泛對稱是一種廣義的對稱性,而對稱性是科學的基本美感的組成要素之一。Emacs 的美感主要集中展現在“混合程式設計”(hybrid programming)上,底層C代碼的健壯和高層Emacs Lisp 代碼的靈活性與可擴充性,兩者完美地結合在Emacs這個程式身上,這使得Emacs 具有一種和諧的美,這種和諧是Emacs 強壯而又靈活的根源。我們不能要求所有的軟體都具備這樣的性質,但是這種追求美的素質卻是每一位程式員都要培養和追求的。孟德斯鸠說,當一個令人愉快的東西我們還沒有發現它的實際價值時,我們可以認為它是美的。我看這句話比較适合中國的大多數程式員:他們聽說過Emacs,但是尚不知道它的實際價值。

孟:我想冒昧地問一句,RMS選擇Lisp ,究竟是因為Lisp 真的很優秀,還是因為他對于Lisp 的熟悉?或者說,如果RMS 在今天開發GNU Emacs ,他還會選擇Lisp 嗎?會不會選擇Python,Perl 或者Java ? Lisp 的那些特質使得它更适合

上層開發?

洪:兩種原因都有。我猜想,如果RMS 今天再編寫Emacs,他一定會直接使用Guile(也就是Scheme)來寫那些Emacs Lisp 代碼。絕對不可能使用 Perl,Java,也不太可能用Python。因為這些程式設計語言盡管都有與C 的接口,但是全部都缺乏Lisp 獨有的元語言的特性(元語言特性?)。

孟:再說說下層。如果是在今天,您認為RMS還會使用C 來開發Emacs 的下層嗎?會不會用C++ 或者Objective-C 等面向對象語言?為什麼?洪:對于Emacs 的設計,他一定仍會使用C,而不會使用C++。RMS 本人并不喜歡C++,因為它太複雜,而且沒有改變C的一些固有問題。如果強制他一定不能使

用C,那麼他有可能會采用Objective-C,因為Objective-C比C++簡單多了。C++是我見到的最複雜的程式設計語言之一,對于初學者,它的門檻實在很高。

孟:現在的軟體體系結構大緻有單體結構,層次結構群組件結構。如果讓您把層次結構群組件結構做一個比較,您認為孰優孰劣?兩者可否結合起來?您覺得GNU Emacs 的經驗對此有何啟示?

洪:我一般使用函數式程式設計、指令式程式設計、面向對象程式設計這些術語。不要把這兩者對立起來!應該根據要設計的軟體本身的特點來選擇軟體的結構,而不是先假定好一個結構,然後費力地讓軟體的代碼去适應這個結構。這就是毛主席曾經教導我們說的:“上什麼山,唱什麼歌。”

孟:是否可以認為類似Java和.NET這些新近的軟體體系結構也受到了Emacs 的影響?站在 Emacs 的觀點看待COM ,Java,.NET 這些技術,您有何評價?

洪:微軟的COM 和C #技術都是專有技術的産物,是以我不打算在這裡評論它們。 至于Java,它的設計師之一 James Goslin 曾經是Lisp 社團裡的一個活躍份子,他用C寫過一個Emacs,Java的設計思想裡到處可以看到Lisp 的影響。剛才我已經提到了一個例子:位元組碼。Java程式是分兩步走的,先編譯為位元組碼,然後在虛拟機上解釋地執行位元組碼。這不是Java的首創,Lisp早在50年前就有了,隻是Java 走得更遠一些,把一種計算機内使用的位元組碼格式擴充到了所有的機器上,實作它“編寫一次、到處運作”的目的。再舉出一個例子:中繼資料。Java的位元組碼檔案以.class結尾,而在這個檔案中含有對檔案自身的說明。中繼資料的概念起源于Lisp,因為在Lisp中,程式和資料是以相同的形式表達的,程式可以當作資料處理,資料也可以編成程式進行運算。這一點C程式員可能難于了解,怎麼程式可以當作資料來處理呢?但在Lisp中,兩者在形式上的确是一緻的,都是使用符号表達式,你可能已經注意到了Lisp程式中的一對對小括号,它們就是用來标明符号表達式的。我還可以舉出一個例子:記憶體垃圾收集。Java中有記憶體垃圾自動收集機制,而這個機制是Lisp首先引入并實作的。

孟:GNU Emacs的解釋核心跟現在流行的虛拟機有什麼相同和不同之處?

洪:Emacs 的解釋器是采用Emacs Lisp 程式設計語言編寫的,它是編輯任務的執行環境,某種意義上說,這個解釋器的确就是一個虛拟機。不過Emacs Lisp這個虛拟機與以往的Lisp 語言實作版本有一個巨大的差別:以往的Lisp實作版本都是自含式的系統,而Emacs Lisp則是可以充分利用作業系統的功能的,例如敲入M-xhell 這個指令,你就可以在Emacs 中直接運作作業系統的shell,而不用退出

Emacs。你可以在Emacs 環境中收發電子郵件,排版,浏覽網頁等等。

孟:我讀那本elisp的書,知道了我在Emacs中的每一次操作,甚至每一次按鍵實際上都是在執行一個對應的表達式。這個表達式可能是elisp程式,也可能實際上是一個C程式。使用者的操作是通過某種機制與某個表達式綁定在一起的。我們可以改變這種綁定,進而讓同一個操作引發不同的表達式,表現出不同的效果。請問我的上述了解是否正确?如果是這樣的,那麼我們是不是可以說E m a c s 内部也具有一種獨特的Event-handler 架構?

洪:你的了解有一部分是對的,有一部分不準确。對的部分是:在用Emacs編輯時,你下的指令,例如 Mx ispell-region将被綁定到一個程式上,這個程式就是shell 下也可以運作的ispell,然後程式的控制交給ispell 執行。計算完成之後,再回到Emacs 的編輯狀态。不準确的部分是:Emacs 内部沒有你說的Event-Handler 架構,一切都是閱讀-求值-列印的循環,特别簡單。實際上,任何程式設計語言的最低層,都是有這麼一個機制的,畢竟無論什麼計算,最終都是由CPU 的ALU 完成的算術運算或者邏輯運算。但是Lisp 可以直接與這些機器指令互動(Lisp/Scheme 可以直接操作CPU的寄存器)。換句話說,任何程式設計語言都有Lisp的計算模型在裡面,可能絕大多數程式員從來就沒有意識到這點。從這個意義上說,Lisp 的确是一種元語言。

孟:我長期從事Win32 開發,對于Windows 中的事件做過不少思考。我認為在一個事件驅動的系統裡,有三個關鍵問題決定了整個系統的表現。我先說第一個,事件消息表示和傳遞機制。比如Win32,把所有的事件表示為一個unsigned int,附加以兩個4位元組整數作為參數(wParam, lParam),所有的事件消息,都無一例外地被強行規範化為這樣的消息格式,發送給相應的視窗對象。這樣做當然是為了滿足C這種靜态語言的條件,但是帶來的缺點是每個事件消息本身的資訊很少,必須有與之相配合的一系列外部協定,而且這些協定沒什麼規律,隻能通過文檔的形式來申明。是以在Win32 程式設計中,沒有文檔參考是不可想象的,即使有很多年的Win32 程式設計經驗,也需要不厭其煩地去查文檔。我曾經想,如果能夠發送格式自由的消息,再規定一個消息含義的規範化語言(類似printf 中的那種little language),那麼不需要很多文檔,也可以很輕松的發送消息了。現在的SOAP 協定,實際上是通過XML 在網絡上實作了這種消息協定。

洪:首先我應該告訴你,Win32 的模型與X Window的模型在本質是相似的,都是事件驅動機制。而且我還應該告訴你,最早實作的X Window系統的一個庫是用Lisp 編寫的,稱為CLX,至今還有一個X視窗管理系統的發行版 Sawfish,使用的就是Scheme,但是它設計得不太好。 你提到的這一點很有道理。 Win32與DOS 模型相比,當然是一個巨大的進步,但是它沒有徹底解決問題,因為一旦事件發生

後,被視窗的事件循環檢測機制捕捉到後,必須有事先設計好了的一套動作使用一個句柄來與之配套,事件才能往下進行處理。是以,有多少個應用程式,就會有多少種事件,就需要有多少種句柄事先就要設計好來與之比對,這是一個永遠也做不完的機制,按照陳榕博士的說法,Win32 是一個半成品。更加糟糕的是,Win32 API 底層的實作機制是不公開的,是以對于第三方開發人員而言,他們一

旦選擇了Win32,就等于“賣身”給了微軟。

Lisp/Scheme 的思想是,符号與資料對象的綁定是任意的,就像一個人可以使用多個化名一樣,你可以将任意多個符号綁定到一個對象上,然後将符号放在清單中進行操作,而清單的格式隻有一種。你可以在不同的塊結構中做不同的綁定,是以它提供了巨大的靈活性。 Scheme 一個比C++ 設計得好的方面是,Scheme的符号本身就是隐含地具有名稱、值、類型、屬性表和綁定函數表五個特征,其中類型是動态類型,根據運作時的環境而決定,Lisp/Scheme 天生就是一個面向對象的語言。C++費了牛勁才在C的基礎上得到了對多态性的支援,但是Lisp 早在50 年代就已經實作了。不同的是C++ 的虛函數表機制是基于stack 的,而Lisp是基于heap 機制的,stack 是一個“準緊湊”的資料結構,heap 中的資料則不一定都是LIFO 結構,記憶體垃圾自動收集還要損失一些速度,是以早期的Lisp 的效率與C++ 相比不算高,但是我上次講過了,目前的硬體物質基礎已經跟上來了,是以經過優化設計的Scheme 程式以編譯方式運作時是完全有可能在速度上超過C++ 程式的。Java 程式在速度上根本不是Scheme 的對手,www.schemers.org 上有一篇文章,對比Scheme 與Java 的性能,你可以研究一下。

孟:Emacs中的消息——表達式綁定給我提供了一種新的思路。您認為這種機制相對于上面提到的機制有何優勢? 在單機系統和網絡中是否都能夠适用?有沒有這方面的研究項目?

洪:平行處理能力越強的計算機,運作Lisp程式的性能越優越,日本的 NEC 在支援一項研究,技術方向就是這個樣子。從根本上說,函數計算需要非馮諾伊曼體系的支援,效率才會有大的突破,原來的方向是通過專用的晶片來搞,而目前的叢集技術為在大陸貨的硬體上得到平行計算技術的效果帶來了新的思路和希望。

孟:好的。我再說第二點:可以處理的消息數量。這主要涉及到類似MFC 的Win32 C++ wrapper。在C++ 中,上面所說的問題在名義上得到了解決。因為成員函數的參數表可以由我們自己設計。但是在C++中一個對象在運作時能夠處理什麼消息,完全是編譯時靜态決定的。給一個對象發送它并不打算處理的消息,這樣的行為在編譯時就會被禁止。表面上這維護了系統的類型安全性,但是實際上并不符合事件驅動的互動式系統對象模型。在這樣的系統中,一個對象可能需要處理的消息實際上是無限多的,隻不過實際上它隻關心其中的一部分,其他大部分它不關心的消息它隻是簡單地傳遞給一個公共處理器(DefWindowProc)來處理。可是在C++中,由于所有的消息都必須事先确定下來,系統一旦定性,就成為剛性的架構,擴充起來很困難,是以設計者必須有卓越的眼光和超前的思維,預料到可能發生的各種變化,這實際上是不可能的。是以,我認為C++對象模型與事件系統對象模型本質上是不一緻的。Emacs 借助了Lisp的動态特性,在這方面自然具有先天優勢。不過我對于Emacs内部還不了解,Emacs 内部也有很多“對象”嗎?您認為Emacs 的結構如果擴充整個應用系統甚至作業系統,依然是優越的嗎?請在這方面談談您的看法。

洪:你的了解是對的。關鍵的原因在于C++想保持與 C 的相容,它不肯放棄對stack 運作時環境的支援(如果放棄了這點的話,它就不是C++了。)這樣做的優點是程式比較緊湊,适合實作過程或者機制,但是在算法(政策)的靈活性上,它根本沒有辦法與Scheme 相比。你再結合我們的時代看看,就會同意這樣的觀點:硬體的成本總是年趨下降的,而人的成本總是在上漲的,是以程式設計語言必須具有靈活性和良好的擴充性,使人可以在相對較短的時間内拿出可以搞定問題的算法來,至于程式運算起來的效率如何,則由機器去搞定。應該說它仍是一個重要的因素,但是重要性與以往相比,則大大下降了。而且一旦某些地方對速度要求很嚴,就可以将這部分的代碼采用基于stack 的原子函數封裝掉。Emacs Lisp内部的确有很多對象,具體可以參考Emacs Lisp的參考手冊,對象的類型是在運作時動态決定的,也就是說,Lisp 天生就是支援多态性。将Lisp擴充到整個作業系統時,還有很多其他的因素要考慮,例如對于程序排程、記憶體管理、裝置的管理等,這些東西在MING 系統中都是原子函數。是以,如果一個應用程式要申請使用裝置,那麼就把裝置驅動的原子函數加入到程式的參數清單中就行了,至于程式的參數清單如何與裝置驅動去綁定,則交給運作時系統去決定和完成。當然,這裡有大量的中斷、優先級别、權限等等政策問題,這些原子函數在算法空間裡要由另外的原子函數完成聚類和離散操作(以得到計數和排序),其細節是不可避免地相當複雜的。我在國内講了很多次關于MING的設計思想,好像迄今隻有陳榕一個人真正了解我的意思。首先是一些教授和學者一聽Scheme,就不願意向下聽了,也不知他們是真的了解Scheme(進而認為這條方案不行),還是聽不懂。

孟:說實在的,第一次聽到您說用解釋語言來寫OS,我也很詫異和懷疑。以後有機會我還要為這向您請教呢。現在我們再來看第三點,消息傳遞路徑。上面的問題中說到,在GUI系統中,一個對象不關心的消息可以傳給DefWindowProc,這就構成了一個非常簡單的消息傳遞路徑。MFC為了模仿Windows 事件機制也模拟了自己的消息傳遞路徑。德國人Miro Samek把這種模式叫做“Ultimate Hook”,并且認為具體視窗對象與Windows 系統之間形成了一種inheritance關系,隻不過既不是interface inheritance,也不是implementation inheritance,而是behavior inheritance。 我想知道Emacs 中是否存在這種消息傳遞?如果從Lisp 和Scheme 出發,這種所謂的消息傳遞路徑是否有獨具風格的解決之道?

洪:我的了解是,當計算中需要很多指針傳遞時,最好是将多級指針通過符号與對象的重新綁定給“短路”掉效率最高。在C++ 中,你知道,每一次間址,都引發了更多的(設計上的)複雜性,而且每次間址運算或者函數調用,在記憶體空間裡都不可避免地引起從一個棧到另一棧的跳轉,并且最終還要傳回,這一切最終都變成了程式員的負擔。 (Scheme 要求解釋器的原子曆程和庫函數一律實作尾遞

歸。) 你說的這種消息路徑在S c h e m e 中稱為計算的連續性,Scheme 可以在記憶體空間中無限制地跳轉,進而得到上面的“短路”效果,它是程式設計語言王國中的一等公民,其他都是二等、三等公民。如果你現在一下子不了解,沒有關系,過了一段時間,你就會明白的。程式設計和計算科學的美感就集中展現在這些地方。但是遺憾的是,目前國内沒有一所大學裡,開設了Scheme 課程,進而使所有的學生都喪失掉了體會這種美感的機會。

孟:您反複提到一種叫Scheme 的語言,能不能給我們介紹一下?

洪:Lisp 有很多變種,Emacs Lisp 隻是其中一個。Scheme 也是Lisp 的一個變種,誕生于1975 年。它與它以前的Lisp 和以後的Lisp 變種都不同。除了Scheme 之外(如果你不算 Emacs Lisp),那麼所有的Lisp 現在都已經統一在Common Lisp 中了。

RMS 說過,Emacs Lisp 将來會被 Scheme 逐漸替換掉。替換Emacs Lisp 的Scheme 稱為Guile。(順便告訴你,在RMS 的頭腦中,Guile 将是GNU 系統上預設的腳本語言)。與以往的Lisp相比,Scheme最大的變化就是引入了塊結構和詞法定界兩個特點。這兩個特點大大地友善了程式員編寫程式。

孟:Lisp 族類的語言在80 年代曾經興起過,後來又平淡下去,請問這是為什麼? 您認為曆史會再給 Lisp 一個機會嗎?為什麼呢? Emacs這種體系結構以及Lisp/Scheme語言是否符合網絡互聯時代的計算模型?會不會被徹底淘汰?

洪:應該說Lisp是一批天才的創造。其中既有大量數學家的貢獻,又有一批計算機科學家的貢獻。它的産生是大大超前于它出生的那個時代的。Lisp 和Fortran 是最先發明的兩種進階語言,一個用于數字計算,一個用于符号計算,但是他們的生命力現在仍然非常強。

以前的Lisp退出主流市場的原因不是Lisp的設計思想本身有問題,而是那個時代的計算機硬體資源與它不協調。你應該明白,50 年前1MB 記憶體的造價可能是一個天文數字。 八十年代時局面仍然沒有根本的改觀,但是進入二十一世紀後,計算機上的CPU與RAM資源都有了質的飛躍,而且現在還可以嘗試使用“非馮諾伊曼”體系的并行計算機來運作Lisp 程式,Lisp 終于迎來了它的生命第二春。

Scheme是一個非常适合編寫網絡程式的語言。例如,你可以使用它編寫CGI程式。原因我剛才已經說過了,Scheme 的程式與資料是采用相同格式表達的,現在網際網路上流行的XML 就是Lisp 程式的一種更加醜陋的變形。

孟:如果我現在想開發一個軟體,打算學習和模仿GNU Emacs 的體系架構,我是不是上來就得寫一個Lisp解釋器?這是不是有點不現實?好像快渴死的人跑去種西瓜一樣。模仿GNU Emacs 體系架構有沒有什麼變通的方法?

洪:不應該采用這種本末倒置的方法來學習程式設計。我認為正确的方法應該是先了解Lisp背後的思想,特别是數學方面的關于計算本質的思想。我剛才說過,Lisp 背後的思想是許多數學家和計算機科學家長期思考的結果,這些東西是不會過時的。你難道聽說過有什麼數學定理過時嗎?!隻有了解了這些問題的實質,那麼你眼中的Lisp會是另一個完全不同的模樣。

孟:最後一個問題,聽說您正在積極準備一個“黑客道”教育訓練。能給我們簡單介紹一下嗎?

洪:“黑客道”教育訓練計劃是“一、百、萬”工程的一個重要組成部分,目的在于為自由軟體社團教育訓練大量的人才。

你可能注意到這樣的一個事實:許多計算機專業的大學生學習四年畢業後不會編寫程式,缺乏動手實踐的能力,這不能全怪這些學生學習不努力,而是我們的人才培養模式上存在重大的缺陷。我個人認為,目前國内軟體界最缺乏的就是進階程式員,而目前高校的這種落後的教育體制下是難以培養出黑客的。

“黑客道”的教育訓練計劃是綜合運用泛系理論和自由軟體的産物,是培養計算機黑客的“生産線”。通過系統的教育訓練,智商中等的學員可以在相對較短的時間内成為進階程式員,進階程式員可以像小汽車一樣從流水線上批量地生成出來。以往絕大多數人認為程式設計是需要創新的工作,程式員是難以按照程式化的工序一步一步訓練出來的。黑客道教育訓練計劃通過實踐證明這是一種錯誤的觀點,盡管編寫軟體是需要高度創造性的,但是培養具有創新精神的程式員的活動是有内在規律的,是有章可循的。“黑客道”教育訓練計劃以往的探索在這一點上取得了初步的成功。

孟:非常感謝您。這次專訪的内容我會生成PDF文檔交給您審校。

洪:你用什麼生成PDF 文檔?

繼續閱讀