2012年2月11日星期六

讀書心得: 程式設計師提昇生產力秘笈

More about 程式設計師提升生產力秘笈
原文書名:Productive Programmer
(對岸譯『卓有成效的程序員』,我比較喜歡這個名字。)

「程式設計師提升生產力秘笈」這本書非常有趣,它並不打算教你一套新的程式心法或者尖端技術,他想要做的事情是「扭轉你從小到大操作電腦的習慣」。有一點莫名其妙是吧,不過讀過這本書之後,我發現自己的不良的操作習慣,甚至一般人習以為常的操作習慣,真的很浪費時間。

啟動板

啟動板「Launchy」是我打開書後第一個安裝的小工具軟體,而且用了五分鐘後我就愛上它了!平常我們想要啟動一隻程式,例如打開 Word,會怎麼做呢?當然是先把滑鼠移到螢幕左下角點擊「開始功能表」、展開「程式集」、選擇「Office」目錄、最後用滑鼠敲一下程式的捷徑。這個過程一般人已經習以為常,不以為怪;而啟動版Launchy讓你直接這樣幹:按下Alt+Space叫出啟動板,然後敲W-O-R-D四個鍵就行了。(甚至只要敲W,啟動版就替你挑出最常用的程式),傳統的方法相較之下簡直是繁文縟節。

這例子很小,但是隱約帶出了幾個本書強調的原則:

第一、用搜尋取代瀏覽。隨著使用電腦的時間越久,應用程式的清單就會越來越長,而長度正好和其用處成反比,清單越長,效率就越低。啟動版可以幫助你跳過這段用眼睛上下找尋瀏覽的時間,保證啟動程式的動作永遠是O(1)。第二、啟動版可以隔離那些會讓人不小心分心的事物。從你想要啟動某個程式,到程式真的運行起來之間,不會有瞥見一眼就丟掉十幾分鐘的東西,例如 RSS Reader,或者是某個你之前就很有興趣但是一直沒時間看的漂亮網頁。第三、手不需要離開鍵盤。程序員大多時間都把手放在鍵盤上,滑鼠雖然直覺,但是速度永遠比不上鍵盤,手臂在鍵盤滑鼠之間移動也是很慢的一件事情。附帶一提,我的桌面現在非常乾淨,只有一個垃圾桶跟幾個常用檔案,因為那些花花綠綠的圖示跟捷徑都不再需要了,呵呵。

上面提到的這幾項都是書中不斷重複出現的中心思想,用搜尋取代瀏覽,排除讓你分心的事物,鍵盤永遠比滑鼠好,以及最重要的,不要不停的重複做同一件事。

漂亮的GUI是效率的障礙

「重複做同樣的事」是軟體開發裡面最嚴重的效率傷害,通常我們把他稱作 D.R.Y (Don't Repeat Yourself  ) 原則,這不光只是程式碼複製貼上而已,操作電腦的習慣也有DRY,例如重複來回地在兩個視窗之間複製貼上,手動修改一份文件裡的幾十個同樣的格式錯誤,或者在許多目錄之間來回的瀏覽翻找一個檔案。重複動作有雙重傷害:浪費時間,而且會傷害專注力。書裡有幾段話節錄:
『對使用者有生產力的事情(漂亮的GUI、滑鼠、下拉式選單等等)實際上可能是某人試著讓電腦發揮最大效能的障礙。』
『最近幾十年來最大的諷刺之一就是,高手執行日常任務的速度變慢了。往昔Unix的傢伙都比較有效率,因為他們把一切都自動化了。』
我看了很震撼,回想起之前我剛開始用 CodeIgniter Framework 寫網站的時候,因為一個網頁程式被切成M-V-C三隻檔案,所以我往往必須一直用滑鼠去點分頁,手不斷地在滑鼠跟鍵盤之間移動,這些重複的操作把我弄得很痛苦,但是卻不知道要怎麼改善。

現在我開始轉變自己的心態,放開心胸去學習那些以前看起來不太友善的東西。比方說,書裡說道『IDE有大量鍵盤捷徑,全都學!』我就把eclipse快捷鍵全部翻出來作成一份清單放在案前。以前我寫PHPUnit,一個檔案裡總會出現幾十次$this->assertEquals($v1, $v2);,現在我把它編成 Code Template,我現在只要打 aeq+Tab 就會自動展開句子。比方說看起來就很難懂的 vim 、 Regular Expression 還有命令列工具。我的觀念從原本的基本會用就好,轉為積極的去探究IDE的極限。程序員應該是使用工具的終極高手。只要一件工具能讓你效率倍增,就值得多花時間學習掌握。

電腦是重複工作的能手

我想我被本書影響最大的一點就是對 D.R.Y 原則的敏感程度吧,由一般人的程度拉高到靈敏有如狗鼻子,每當察覺自己做了同一件事兩三次後,就思考如何讓電腦代勞。書中到處可見一支支用Script Language (Ruby/Python/Perl) 隨手捏成的小程式,作者甚至連每天要固定開啟數個 Excel 檔案都寫成 Ruby 程式。第一次可能會多花費一點時間來撰寫Script,但是他的論點很簡單『想出聰明的方法讓任務自動化,可讓你變精明,因為一路上你得學點什麼。』而這個加速過程是正向循環,越熟悉工具,就能把更多任務自動化,人手熟練有先天的速度極限,而電腦的自動化幾乎沒有極限。

這本書的前半段就是一個收集很多技巧的大錦囊,總共有四大原則幾十條內容。總結來說吧,作者認為Unix上操作電腦的方法跟工具很有效,但現今已逐漸失傳,於是作者打算撥亂反正,把這些訣竅重新挖出來分享給大家,而且試圖證明這些訣竅在Win、Mac上一樣可以實現。

後半段則是一系列思考軟體開發的散文集。我很喜歡其中的一篇,用一個漂亮的例子說明TDD不只消極的防止bug,還能積極的影響軟體本身的設計。應用TDD的程式最後會切割成許多很小、不可分割的運算,正好呼應Code Complete裡的優良函數的特性「內聚力強」、「耦合力弱」。有機會我再把後半段也吸收消化成另一篇讀書心得。

這裡有兩篇我認為跟本書呼應的文章,相當值得一看:
Vgod追求神乎其技的程式設計(十): 程式員生產力之謎
軟體開發之建置風險的故事

2011年11月4日星期五

9. 空間轉換 - OpenGL FAQ

9.001 我搞不定空間轉換啦。我可以去哪兒學習了解矩陣這東西?

基本矩陣數學與線性代數的詳細解說已經超出了本FAQ的範圍,這些內容美國的高中課程會教。如果你已經學過了,只是現在有點混淆 (老手也有的常見問題),去讀 Steve Baker 的矩陣觀念複習尤拉角度的文章

這兒有向量、矩陣、四元數運算的 Delphi 基本演示代碼

9.005 OpenGL 矩陣是 column-major 還是 row-major 呢?

以編程觀點來看,OpenGL矩陣是個陣列,有16個數值,四個基底向量依序地擺放在記憶體中。陣列的索引值編號為 1~16,其中位移分量(Translate Component) 佔據了16值的陣列的第13、14、15號元素,這些內容都寫在 OpenGL 2.1 規格書的 2.11.2 小節。

Column-major 與 Row-major 表示法純粹只是慣例上的差別。請注意,把向量乘在 column-major 矩陣的後頭,跟把向量乘在 row-major 矩陣的前頭,產生的結果完全相同。OpenGL規格書與OpenGL參考手冊雙雙採用了 column-major 表示法。只要夠明確清楚,你用任何一種表示法都行。

但不幸地,規格書跟藍皮書中的 columr-major 格式,已經造成了 OpenGL社群無止盡的混淆。因為 Column-major 表示法建議的記憶體布局不同於一般編程的期望。

9.010 OpenGL坐標系使用什麼長度單位呢?

短答案: 你想要單位是什麼就是什麼。

依據於你的幾何資料,應用程式可以把OpenGL座標單位視為毫米(millimeter) / 秒差距 (parsec) 或者任意更大或更小的長度單位,端賴哪種對你會比較方便。

OpenGL也允許你指定不同的坐標系單位。比方說,你覺得這樣做比較方便,飛機控制以公分為單位,但是機身使用單位公尺,翱翔在單位是公里的世界天空中。OpenGL 的 ModelView 矩陣可以隨意縮放不同的座標系統,最後落於同一個眼空間座標中。

建立適切的投影矩陣跟ModelView矩陣是應用程式的責任,確保觀看者有適當的距離、視角、而且近平面跟遠平面都位於適當的範圍。比方說,一個展示微米尺度級的分子應用程式的鏡頭就不該放在10呎遠,且視角60度寬。

9.020 我要如何只針對場景裡的一個物體作空間轉換,或者對每個物體做它自己的空間轉換? How do I transform only one object in my scene or give each object its own transform?

OpenGL 特別提供了矩陣堆疊(matrix stacks) 來達成這個目標。在這裡,我們用 ModelView 矩陣堆疊。

OpenGL provides matrix stacks specifically for this purpose. In this case, use the ModelView matrix stack.

A typical OpenGL application first sets the matrix mode with a call to glMatrixMode(GL_MODELVIEW) and loads a viewing transform, perhaps with a call to gluLookAt().More information is available on gluLookAt().

Then the code renders each object in the scene with its own transformation by wrapping the rendering with calls to glPushMatrix() and glPopMatrix(). For example:

glPushMatrix();
glRotatef(90., 1., 0., 0.);
gluCylinder(quad,1,1,2,36,12);
glPopMatrix();
The above code renders a cylinder rotated 90 degrees around the X-axis. The ModelView matrix is restored to its previous value after the glPopMatrix() call. Similar call sequences can render subsequent objects in the scene.

2011年10月30日星期日

OpenGL 常見問答集與錯誤排除指南

此份文件翻譯自『OpenGL FAQ and Troubleshooting Guide』
來源是 http://www.opengl.org/resources/faq/technical/

1.010簡介
這份 OpenGL Technical FAQ and Troubleshooting Guide 將回答一些基本技術問題,並解釋經常被誤解的主題、特性與觀念。本FAQ裡的所有的文字以及範例代碼都屬於公共領域,文字、範例碼、程式片段都可以自由使用與複製。超連結後的文字與範例代碼則不屬於此份FAQ的範圍,所以可能不屬於公共領域,使用它們可能會受限。

目錄

  1. 關於本FAQ 
  2. 入門
  3. GLUT
  4. GLU
  5. MS Windows 平台特定細節
  6. 視窗、緩衝區、及繪圖文本
  7. 視窗系統互動、作業系統、和輸入設備
  8. 使用視圖(Viewing)與相機鏡頭(Camera)轉換,以及 gluLookAt()
  9. 空間轉換 
  10. 裁切、剔除(Culling) 與能見度測試
  11. 色彩
  12. 深度緩衝區 (Depth Buffer)
  13. 畫線於多邊形上以及多邊形偏移
  14. 光柵化(Resterization) 與Framebuffer操作
  15. 透明、半透明與混合使用
  16. 顯示列表(display list)與頂點陣列(vertex array)
  17. 字型
  18. 照明和陰影
  19. 曲線、平面與求值器
  20. 選擇
  21. 紋理貼圖映射
  22. 效能問題
  23. 擴展與版本
  24. 雜七雜八

歡迎指正任何翻譯錯誤,或者發patch給我XD。

更新歷程
2011/10/29 翻譯計畫開始
2011/10/30 完成 3.GLUT
2011/11/04 完成 8. 使用視圖與相機鏡頭轉換,以及gluLookAt()
2012/01/05 開始 9. 空間轉換