Total Pageviews

2013/03/28

JPA Lifecycle Events Practice


2013/03/08

什麼是“對用戶友好”



當我提到一個工具“對用戶不友好”(user-unfriendly)的時候,我總是被人“鄙視”。難道這就叫“以其人之道還治其人之身”?想當年有人對我抱怨 Linux 或者 TeX 對用戶不友好的時候,我貌似也差不多的態度吧。現在當我指出 TeX 的各種缺點,提出新的解決方案的時候,往往會有美國同學眼角一抬,說:“菜鳥們抱怨工具不好用,那是因為他們不會用。LaTeX 是‘所想即所得’,所以不像 Word 之類的上手。”

殊不知他面前這個“菜鳥”,其實早已把 TeX 的配置搞得滾瓜爛熟,把 TeXbook 翻來覆去看了兩遍,"double bend" 的習題都全部完成,可以用 TeX 的語言來寫巨集包。而他被叫做“菜鳥”,這是一個非常有趣的問題。所以現在拋開個人感情不談,我們來探討一下這種“鄙視”現象產生的原因,以及什麼叫做“對用戶友好”。

首先我們從心理的角度來分析一下為什麼有人對這種“對用戶不友好”的事實視而不見,而稱抱怨的用戶為“菜鳥”。這個似乎很明顯,答案是“優越感”。如果每個人都會做一件事情,如何能體現出我的超群智力?所以我就是要專門選擇那種最難用,最晦澀,最顯得高深的東西,把它折騰會。這樣我就可以被稱為“高手”,就可以傲視群雄。我不得不承認,我以前也有類似的思想。從上本科以來我就一直在想,同樣都會寫程式,是什麼讓電腦系的學生與非電腦系的學生有所不同?經過多年之後的今天,我終於得到了答案(以後再告訴你)。可是在多年以前,我犯了跟很多人一樣的錯誤:把“難度”與“智力”或者“專業程度”相等同。但是其實,一個人會用難用的工具,並不等於他智力超群或者更加專業。

可惜的是,我發現世界上有非常少的人明白這個道理。在大學裡,公司裡,彰顯自己對難用的工具的掌握程度的人比比皆是。這不只是對於電腦系統,這也針對數學以及邏輯等抽象的學科。經常聽人很自豪的說:“我準備用XX邏輯設計一個公理化的系統……”可是這些人其實只知道這個邏輯的皮毛,他們會用這個邏輯,卻不知道它裡面所有含混晦澀的規則都可以用更簡單更直觀的方法推導出來。

愛因斯坦說:“Any intelligent fool can make things bigger and more complex... It takes a touch of genius - and a lot of courage to move in the opposite direction.”我現在深深的體會到這句話的道理。想要簡化一個東西,讓它更“好用”,你確實需要很大的勇氣。而且你必須故意的忽略這個東西的一些細節。但是由於你的身邊都是不理解這個道理的人,他們會把你當成菜鳥或者白癡。即使你成功了,可能也很難說服他們去嘗試這個簡化後的東西。

那麼現在我們來談一下什麼是“對用戶友好”。如何定義“對用戶友好”?如何精確的判斷一個東西是否對用戶友好?我覺得這是一個現在仍然非常模糊的概念,但是程式語言的設計思想,特別是其中的類型理論(type theory)可以比較好的解釋它。我們可以把機器和人看作同一個系統:

  1. 這個系統有多個模組,包括機器模組和人類別模組。
  2. 機器模組之間的介面使用通常的程式介面。
  3. 人機交互的介面就是機器模組和人類別模組之間的介面。
  4. 每個介面必須提供一定的抽象,用於防止使用者得到它不該知道的細節。這個使用者可能是機器模組,也可能是人類別模組。
  5. 抽象使得系統具有可擴展性。因為只要介面不變,模組改動之後,它的使用者完全不用修改。

在機器的各個模組間,抽象表現為函數或者方法的類型(type),程式的模組(module)定義,作業系統的系統調用(system call),等等。但是它們的本質都是一樣的:他們告訴使用者“你能用我來幹什麼”。很多程式師都會注意到這些機器介面的抽象,讓使用者儘量少的接觸到實現細節。可是他們卻往往忽視了人和機器之間的介面。也許他們沒有忽視它,但是他們卻用非常不一樣的設計思想來考慮這個問題。他們沒有真正把人當成這個系統的一部分,沒有像對待其它機器模組一樣,提供具有良好抽象的介面給人。他們貌似覺得人應該可以多做一些事情,所以把紛繁複雜的程式內部結構暴露給人(包括他們自己)。所以人對“我能用這個程式幹什麼”這個問題總是很糊塗。當程式被修改之後,還經常需要讓人的操作發生改變,所以這個系統對於人的可擴展性就差。通常程式師都考慮到機器各介面之間的擴展性,卻沒有考慮到機器與人之間介面的可擴展性。

舉個例子。很多 Unix 程式都有設定檔,它們也設置環境變數,它們還有命令列參數。這樣每個用戶都得知道設定檔的名字,位置和格式,環境變數的名字以及意義,命令列參數的意義。一個程式還好,如果有很多程式,每個程式都在不同的位置放置不同名字的設定檔,每個設定檔的格式都不一樣,這些配置會把人給搞糊塗。經常出現程式說找不到設定檔,看手冊吧,手冊說設定檔的位置是某某環境變數 FOO 決定的。改了環境變數卻發現沒有解決問題。沒辦法,只好上論壇問,終於發現設定檔起作用當且僅當在同一個目錄裡沒有一個叫 ".bar" 的文件。好不容易記住了這條規則,這個程式升級之後,又把規則給改了,所以這個用戶又繼續琢磨,繼續上論壇,如此反復。也許這就叫做“折騰”?他何時才能幹自己的事情?

TeX 系統的配置就更為麻煩。成千上萬個小檔,很少有人理解 kpathsea 的結構和用法,折騰好久才會明白。但是其實它只是解決一個非常微不足道的問題。TeX 的語言也有很大問題,使得擴展起來非常困難。這個以後再講。

一個良好的介面不應該是這樣的。它給予使用者的介面,應該只有一些簡單的設定。使用者應該用同樣的方法來設置所有程式的所有參數,因為它們只不過是一個從變數到值的映射(map)。至於系統要在什麼地方存儲這些設定,如何找到它們,具體的格式,用戶根本不應該知道。這跟高階語言的運行時系統(runtime system)的記憶體管理是一個道理。程式請求建立一個物件,系統收到指令後分配一塊記憶體,進行初始化,然後把物件的引用(reference)返回給程式。程式並不知道物件存在於記憶體的哪個位置,而且不應該知道。程式不應該使用物件的位址來進行運算。

所以我們看到,“對用戶不友好”的背後,其實是程式設計的不合理使得它們缺少抽象,而不是用戶的問題。這種對用戶不友好的現象在 WindowsMaciPhone, Android 裡也普遍存在。比如幾乎所有 iPhone 用戶都被洗腦的一個錯誤是“iPhone 只需要一個按鈕”。一個按鈕其實是不夠的。還有就是像 Photoshop, Illustrator, Flash 之類的軟體的功能表介面,其實把使用者需要的功能和設置給掩藏了起來,分類也經常出現不合理現象,讓他們很難找到這些功能。

如何對用戶更加友好,是一兩句話說不清楚的事情。所以這裡只粗略說一下我想到過的要點:

  1. 統一:隨時注意,人是一個統一的系統的一部分,而不是什麼古怪的神物。基本上可以把人想像成一個程式模組。
  2. 抽象:最大限度的掩蓋程式內部的實現,儘量不讓人知道他不必要知道的東西。不願意暴露給其它程式模組的細節,也不要暴露給人。“機所不欲,勿施於人”。
  3. 充要:提供給人充分而必要(不多於)的機制來完成人想完成的任務。
  4. 正交:機制之間應該儘量減少冗餘和重疊,保持正交(orthogonal)
  5. 組合:機制之間應該可以組合(compose),儘量使得幹同一件事情只有一種組合。
  6. 理性:並不是所有人想要的功能都是應該有的,他們經常欺騙自己,要搞清楚那些是他們真正需要的功能。
  7. 通道:人的輸入輸出包括5種感官,雖然通常電腦只與人通過視覺和聽覺交互。
  8. 直覺:人是靠直覺和模型(model)思考的,給人的資訊不管是符號還是圖形,應該容易在人腦中建立起直觀的模型,這樣人才能高效的操作它們。
  9. 上下文:人腦的“快取記憶體”的容量是很小的。試試你能同時想起7個人的名字嗎?所以在任一特定時刻,應該只提供與當前被關注物件相關的操作,而不是提供所有情況下的所有操作供人選擇。上下文功能表和依據上下文的鍵盤操作提示,貌似不錯的主意。


談 Linux,Windows 和 Mac



這段時間受到很多人的來信。他們看了我很早以前寫的推崇 Linux 的文章,想知道如何“拋棄 Windows,學習 Linux”。天知道他們在哪裡找到那麼老的文章,真是好事不出門…… 我覺得我有責任消除我以前的文章對人的誤導,洗清我這個“Linux 狂熱分子”的惡名。我覺得我已經寫過一些澄清的文章了,可是怎麼還是有人來信問 Linux 的問題。也許因為感覺到“輿論壓力”,我把文章都刪了。

簡言之,我想對那些覺得 Linux 永遠也學不會的“菜鳥”們說:


  1. Linux Unix 裡面包含了一些非常糟糕的設計。不要被 Unix 的教條主義者嚇倒。學不會有些東西很多時候不是你的錯,而是 Linux 的錯,是“Unix 思想” 的錯。不要浪費時間去學習太多工具的用法,鑽研稀奇古怪的命令列。那些貌似難的,複雜的東西,特別要小心分析。
  2. Windows 避免了 UnixLinux Mac OS X 的很多問題。微軟是值得尊敬的公司,是真正在乎程式開發工具的公司。我收回曾經對微軟的鄙視態度。請菜鳥們吸收 Windows 設計裡面好的東西。另外 Visual Studio 是非常好的工具,會帶來程式設計效率的大幅度提升。請不要歧視 IDE。請正視 EmacsVIM 等文字編輯器的局限性。
  3. 學習作業系統最好的辦法是學會(真正的)程式設計思想,而不是去“學習”各種古怪的工具。所有作業系統,資料庫,Internet,以至於 WEB 的設計思想(和缺陷),幾乎都能用程式語言的思想簡單的解釋。
先說說我現在對 Linux 和相關工具(比如 TeX)的看法吧。我每天上班都用 Linux,可是回家才不想用它呢。上班的時候,我基本上只是盡我所能的改善它,讓它不要給我惹麻煩。Unix 有許許多多的設計錯誤,卻被當成了教條,傳給了一代又一代的程式師,惡性循環。Unix shell,命令,配置方式,圖形介面,都是相當糟糕的。每一個新版本的 Ubuntu 都會在圖形介面的設計上出現新的錯誤,讓你感覺歷史怎麼會倒退。其實這只是表面現象。Linux 所用的圖形介面(X Window)在本質上幾乎是沒救的。我不想在這裡細說 Unix 的缺點,在它出現的早期,已經有人寫了一本書,名叫 Unix Hater's Handbook,裡面專門有一章叫做 The X-Windows Disaster。它分析後指出,X Window 貌似高明的 client-server 設計,其實並不像說的那麼好。

這本書彙集了 Unix 出現的年代,很多人對它的咒駡。有趣的是,這本書有一個“反序言”,是 Unix 的創造者之一 Dennis Ritchie 寫的。我曾經以為這些罵 Unix 的人都是一些菜鳥。他們肯定是智商太低,或者被 Windows 洗腦了,不能理解 Unix 的高明設計才在那裡駡街。現在理解了程式語言的設計原理之後,才發現他們說的那些話裡面居然大部分是實話!其實他們裡面有些人在當年就是世界頂尖的程式設計高手,自己寫過作業系統和編譯器,功底不亞于 Unix 的創造者。在當年他們就已經使用過設計更加合理的系統,比如 MulticsLisp Machine 等。

可惜的是,在現在的作業系統書籍裡面,Multics 往往只是被用來襯托 Unix 的“簡單”和偉大。Unix 的書籍喜歡在第一章講述這樣的歷史:“Multics 由於設計過於複雜,試圖包羅萬象,而且價格昂貴,最後失敗了。” 可是 Multics 失敗了嗎?MulticsOberonIBM System/38 Lisp Machine,…… 在幾十年前就擁有了 Linux 現在都還沒有的好東西。Unix 裡面的東西,什麼虛擬記憶體,檔案系統,…… 基本上都是從 Multics 學來的。Multics 的機器,一直到 2000 年都還在運行。Unix 不但“竄改”了歷史教科書,而且似乎永遠不吸取教訓,到現在還沒有實現那些早期系統早就有的好東西。Unix 的設計幾乎完全沒有一致性和原則。各種工具程式功能重複,冗餘,沒法有效地交換資料。可是最後 Unix 靠著自己的“廉價”,“宗教”和“哲學”,戰勝了別的系統在設計上的先進,統治了程式師的世界。

如果你想知道這些“失敗的”作業系統裡面有哪些我們現在都還沒有的先進技術,可以參考這篇文章:Oberon - The Overlooked Jewel。它介紹的是 Niklaus Wirth(也就是 Pascal 語言的設計者)的 Oberon 作業系統。

勝者為王,可是 Unix 其實是一個暴君,它不允許你批評它的錯誤。它利用其它程式師的輿論壓力,讓每一個系統設計上的錯誤,都被說成是用戶自己的失誤。你不敢說一個工具設計有毛病,因為如果別人聽到了,就會以為你自己不夠聰明,說你“人笨怪刀鈍”。這就像是“皇帝的新裝”裡的人們,明明知道皇帝沒穿衣服,還要說“這衣服這漂亮”!總而言之,“對用戶友好”這個概念,在 Unix 的世界裡是被歧視,被曲解的。Unix 的狂熱分子很多都帶有一種變態的“精英主義”。他們以用難用的工具為豪,鄙視那些使用“對用戶友好”的工具的人。

我曾經強烈的推崇 FVWMTeX 等工具,可是現在擦亮眼睛看來,它們給使用者的介面,其實也是非常糟糕的設計,跟 Unix 一脈相承。他們把程式設計的許多沒必要的細節和自己的設計失誤,無情的暴露給用戶。讓用戶感覺有那麼多東西要記,仿佛永遠也沒法掌握它。實話說吧,當年我把 TeXbook 看了兩遍,做完了所有的習題(包括最難的“double bend”習題)。幾個月之後,幾乎全部忘記乾淨。為什麼呢?因為 TeX 的語言是非常糟糕的設計,它沒有遵循程式語言設計的基本原則。

這裡有一個鮮為人知的小故事。TeX 之所以有一個“擴展語言”,是 Scheme 的發明者 Guy Steele 的建議。那年夏天,Steele Stanford 實習。他聽說 Knuth 在設計一個排版系統,就強烈建議他使用一種擴展語言。後來 Knuth 採納了他的建議。不幸的是 Steele 幾個月後就離開了,沒能説明 Knuth 完成語言的設計。Knuth 老爹顯然有我所說的那種“精英主義”,他咋總是設計一些難用的東西,寫一些難懂的書? 

一個好的工具,應該只有少數幾條需要記憶的規則,就像象棋一樣。而這些源於 Unix 的工具卻像是“魔鬼棋”或者“三國殺”,有太多的,無聊的,人造的規則。有些人鄙視圖形介面,鄙視 IDE,鄙視含有垃圾回收的語言(比如 Java),鄙視一切“容易”的東西。他們卻不知道,把自己沉浸在別人設計的繁複的規則中,是始終無法成為大師的。就像一個人,他有能力學會各種“魔鬼棋”的規則,卻始終無法達到象棋大師的高度。所以,容易的東西不一定是壞的,而困難的東西也不一定是好的。學習電腦(或者任何其它工具),應該“只選對的,不選難的”。記憶一堆的命令,烏七八糟的工具用法,最後腦子裡什麼也不會留下。學習“原理性”的東西,才是永遠不會過時的。 

Windows 技術設計上的很多細節,也許在早期是同樣糟糕的。但是它卻向著更加結構化,更加簡單的方向發展。Windows 的技術從 OLECOM,發展到 .NET,再加上 Visual Studio 這樣高效的程式設計工具,這些帶來了程式師和用戶效率的大幅度提高,避免了 Unix C 語言的很多不必存在的問題。Windows 程式從很早的時候就能比較方便的交換資料。比如,OLE 讓你可以把 Excel 表格嵌入到 Word 文檔裡面。不得不指出,這些是非常好的想法,是超越“Unix 哲學”的。相反,由於受到“Unix 哲學”的誤導,Unix 的程式間交換資料一直以來都是用字串,而且格式得不到統一,以至於很多程式連拷貝粘貼都沒法正確進行。Windows 的“配置”,全都記錄在一個中央資料庫(註冊表)裡面,這樣程式的配置得到大大的簡化。雖然在 Win95 的年代,註冊表貌似老是惹麻煩,但現在基本上沒有什麼問題了。相反,Unix 的配置,全都記錄在各種稀奇古怪的設定檔裡面,分佈在系統的各個地方。你搞不清楚哪個設定檔記錄了你想要的資訊。每個設定檔連語法都不一樣!這就是為什麼用 Unix 的公司總是需要一個“系統管理員”,因為軟體工程師們才懶得記這些麻煩的東西。

再來比較一下 Windows Mac 吧。我認識一個 Adobe 的高級設計師。他告訴我說,當年他們把 Photoshop 移植到 Intel 構架的 Mac,花了兩年時間。只不過換了個處理器,移植個應用程式就花了兩年時間,為什麼呢?因為 Xcode 比起 Visual Studio 真是差太多了。而 Mac OS X 的一些設計原因,讓他們的移植很痛苦。不過他很自豪的說,當年很多人等了兩年也沒有買 Intel 構架的 Mac,就是因為他們在等待 Photoshop。最後他直言不諱的說,微軟其實才是真正在乎程式師工具的公司。相比之下,Apple 雖然對用戶顯得友好,但是對程式師的介面卻差很多。Apple 尚且如此,Linux 對程式師就更差了。可是有啥辦法呢,有些人就是受虐狂。自己痛過之後,還想讓別人也痛苦。就像當年的我。

我當然不是人云亦云。微軟在程式語言上的造詣和投入,我看得很清楚。我只是通過別人的經歷,來驗證我已經早已存在的看法。所以一再宣揚別的系統都是向自己學習的 Apple 受到這樣的評價,我也一點不驚訝。Mac OS X 畢竟是從 Unix 改造而來的,還沒有到脫胎換骨的地步。我有一個 Macbook Air,一個 iPhone 5,和一個退役的,裝著 Windows 7 T60。我不得不承認,雖然我很喜歡 Macbook iPhone 的硬體,但我發現 Windows 在軟體上的很多設計其實更加合理。

我為什麼當年會鄙視微軟?這很簡單。我就是跟著一群人瞎起哄而已!他們說 Linux 能拯救我們,給我們自由。他們說微軟是邪惡的公司…… 到現在我身邊還有人無緣無故的鄙視微軟,卻不知道理由。可是 Unix 是誰製造的呢?是 AT&T。微軟和 AT&T 哪個更邪惡呢?我不知道。但是你應該瞭解一下 Unix 的歷史。AT&T 當年發現 Unix 有利可圖,找多少人打了多少年官司?說微軟搞壟斷,其實 AT&T 早就搞過壟斷了,還被拆散成了好幾個公司。想想世界上還有哪一家公司,獨立自主的設計出這從底至上全套家什:程式語言,編譯器,IDE,作業系統,資料庫,辦公軟體,遊戲機,手機…… 我不得不承認,微軟是值得尊敬的公司。

公司還不都一樣,都是以利益為本的。我們程式師就不要被他們利用,作為利益鬥爭的炮眼啦。見到什麼好就用什麼,就學什麼。自己學到的東西,又不屬於那些壟斷企業。我們都有自由的頭腦。

當然我不是在這裡打擊 Linux Mac 而鼓吹 Windows。這些系統的紛爭基本上已經不關我什麼事。我只是想告訴新人們,去除頭腦裡的宗教,偏激,仇恨和鄙視。每次仇恨一個東西,你就失去了向它學習的機會。