2010年12月31日

yUML - 線上繪製UML的免費服務

yUML(http://yuml.me)提供線上UML繪製服務,只要呼叫它的API,傳入以純文字描述的UML繪製語法,就可以產生一組簡易的UML圖。目前提供的圖型種類有:Class Diagram、Activity Diagram及Use Case Diagram,雖然它只能無法繪製複雜的圖型,不過當我們需要用UML圖來表示一個簡單的概念時,這個服務就能派上用場。

使用 yUML API 很簡單,只要複製及修改以下的圖片位址。
http://yuml.me/diagram/class/[Customer]+1->*[Order], [Order]++1-items >*[LineItem], [Order]-0..1>[PaymentMethod]

藍字部分是指定產生哪一種類型的圖,紅字的部分必須需要經過UML編碼。以下是來自 yUML 提供的一些範例。


# Cool UML Diagram
[Customer]+1->*[Order]
[Order]++1-items >*[LineItem]
[Order]-0..1>[PaymentMethod]

Class Diagram

(start)->logged in->(Show Dashboard)->|a|->(end)
not logged in->(Show Login)->|a|

Activity Diagram

[User]-(Login)
[User]-(Logout)
(Login)<(Reminder) (Login)>(Captcha)

Use Case Diagram

創造週期性的點閱人潮

想要在某個時間點一到,網站就不斷被點閱嗎?其實有個小撇步可以應用,讓網站在設定的期間,不斷湧入人潮,而且不花一毛錢廣告。

說穿了方法很簡單,就是掌握關鍵字的趨勢,而且是週期性的熱門關鍵字。如此一來,花一次工夫建置好的內容,就可以每年都帶來一些流量成長。右圖是我以自己的網站做的實驗,在12/01至12/31之間的流量變化,說明了這個方法的有效。

Google Analytics的統計報表可以清楚掌握流量的變化,而Google Trends則是輔助用來創造流量的工具。下圖是一張Google Trends產生的統計圖表,在每年年底形成一根長柱,而且逐年遞增,請猜猜看這張圖用什麼關鍵字產生?


答案很顯而易見,就是「跨年」這個關鍵字。也就是說,在這個關鍵字熱潮來臨之前,先把網頁內容提早準備好,就有機會在這段期間創造流量成長。而提早多久準備內容,也是一個需要考慮的因素,過早準備好的內容會失去新穎性,少掉了一些被連結及點閱的機會;太接近才準備的內容可能來不及被搜尋引擎登錄。

但也不是週期性的熱門關鍵字都會逐年成長,下圖就是一張逐年衰退的例子。
「音樂祭」的關鍵字趨勢統計

2010年12月28日

推薦幾個適合HTPC的多媒體播放程式

現在的高畫質液晶電視都支援VGA、HDMI輸入,應該有不少朋友使用HTPC當作客廳的多媒體播放機吧!在播放高清畫質(Full HD)的影片,使用不同的軟體播放,效果會有些許差異,如果很在意播放品質,可以多試試幾套多媒體播放程式,調整一下最佳化設定,就可以讓影片更流暢、清晰一些。以下依照個人測試後,從效果最好到普通的排序。

Potplayer (http://tvpot.daum.net/video/live/PotplayerSpec.do)
The KMPlayer (http://www.kmplayer.com/korea/index.php)
Splayer 射手播放器 (http://www.splayer.org/)
K-Lite Mega Codec Pack - Media Player Classic (http://www.free-codecs.com/download/k_lite_mega_codec_pack.htm)
Potplayer是The KMPlayer的改良版,相當輕巧、播放品質也很棒;但為了方便比較差異,我這兩套都有安裝。Splayer最大的好處是它可以自動從射手網取得字幕,播放網路下載的「完整版預告片」很方便,不用到處找字幕。K-Lite Mega Codec算是老牌,它內建的Media Player Classic很精簡,但基本功能具備,安裝好Mega Codec之後,Windows就能吃下大多數的影片格式,只是對於高清影片並沒有特別的處理。

2010年12月27日

快快樂樂認識Grails

Ruby on Rails(RoR)給網頁應用(webapp)帶來不少敏捷開發的啟發,對於許多深陷JavaEE泥沼中的開發者,成天和一堆XML設定奮戰,被複雜的框架搞得心不從心,看到RoR快速簡單的開發方式,都會投以一種渴望卻得不到的眼神。得不到的原因是很多JavaEE的專案,相當程度地依賴一些Java穩固的基礎建設,畢竟Java的發展有十多年之久,許多成熟的解決方案並不容易在RoR找到相等的替代方案。

發展一個網頁應用程式,有許多瑣碎的事情要做,建立資料庫和查詢語法、發展商業邏輯、撰寫測試程式碼及增加一些AJAX功能。這些事情很平常,但為了讓基礎能夠完整穩固,我們可能加入Hibernate讓資料存取抽象化,用EJB或Spring Framework發展商業邏輯的元件,不情願地寫了些JUnit的測試程式,為AJAX加入DWR。為了發展一個專案去做這些事並不難,但是對於不斷在創造新產品的團隊,要一直把新的創意實現出來,很多瑣碎的事情重覆做起來也是很麻煩。

RoR幫我們把很多瑣事自動化,Grails是JavaEE的解決方案,它受到RoR的啟發,可以用來快速開發網頁應用程式,但骨子裡是Spring/Hibernate這些強大的基礎。Grails使用Groovy(Java的Scripting語言)為基礎,可以用比Java更簡潔、動態的語法開發程式。Grails實現了MVC架構,以Groovy語法開發Model/Controller程式碼,而View則是以GSP(Groovy Server Page)或JSP(搭配Grails自訂的Tag)設計。
The Grails ecosystemis a powerful confluence of people,ideas, and technology.
參考資料

  • Grails in Action, 2009, Manning

2010年12月26日

用VirtualBox體驗Ubuntu 11.04的Unity桌面

Unity是Ubuntu針對小筆電(netbook)設計的桌面外觀,在明年(2011)發行的Ubuntu 11.04(代號natty),將會把Unity變成Desktop版本預設的Gnome桌面。這個決定當然也引發一些反對的聲音,但不想用它的使用者,可以在登入前選擇Classic模式切換成傳統桌面。

如果想要搶先體驗11.04的Unity桌面功能,可以使用VirtualBox 4.0的虛擬機器安裝Ubuntu 11.04。VirtualBox 3.2經測試並無法順利啟用Unity,原因是Unity的桌面特效需要硬體3D支援,即使打開VirtualBox 3.2的3D顯示加速選項,仍無法在Ubuntu 11.04中使用3D功能。

目前Ubuntu 11.04最新發行版是Alpha1,也可以在Daily Build取得每日打包的最新版本。VirtualBox 4.0的安裝請參考這篇

要啟用Unity桌面,除了在VirtualBox 4.0安裝Ubuntu,還需要兩項調整。
  1. 在虛擬機器的設定值中,找到「顯示、視訊、延伸功能」,將「啟用3D加速」的選項打勾。
  2. 在虛擬機器中「安裝Guest Additions」
this week in linux發表的「First Look At Ubuntu 11.04 Natty Narwhal Alpha 1」短片:

免費強大的虛擬機器軟體 VirtualBox 4.0 發佈

VirtualBox 4.0在12/22日(2010)發佈了,這個版本跟3.2版最大的差異在使用者介面有一些調整。VirtualBox是一款免費的x86虛擬機器軟體,支援常見的Windows/Linux/MacOSX/Solaris等作業系統,可以安裝的客體作業系統(Guest OS)也非常多,功能媲美VMWare等商業軟體,操作簡單執行效能很不錯。對於一台電腦想要安裝多種作業系統,例如在Windows 7下執行Windows XP、Ubuntu Linux,使用VirtualBox可以讓多個作業系統同時執行,對於擁有多核心處理器(雙核以上)、高容量記憶體(4GB以上),這是一個充分發揮電腦效能、一台電腦當多台用的方式。

先前VirtualBox 3.2版本有區分完整版及OSE(Open Source)版本,OSE版少了USB2.0的支援等,但是到了4.0就沒有這種區分,但是安裝好之後預設是不支援USB2.0功能,必須另外下載安裝Extension Pack(個人使用免費,下載後滑鼠點擊即可安裝)。

  • VirtualBox 4.0 Oracle VM VirtualBox Extension Pack All platforms
    Support for USB 2.0 devices, VirtualBox RDP and PXE boot for Intel cards
連結
  1. 版本差異說明(http://www.virtualbox.org/wiki/Changelog)
  2. 下載區 (http://www.virtualbox.org/wiki/Downloads)
  3. 下載區 for Linux (http://www.virtualbox.org/wiki/Linux_Downloads)
  4. 重灌狂人VirtualBox Windows版安裝教學 (http://briian.com/?p=5690)
  5. VirtualBox for Ubuntu Linux版安裝教學 (http://www.webupd8.org/2010/12/install-virtualbox-40-stable-in-ubuntu.html)
  6. 免安裝中文版 (http://azo-freeware.blogspot.com/2008/09/virtualbox-166.html)
  7. phpVirtualBox AJAX網頁版本的遠端虛擬機器管理 (http://code.google.com/p/phpvirtualbox/)

Python的工作機會 - 精靈數位科技

今天偶然從網路廣告點進一家「精靈數位科技」公司的網站,發現他們正在找Python開發工程師,這在台灣算是不多見的職缺。從104的公司簡介,不難看出精靈數位的前衛的做法,他們的產品以Web 2.0、iPad、Cloud、SmartPhone相關應用為主,目前推出的兩項產品服務,一個是智慧型手機的餐廳應用,另一個則是雲端服務管理系統。

在Web 2.0網站應用的部份,精靈數位採用Python程式語言及Django開發框架(web framework),而非業界普遍保守的選擇:.NET、PHP、J2EE。這種前衛的選擇看似具有風險,但其實Django從2005年迄今也歷經5年發展,而Python從1991年發展到現在,又是Google所採用的主要開發語言之一,說需要擔心似乎是有點多慮了。

這讓我想到「選擇程式語言」,對於一家新創公司的發展,或許有著某種重要程度的關聯。

一家公司採用Python(或Ruby?)作為主要的開發工具,會有什麼有趣的結果呢?如果這家公司的文化夠創新,或許就能夠不斷吸引到「對軟體創作真正有興趣的那群人」。我們不能說懂Python的人就比較厲害或怎樣;但是同樣是大學畢業的新鮮人,如果已經熟悉Python及相關的解決方案,我們就能臆測這個人八成是很熱愛創作軟體,曾經下過不少苦心鑽研,對技術的熱誠超乎常人,未來投入相關的開發工作也肯定具有一定水準的生產力,不需要太多鞭策他就會自己努力。

以目前來說,在高中職的課程安排中,通常是教C或VisualBasic,到了大學則是教進階一點的C/C++、Java等。有些學生會依照自己的興趣,利用選修課或專題的機會,學習其他非主要的核心科目,例如Linux、SmartPhone的程式設計。

但是像Python的學習就需要花費額外的不少功夫,一來不懂的地方問老師可能也不懂;想跟同學朋友討論,他們不是沒聽過就是問你學這個要幹嘛;就算學會了對考試也沒幫助,市面上能參考的書不多,幾乎只能存錢買粉貴的原文書,或從網路的原文資料一點一點慢慢吸收;想要找到同好,就必須犧牲晚上或週末,老遠跑去參加人數不會太多的聚會;而且還可能以後工作也沒機會用到,但在一股狂熱的驅使下,還是無怨無悔地努力學習。

簡單地說,當多數的大學生晚上都窩在宿舍或實驗室打電動,或是出去聯誼逛街唱歌,而有人卻不合群地一直努力學著Python,這樣的人,你說他能不變態嘛?

當然一家公司的組成,也不能都是前衛的狂熱份子,因為他們不用人推就會向前走,但想拉的時候卻也拉不住。還是要有守成、穩紮穩打的一群人,才能維持劈荊斬棘換來的成果。

Google Demo Slam: Streetview Road Race 虛擬馬拉松橫越美國

影片中的兩位老兄,用Google Map的Streetview功能,跑了一段橫越美國的虛擬馬拉松,從舊金山直奔紐約。什麼時候才能開始用街景服務虛擬台灣環島呢?!

2010年12月23日

升級MySQL 5.5的五個理由

Ronald Bradford是一位MySQL專家,日前他在部落格發表一篇文章,列出五個將MySQL升級至5.5版的理由。
  1. Improved integration
    InnoDB由Plugin正式成為內建預設的儲存引擎。
  2. Improved performance
    可以在多核心的硬體上執行大量執行緒時增加效能,InnoDB也帶來一些效能的加強。
  3. Improved recoverability
    更好的可回復性。
  4. Improved instrumentation
    提供較多可以協助找出效能問題的資訊。
  5. Improved development methodology
    目前Oracle對MySQL作出的計畫是正面的。
這篇文章看起來重點還是在更換InnoDB的部分,我的專案本來就是採用InnoDB,參數也是為InnoDB調整,還沒出現非升級不可的理由。所以若知道怎麼在MySQL 5.1使用和調校InnoDB,還是繼續用吧! :XD

參考資料

《他們在畢業的前一天爆炸》第一集 1-5 完整

前天,睡前我用Android手機上YouTube隨意找了些節目,發現公視《他們在畢業的前一天爆炸》5集迷你連續劇,劇情是一群高中生的校園生活。這是部很會利用網路做行銷的電視短劇,喜歡這個節目的朋友,在YouTubePTS公共電視台有提供720p的HD畫質節目,劇本的PDF在這邊,也可以參觀部落格或加入Facebook粉絲專頁

很多節目都是先在電視上首播,之後才被網友錄製成短片放上YouTube,但是這麼一來畫質就降低了不少。《爆炸》劇的鄭有傑導演很有創意,他在12/18日電視首播之前,就將第一集用高品質的影片格式(HD 720p)完整上傳至YouTube,在正式開播前就先在網路上"爆炸"。

如此一來,12/18日連續播出第一集和第二集,相信很多看過的人,都會想知道第二集的故事怎麼發展,而在第一時間坐在電視機前面收視,不必花大錢宣傳就能得到更多收視率。然而要透過網路宣傳,第一件事情就是先把內容的品質做好,否則結果就會適得其反。









[心得] GUNNAR 數位光學眼鏡 WEEZER 調酒師 (瑪瑙黑)

由於我的工作有超過90%都必須依賴電腦才能完成,即使不是工作,很多休閒娛樂也必須靠電腦,不管什麼評比都是不折不扣的重度電腦依賴者。結果就是,一星期至少有超過三天,一天必須看螢幕超過10個小時。

雖然使用電腦十多年,只有輕微近視(50及75度),但眼睛疲勞痠痛、紅腫及乾燥的問題,卻是經年累月的困擾。在開始依賴電腦工作之後,我很重視螢幕的問題,桌上型的螢幕至少要DELL UltraSharp系列(IPS面板),筆記型的螢幕則必須挑選霧面。

在電腦前愈是專心工作(還好我經常因為各種原因分心),愈是容易成為電腦視覺症候群(Computer vision syndrome,CVS)患者。最好的預防方式是多休息,並使用醫生建議的眼藥水滋潤保養。可是這說來容易要做到卻很難,以軟體設計的工作來說,必須專注一段時間後,才能進入有效率的工作狀態(腦力時間),如果工作15~30分鐘就要眺望遠方的樹林,或是起來到處走走,就很容易打斷高效率的工作狀態,要重新進入高效率的工作狀態,又必須重新花更多時間盯著螢幕。

雖然現在的(面板好一點的)液晶螢幕,長時間盯著看,比較不會像傳統CRT那樣傷眼睛,可是也更容易因此在電腦前一坐就忘了休息。最近注意到一個電競玩家專用的光學眼鏡品牌「GUNNAR 」,已經悄悄在國內正式代理,台中市靠近大里也有家實體店面(電腦零組件的專賣店)可以試戴。我試戴了幾款後,決定先買基本款的WEEZER回家使用一段時間,看看實際的效果。
GUNNA WEEZER 黑
剛開始配戴GUNNAR眼鏡,最明顯的視覺差異是畫面變得偏黃、並稍微放大,而且會略感頭暈。我在使用2~3次之後,只要配戴個十分鐘左右就會習慣,也不會有頭暈的現象了。但如果平常去電影院用3D眼鏡會暈的人,說不定要花比較多時間才能適應,在討論區也看過有人說戴了一星期還是頭暈,最後就退貨,所以這還是要考慮到個人實際使用的差異。

GUNNAR眼鏡採用德國ZEISS認證的鏡片,黃色鍍膜據說可以阻絕對眼睛有害的藍光。它的黃色濾光鏡片,跟一般黃色的運動防風鏡不一樣,用傾斜角度可以明顯看出GUNNAR鏡片將藍光反射。

它對我比較有用處的地方,是在編輯白底黑字的畫面時,眼睛要專注在某一段落會比較容易,這可能是光線經過調節,讓大片的白色區塊變得不會那麼刺眼。可以做個小實驗,準備一份白底黑字文件,有滿滿一篇文字,字體用標準的12、行高固定100%,和螢幕保持40~50公分距離,眼球肌肉放鬆盯著某個段落看一段時間。對我來說,要在眼球肌肉放鬆的狀態看完一段文字很困難,當要專注看那段文字寫什麼的時候,眼睛就會不由自主地緊繃。

我在這篇文章寫了很多的文字,其實就是想測試GUNNAR的效果,例如在編輯這一段的時候,如果戴著GUNNAR眼鏡,可以比較容易眼球放鬆的狀態下,專注編輯這個段落。但拿掉眼鏡裸視的狀態下,眼睛的專注力就很容易被上下段落影響,而必須更用力才能_這一段文字。

說不定使用比較好、具偏光效果的螢幕保護貼,會有類似的效果;不過我自己有十多台螢幕,並不想要每台都貼(很貴,而且有些螢幕不是我自己的)。透過螢幕的亮度、對比及色彩調整,也可以讓眼睛舒服一點,但是編輯文字、看電影、電玩、上網或繪圖最合適的設定都不一樣,每次都要切換很麻煩。如果戴上眼鏡就能解決工作時的需求,那算是個花錢換方便的解決方式吧。

可能因為我自己對鏡框很挑剔,GUNNAR讓我覺得最大的敗筆,就是沒有看到一款會非常喜歡的鏡框,所以我只對三千元以下、功能取向的基本款又興趣,如果未來能夠有不同品牌結合的特別設計款,例如GUCCI鏡架+GUNNAR鏡片,那才會有多犧牲一些小朋友的衝動。而萬元以下的GUNNAR眼鏡都是沒有度數的,對於有近視而且不想戴隱形眼鏡的人來說,想要訂製專用的有度數鏡片,差價已經足夠多配幾副名牌眼鏡。

因為明年(2011年)開始法規修訂,此類眼鏡不能在網路販售,PCHome年底前GUNNAR七五折出清,價格下調到基本款$2,550就可以入手。因為PCHome可以零利率分期付款,利用這次優惠我再訂了一支PPK,這款跟WEEZER主要的差異是「扁」鏡架,這個設計是方便長時間戴全罩式耳機,寬扁的鏡架比較不會壓迫導致疼痛。

GUNNAR PPK 黑
文章連結

2010年12月22日

PPStream禁播歐美影集

歐美影集在這個月,徹底從PPStream網路電視消失。之前,只要安裝解鎖版或是累積一定的在線等級,就可以看得到歐美影集。在台灣的第四台節目質量不佳的現況下,P2P網路電視原本是個很棒的替代品,不過看樣子對岸當局也開始(被施壓?)重視版權問題。

這次的事件影響包括PPS、土豆網及優酷等,如果一直沒有正式合法的授權,或許很快就會出現地下化的網路電視。

相關新聞連結

2010年12月20日

Google將WindowBuilder及CodePro Profiler捐贈給Eclipse基金會

Google在今(2010)年12月15日,宣布將WindowBuilder及CodePro Profiler兩套軟體,捐贈給Eclipse基金會。預計在明(2011)年六月釋出的新版Eclipse(代號Indigo),就會內建這兩套軟體的功能。在此之前,開發者必須以附加方式自行安裝。 (請參考iThome新聞)

WindowBuilder Pro是一套所視即所得的圖形介面開發工具,同時支援Java平台的SWT(Standard Widget Toolkit)、Swing兩大Java GUI主流,以及RCP(Rich Client Platform)、XWT(XML Windowing Toolkit)及GWT(Google Web Toolkit)等。在過去,Eclipse發行的Java開發工具,並沒有內建視覺化的UI設計工具,開發者必須另外安裝其他廠商的附加軟體,才能提供類似VisualStudio、Delphi或NetBeans等,拖曳方式建立視窗程式的開發環境。
WindowBuilder (Eclipse Proposals)
CodePro Profiler是Java應用程式的分析工具,可以用來檢驗執行中的程式,找出效能的瓶頸,偵測記憶體漏洞,解決執行緒同步處理的問題。在Eclipse目前的提案中,新的發行版將加入RAT(Runtime Analysis Tools)功能,就是來自於CodePro Profiler。
CodePro Profiler (Eclipse Proposals)
先花錢把軟體(公司)整個買下來,然後再捐出去,谷歌真牛啊!

2010年12月19日

Seagate Barracuda ST31000528AS-3Y/P硬碟測試

最近入手一顆SEAGATE 7200RPM 1TB(ST31000528AS)的硬碟,應付已經不敷使用的Linux農場伺服器。只是運氣挺背的,第一次裝上去,H.D.D. Smart就已經出現重新分配磁區數量(Reallocated Sectors Count)異常,後來換回一顆新的就正常了。

測試環境:Ubuntu Linux 10.04 LTS x86_64

hdparm -Tt 測試結果

  •  Timing cached reads:   6950 MB in  2.00 seconds = 3476.99 MB/sec
  •  Timing buffered disk reads:  352 MB in  3.00 seconds = 117.18 MB/sec

FACEBOOK網路行銷超簡單(二) 零成本發行優惠券

過去要舉辦促銷活動,不僅要花錢又很麻煩,不但要準備印刷品(實體的折價券或摸彩券等),還要大肆宣傳,免得活動都過期了還沒什麼人知道。

在Facebook的時代,可以透過線上免費工具,結合社群的力量舉辦促銷活動,這個過程相當簡單,這篇教學以Facebook的『好康活動 Hot deals』為例,示範十分鐘之內可以完成的線上舉辦促銷活動。

首先,你還是要有一組Facebook帳號,完成登入,並成立粉絲專頁
接著,打開『好康活動 Hot deals』的主網頁(http://www.facebook.com/myhotdeals)。
點選左上方的『前往應用程式』,會進入熱門好康的應用程式畫面。
再點選管理好康活動的頁籤,從管理粉絲專頁的下拉選單中,挑選一個要舉辦活動的粉絲專頁。
在管理活動的選項中,選取製作優惠券
填寫優惠券的各項資料及設定,按完成後送出。
製作好的優惠券,可以將訊息透過Facebook發佈給朋友,這時候,平時有沒有認真經營個人交友及粉絲團,就會影響到有多少人能看到一手訊息,但可別為了商業活動而製造朋友不喜歡的垃圾訊息,那結果就會適得其反了。

FACEBOOK網路行銷超簡單(一) 成立粉絲團

在全民瘋Facebook的時代,除了玩開心農場,還可以利用這個廣大的社群做什麼事呢?相信你已經感覺到許多企業,正在利用Facebook做行銷。這些行銷方式,不會像電視廣告一樣打斷你的娛樂,也不會像垃圾郵件ㄧ樣,讓你刪到手軟、厭惡至極,而是透過你的交友圈來傳遞,好的行銷廣告,會一傳十、十傳百,最後出現在你面前,而你也可能再將它推薦給你的朋友。

如果你擁有以下任何一項,那麼你該認真考慮成立Facebook粉絲團了!
  1. 擁有一間公司
  2. 創造了某一項產品
  3. 成立一個品牌
  4. 經營一家店
  5. 想打響個人的名號
  6. 部落格作者
  7. 寫了一本書
  8. 拍一系列攝影作品
  9. 發表一項專題
  10. 具有特殊技能?!
要動手玩Facebook網路行銷,你不必花錢去聽演講,也不用聘請專家顧問,你只需要擁有一組Facebook帳號,然後從下面的連結,開始成立你的第一個粉絲專頁。


可以參考以下的教學:



Mac OS X 的螢幕擷圖功能

MacBook的鍵盤沒有 [PrtScr(Print Screen)] 按鍵,所以要擷取螢幕畫面,必須透過組合鍵完成。雖然剛開始用起來比較麻煩,但習慣之後就會發現,內建就能夠選取自訂區域的功能,對於編寫文件時,很容易處理只需要擷取部份畫面的需求。

儲存成檔案

  • [Command] + [Shift] + [3]: 整個螢幕擷圖後儲存成桌面的圖片檔案
  • [Command] + [Shift] + [4]: 接著再選擇一個區域,將自定區域擷圖後儲存成桌面的圖片檔案
  • [Command] + [Shift] + [4] + [Space]: 接著再點選一個視窗,將視窗擷圖後儲存成桌面的圖片檔案


複製到剪貼簿

  • [Command] + [Control] + [Shift] + [3]: 整個螢幕擷圖後複製到剪貼簿
  • [Command] + [Control] + [Shift] + [4]: 接著再選擇一個區域,將自定區域擷圖後複製到剪貼簿
  • [Command] + [Control] + [Shift] + [4] + [Space]: 接著再點選一個視窗,將視窗擷圖後複製到剪貼簿


在Leopard作業系統,自訂選取區域時還可以搭配以下的按鍵(在選取區域範圍時按住不放)。

  • [Space]: 固定目前的選取範圍,移動滑鼠時,選取範圍的位置也會跟著改變。
  • [Shift]: 限制選取範圍只能往水平或垂直方向改變。
  • [Option]: 以選取範圍的中心點作為基準點,移動滑鼠時,可以控制選取範圍放大或縮小。


本文同步發表於: http://lyhdev.com/mac:keyboard_shortcuts

2010年12月12日

不必花錢的進修,史丹佛開放課程

Stanford on iTunes U (http://itunes.stanford.edu/) 是史丹佛大學的線上課程,只要透過Apple iTunes軟體就可以免費訂閱,課程共分為十三類:

  • Business
  • Engineering
  • Fine Arts
  • Health & Medicine
  • History
  • Humanities
  • Language
  • Literature
  • Mathematics
  • Science
  • Social Science
  • Society
  • Teaching & Education

在安裝好iTunes軟體後,打開下列的網址,就會自動開啓iTunes Store,在iTunes Store免費訂閱最新的課程影片。

目前最令我感興趣的是,Stanford的Science分類下,有iPhone程式開發課程。

2010年12月9日

發揮多核心處理器的運算效能,使用 C# 及 Task Parallel Library

.NET Framework 4 提供一組平行處理函式庫「Task Parallel Library」(簡稱TPL),可以很容易用 C# 或 VB.NET 寫出多核心環境的平行運算程式。

使用TPL必須先引用Namespace:
using System.Threading.Tasks;

以下範例使用 Math.Sqrt 計算平方根:

//循序處理的寫法
for (int i = 0; i <= int.MaxValue/2; i++)
{
  Math.Sqrt(i);
};



//平行處理的寫法
Parallel.For(0, int.MaxValue/2, i =>
{
  Math.Sqrt(i);
});



測試環境是 Intel Core2Duo P8700 (2.53GHz雙核心)、Windows 7 32bit作業系統。從CPU Usage的圖形可以看出,循序處理的版本要花費很長的時間才能完成,過程中CPU也僅有60-70%的使用率,根本無法發揮多核心電腦應有的效能。使用平行處理的版本,整個執行過程耗費的時間減少很多,而且兩個CPU都是以100%滿載運作。

※ 本文同步發表於「dotNET探索樂園

2010年12月8日

12項程式設計應該避免的錯誤

一、未善盡責任
基礎知識不足或偷懶,使得程式碼不夠穩固;例如數字計算未事先避免divide-by-zero、將字串寫入資料庫之前沒有檢查最大長度。程式交付到使用者手上,往往都會被以意想不到的方式操作,因此各種潛藏的錯誤都可能發生,甚至造成資訊安全漏洞。
程式語言或開發工具的改善,或許可以幫助我們免於整個系統掛點,例如Java程式的Exception機制,在某個功能拋出Exception時,即使我們沒有加以善後,程式仍然可以繼續執行;但是這些機制並不能真正幫助我們解決問題,因為要解決問題,必須有業務面的考量。舉例來說,執行某功能發生NullPointerException時,如果我們只是catch、顯示error stack訊息之後就置之不理,能夠防止系統crash,對於開發人員也很容易從錯誤訊息得知解決方法;但是對於不了解系統內部設計的end user而言,將很難從中找到修正的做法,例如在執行此功能之前必須先做某項設定之類的操作。

二、過量不必要的細節
假設使用者在網頁填寫一個電子郵件信箱,送到伺服器時必須經過十個function處理,為了徹底防止不正確的資料,每個function都用regular expression檢查信箱格式、並且建立SMTP連線測試是否存在真實的郵件伺服器。這種設計固然做到滴水不漏,但無止盡的過度設計實際上並不可行,因為程式設計必須考量系統資源、網路頻寬、回應時間、開發時程、執行效能等。

三、控制不夠簡化
開發Ruby on Rails應用的程式設計師,會習慣一種「約定取代設定(convention over configuration)」的做法,當程式中建立一個Name類別的model,擁有兩個屬性first及last,那麼就可以預期資料庫中,也會建立命名一致的Name資料表及first、last兩個欄位。程式開發時採用一些約定成俗的慣例,就可以省去很多額外設定的麻煩。

四、對框架過多的託付
框架幫你處理掉很多瑣碎的事情,例如Ruby on Rails將約定的URL格式轉換成controller method呼叫,通常不必知道它怎麼運作。Mike Morton(一位程式設計師)說:「它們(框架)就像用轎子把你抬上九成的山路,但剩下的那一成必須靠你自己攜帶氧氣攀岩才能完成。」

五、太過相信客戶端
我們無法預期網路另一端的使用者怎麼操作系統,就像一個網頁的表單資料,即使我們已經在瀏覽器端用JavaScript做好一些基本的檢查,但送出的資料的過程仍可能遭到惡意竄改,例如使用者用某些瀏覽器外掛,在表單填入原本不允許的資料,或是駭客偽造表單資料進行SQL Injection攻擊。即使是我們自己的程式回傳的資料,只要是來自客戶端,就不該相信它一定照規矩,檢查資料是不是存在威脅很難做得徹底,因此一個好的實踐方式,就是只讓符合條件的資料通過。

六、不夠信任客戶
有時候降低一些對安全的要求,可以讓程式開發比較容易,使用者也比較好操作。例如一個提供八卦閒聊的論壇系統,如果註冊時需要自然人憑證及信用卡驗證,每次登入都需要動態密碼及一連串身分辨識,每一次送出的訊息都經過特殊加密,雖然在資安方面可能有極高的成效,但肯定不會是個好的系統。

七、重度依賴神奇魔術盒
當你買了一個神奇的資料庫備份軟體,你不必管它怎麼運作,因為銷售員告訴你「It just works.」是否就此高枕無憂,再也不必擔心資料庫發生問題?許多買來的函式庫、開發工具很好用,我們只需要知道怎麼用,而且大部分的時候它都很順利,但是有一天它鬧個彆扭,災難就此發生。

八、重新發明輪子
如果你需要一個加密的演算法,應該要找一個好的演算法實作,如果覺得它不夠好,那麼就動手去改善它(如果是自由軟體那麼更需要這樣做);反之,如果你丟棄別人已經辛苦幾年做出的成果,想要重新打造一個自己專屬的演算法,那不僅是浪費時間,也等於是向駭客敞開大門。

九、過多的功能讓使用者困擾
智慧型手機的兩大主流平台,iPhone及Android各自有其愛好者,Android在安裝新軟體時,很詳細地將新軟體有哪些存取權限告訴使用者,讓使用者自己判斷新軟體潛在的安全問題,例如一個可以存取SIM卡資料的軟體,就有可能透過網路把你的個人隱私洩漏出去。但是對於end user而言,根本看不懂這些涉及技術面的問答題,他們最後還是會在不懂有哪些潛在危害的情況下確認安裝。iPhone贏在操作起來"通常"比較簡單,讓完全不懂科技產品的消費者,也能很快就愛上這款新奇的科技產品。試想在登入一個網頁時,你還要選擇是否啟用SSL、GZIP網頁壓縮,要發表一篇文章時,還要設定使用哪一種所視即所得編輯器,使用者哪管這些?大多數人喜歡的系統就是,方便、不必太多思考(參考 Don't make me think)。

十、使用者想的和你不一樣
有些Web郵件系統沒有「新增子資料夾」的設計,但可以用標籤來達到同樣的功能,標籤比子資料夾好用,因為一封郵件設定了多個標籤,就有同時存放於多個資料夾的效果。但並非每一位使用者都願意接受這種操作模式,他們就是喜歡先建好一堆樹狀的資料夾結構,等真的收到郵件的時候,再決定分類到哪個資料夾。

十一、封閉程式碼
許多發展商業軟體的公司,總喜歡用盡各種手段保護程式碼不會洩漏,不但要編碼加密,還要加入防止逆向工程的設計。對軟體公司而言,程式碼是一項資產,要把它分享出去,是件有挑戰的事。並不是每一種程式碼都是需要保護,有些程式碼可以公開,可以藉由分享變得更好;例如在一個專案中,實作了一組方便的郵件發送函式庫,把它公開分享,並不會影響專案的收益,卻能得到知名度的提升及使用者意見回饋的好處。

十二、開放不是萬靈丹
有大量的開放源碼專案在SourceForge、GitHub、Google Project Hosting等網站上線,但僅有少數能夠獲得人們參與維護、修正及擴充代碼。如果軟體專案缺的是人力,即使把它變成開放源碼的方式分享出去,也不見得就能獲得問題的解決,因為很容易找到其他相似的替代品,即使現在沒有,也會在未來出現。而且將產品開放,可能也意謂著將失去財務上的支持,更可能被拿去做違反自由軟體精神的應用,例如某些程式碼被拿去開發成商業產品的一部分,並且衍伸的程式碼並沒有同樣分享出來或回饋給創始者。

參考資料

樂趣,工作的原力 (五) 解除迷思

天下雜誌網站近日發表一篇「好玩為成功之本」,其內容最早刊登在2004年的Cheers快樂工作人雜誌。這篇文章很適合想找回工作樂趣的人參考,以下斜線部份節錄片段文字與讀者分享。

過去,組織時代強調人人一致,但是創意階級卻主張獨立性、自我陳述、包容差異,以及多面向的經驗。最明顯的現象,就是從前人們透過職業(農夫、工人……)來識別身分,但今天更多人喜歡用各種創意活動,像作家、美食家、設計師、顧問...來稱呼自己。


無獨有偶,德國最暢銷的企管書作者萊納德史布萊格爾(Reinhard K. Sprenger)與理查隔海遙相呼應。他在新作《個體的崛起》一書中提出,今天的經濟環境中,只有「獨具特色」的人,才有機會出人頭地。什麼叫「獨具特色」?史布萊格爾的看法是:「專注於最拿手、最能展現天賦的領域」,而且這項能力能受到肯定、得到讚許。 (節錄自天下雜誌好玩為成功之本)


個體的崛起」這本書,在「IT自由工作者」這篇文章中也曾經推薦,但出版已經有五年,在一般書店不太好找;近期有一本「工作大解放」,由37 signals創辦人著作,也是值得閱讀的一本書


工作的趨勢在改變,社會對人才的衡量,不再是這個「人」隸屬哪一家公司,而是這「個人」具備什麼樣的能耐,在把公司、頭銜的光環拿掉之後,還存在什麼樣的價值。過去的管理思維著重團隊領導,不容許個人主義、也不重視員工的個體性,企業希望把員工組織成軍隊般有效率地運作,有效地為組織的利益奮鬥。


傳統企業的運作方式,讓中年失業成為許多忠誠員工的噩夢,他們甚至在走投無路的那天,還不懂是誰偷走了乳酪。


傳統的工作,一切的價值建立在組織之上,因此員工離開的時候,通常需要一筆足夠過下半輩子的退休金;如果在這一項保障兌現之前,就失去了工作,要捲土重來並不容易。


過去,只要在一家夠大的企業待得夠久,往往不必擔心年邁的生活。

但是當多數企業不再能提供這種保障時,工作者自己必須及早換個腦袋思考,在長年工作之後,到底累積多少真正屬於自己的經驗、知識及學問,結束一段工作生涯後,能夠在下一個工作生涯創造更高價值。

即使是處在民主自由的社會,我們多數人其實都是被控制的。為了讓每個人都往同一個目標努力,有個手段叫作「排名」。


「排名」在台灣社會過度被重視,在學校裡,成績的排名決定哪些人優秀、需要被獎勵;升學時,排名決定哪些人可以進入優秀學校、繳比較低的學費;找工作時,排名決定哪些人可以進入百大企業;在公司裡,績效的排名決定哪些人可以被升遷、加薪。為了不要在排名上落後他人,許多人兢兢業業,但現實是一種排名只會有一位第一名,而多數的人最後被淘汰、被犧牲。

當名列前茅不再能保障你擁有理想的生活,那又為何要在意排名呢?

要成為快樂的工作者,得跨出無視於排名的第一步,不要再去競爭多數人都想要的第一名,不要再去擠百大企業,不要再去埋首為得到鐵飯碗辛苦拼命。每個人都有機會在自己獨特天賦的領域成為佼佼者,做自己的第一名並不難,把快樂加進來計算,獲得的報酬也不見得比較低。

2010年12月7日

VirtualBox 虛擬IDE及SATA控制器效能實測

最近在研究怎麼讓VirtualBox跑快一點,從Google找到多篇資料,都是講硬碟控制器從IDE轉換成SATA之後效能會提高,於是就自己動手測試一遍。

HOST作業系統
$ uname -a
Linux desktop 2.6.35-23-generic #41-Ubuntu SMP Wed Nov 24 11:55:36 UTC 2010 x86_64 GNU/Linux


HOST處理器
kyle@desktop:~$ cat /proc/cpuinfo
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 30
model name : Intel(R) Core(TM) i5 CPU 760 @ 2.80GHz
stepping : 5
cpu MHz : 1197.000
cache size : 8192 KB


HOST記憶體
$ free
total used free shared buffers cached
Mem: 8185352 8111476 73876 0 1557100 2566644
-/+ buffers/cache: 3987732 4197620
Swap: 2000088 92 1999996


HOST硬碟讀取測試(硬碟格式化為ext4)
$ sudo hdparm -Tt /dev/sda
/dev/sda:
 Timing cached reads:   17238 MB in  2.00 seconds = 8627.19 MB/sec
 Timing buffered disk reads:  268 MB in  3.00 seconds =  89.26 MB/sec


VM硬碟控制器(IDE及SATA)
Intel(R) 82371AB/EB PCI Bus Master IDE Controller
Intel(R) ICH8M-E/M SATA AHCI Controller


使用IDE控制器

使用SATA控制器

結果,改用SATA控制器沒比較快,不過這次的實驗是用VMDK的虛擬磁碟,而不是VBox自家的VDI格式,還有些其他的影響因素,等下次改用乾淨的實驗環境再比較。

最近的開發環境愈來愈依賴虛擬機器,再過不久應該會將工作站升級到16GB RAM/64GB SSD/2TB * 4 RAID5的規格。

2010年11月24日

丟掉50樣東西,書籍篇

要把自己花錢買的東西,扔到資源回收箱,著實不是件簡單的事。

以下是《丟掉50樣東西,找回100分人生》的書籍介紹:

很多人因為放不下一切,只好放棄夢想。——曹蘭
「放」的快樂是很久的,「得」的快樂是一時的。——金惟純
看見美好未來的方式很多,但最簡單、最不求人,卻一直被遺忘的方法,就是:
丟東西!
我知道你一定不相信,但是,丟掉50樣東西,你想要的好事確實會發生。
20件很少穿的衣服,只算一樣,丟掉。
一直沒用完的洗髮精、N年沒打開的文件、勾起往事的紀念品、舊照片、甚至是msn的連絡人……都丟掉。
為什麼是「50樣」、而不是20樣、30樣?作者蓋兒‧布蘭克說,無論你丟棄的是曾經具有多重大意義的東西,你都得持續地丟,至少丟滿50樣。在這過程裡,你一次次檢視自己需要什麼、該拋開什麼,你將變得越來越能凝聚「勇氣」、越來越能明快的「做決定」,也越來越善於擺脫內心壓抑、自我設限的聲音。很多時候,你不學會放手,就沒辦法重新來過。

擁有很多東西,可以滿足自己的安全感;但隨著東西愈來愈多,佔去生活空間、害怕失去,反而成為生理及心理上的負擔。如果每天回到家,走進自己的房間,都有到漂亮民宿、飯店的感覺,就是一眼望去只有簡潔舒適的環境,而不是堆疊陳列許多雜物。

書籍就是一個很不容易處理的物品,在書店看到喜歡、需要的書,花錢把它買回家通常不是困難的事;但日子久等書櫃爆滿後,也沒有空間擺放新書櫃,開始在其他地方堆疊,就會造成生活空間的凌亂。而且把新買的書跟琳瑯滿目的舊書放在一起,也很容易忘記自己最近想閱讀的新書。

超過三年以上的舊書,我重新檢視一次,選擇留下或丟掉。

有一些書,我選擇留下來:

  1. 經典書籍,雖然看過之後就很少再翻,只要空間足夠就當作收藏。當然每個階段會認為是經典的書都不一樣,或許這次選擇留下,下一次就會覺得可以丟了。
  2. 談理論、概念的書,內容即使過了十年仍有參考價值。但如果已經過了十年,或許就要再思考是不是該丟。
  3. 對自己有紀念價值的書,在空間允許的情況,我留下了一些,例如小學第一次接觸QuickBasic語言的幾本書,雖然內容已經沒有什麼意義,但卻代表一些回憶。

有很多書,其實都該丟(拿去拍賣、樂捐或回收)了:

  1. 超過一年沒翻閱,想不到理由可以留下的書,也想不出以後什麼情況還會拿出來翻閱。
  2. 在學習階段需要的工具書,但已經過了該階段,學校的教科書大多是此類。
  3. 講解操作方法的書,可以當作是說明書,如果操作東西已經再也不會用,就可以丟了。
在這個原則下,我清掉了三箱書。

認真想過什麼東西該丟,什麼東西值得留下後,下次花錢買東西的時候,準備打開荷包的時候,就更容易想清楚該不該、值不值得買,而不會衝動行事,把不久後就用不到的東西給帶回家。

[書評] Brownfield Application Development in .NET (軟體構築美學)

Brownfield Application Development in .NET (軟體構築美學)

Kyle Baley and Donald Belcham
Foreword by David Laribee
April, 2010 | 416 pages
ISBN: 1933988711

Findbook找書 | 出版社連結 | 中文版譯者部落格

Table of Contents (中譯版)
第01章│認識棕地應用程式
第02章│棕地專案的版本控制
第03章│持續整合
第04章│自動化測試
第05章│軟體度量與程式碼分析
第06章│瑕疵管理
第07章│在專案中導入好的物件導向實務
第08章│應用程式的重新分層
第09章│鬆散一些:降低程式碼的依賴性
第10章│重整使用者介面
第11章│重構資料存取
第12章│管理系統外部的依賴
第13章│持續改善

作者借用土地管理的名詞 Brownfield 來稱呼「既有的、難以維護及改善」的軟體專案。許多人一踏進軟體開發的行業,就開始面臨這種專案,因為一般公司並不會將 Greenfield(剛開始起步) 的專案交給新人,通常是由維護、擴充既有的系統,延續使用前人已經訂好的架構,依樣畫葫蘆寫出新程式。

既有的系統發展到一定規模,通常已經有穩固的架構,而且也確實能滿足使用者的需求,又為何需要有一本專書來探討其中的問題?從 Brownfield 的定義來看就很清楚。

Brownfield狀態是一個條件,在某些法律排除和加法,不動產之內,擴展、再開發或者再用,其中可以由出現或危害物質、汙染物或者汙染物的潛力出現複雜化,也許包括石油碳氫化合物發行。 Brownfield狀態一般意味有對站點的用途或發展制約。
Brownfields 被摒棄或未充分利用的工業和商業設施,擴展或再開發由真正或被察覺的環境複雜化、汙穢。在市政規劃,brownfield土地 (或簡單地a brownfield)是土地早先使用為工業可以被低集中沾染的目的或某些商業用途有害廢料或汙染一旦清掃它,并且有潛力被重複利用。登陸更加嚴厲地沾染并且有有害廢料或汙染的高濃度,例如a Superfund 或有害廢料站點,不屬於brownfield分類。 [from WorldLingo]

軟體專案發展一段時間後,多數都會變成 Brownfield 狀態,且造成的原因通常都是無可避免。例如在出貨壓力下,程式開發時僅考慮怎麼做比較快完成,而不是採取比較好的設計方式;也可能是沒有清楚一致的架構,造成不同人寫的程式看起來像是來自不同專案;可能是架構師一開始就做了錯誤的決定,可能根本沒有 Pre-architecture 就開始寫程式;也可能在解決BUG時,因缺乏經驗或偷懶而加入了一些造成汙染的程式碼;軟體開發技術的改變很快,有時候軟體還沒到成熟的地步,使用的技術就已經顯得老態,開始翻新的時候,舊有技術的實作就變成了麻煩的來源。

由於許多主管只看重結果,也就是能達成時程規畫的產出,造成根本沒人在乎「好的設計」,或是在乎卻無法落實。站在企業經營的角度,這麼做是合理的,因為「好的設計」可能造成一開始成本就過高、開發時間過長、無法達成客戶要求的時限。在現實的考量下,許多好的設計先被犧牲,以完成專案目標為優先,最後面臨軟體專案變成 Brownfield 狀態。

變成 Brownfield 狀態,並不是代表軟體專案已經無藥可救,通常這時軟體已經發展到一定規模,企業也開始藉助這個軟體獲利,因此有更多資金可以投入改善。

如果拋棄 Brownfield 的軟體專案,讓這些已經在經驗中成長茁壯的團隊,重新啟動一個 Greenfield 專案,用更好的設計重新打造軟體不是更棒嘛?身處軟體開發的是非之地,我經常會有這種想法,但也一再驗證這樣做並不可行。

軟體重新由 Greenfield 狀態開始做起,剛開始可能很愉快,但之後還是會因為各種因素變成 Brownfield。而且過程還是要不斷面對既有醜陋惡劣的程式碼,因為發展到一定規模的 Brownfield 軟體專案,有太多商業邏輯的細節、特殊考量下的設計,被實作在程式碼中,雖然好的文件會有記載,但許多情況,看程式碼往往還是最清楚直接。既然還是要身陷泥濘中,翻修 Brownfield 的軟體,整體來說痛苦還是較輕一些。

這本書中各章節提供的方法,適合實際開發軟體的團隊成員,是開發大型軟體專案「必備」的各項 Know-how。在軟體還沒發展到一定規模前,現時營利的考量下,許多已知的更好做法派不上用場。但身為軟體開發人員,並不能因為這些方法目前用不上,就將它忽視,而必須儘早學習、謹記在心,在合適時機出現時,知道能夠採取什麼方法,並在開發過程中才能為自己留好後路,減少未來翻修時的痛苦。

良好的軟體整合開發環境,例如 Eclipse、Visual Studio .NET 等,已經開始具備現代軟體專案所需的功能,例如版本控制(Version Control)、重構(Refactoring)等,這本書是以 .NET 為例,操作實例也是以 Visual Studio .NET 為主,書中大部分的內容是與工具無關的觀念講解,所以也很適合其他開發工具、程式語言的讀者參考。

這本書很適合以下的讀者:
  1. 需要改善既有軟體專案
  2. 需要建置軟體專案環境、規畫軟體架構
  3. 想改善軟體專案的開發效率及品質
  4. 想避免開發「現在看起來很棒、但未來會變得很糟糕」的軟體
  5. 在軟體開發之路迷途,需要燈塔指引的旅客
  6. 在公車、火車上需要假裝認真看故事書的善男信女

2010年11月14日

樂趣,工作的原力 (四) 正確的投資規劃

談到投資,許多人往往聯想到基金、股票、黃金、外幣、不動產…,這些投資必然是讓財富累積更快、減少受通膨影響的方法。

對年輕的工作者來說,收入往往不高、存款通常有限,我們需要去關心經濟、瞭解正確的投資理財方式,但不必花太多心力在這些類型的投資上,因為報酬往往非常有限;比起開源節流的不二法門,進行上述的投資,只要做到比定存好一點、不要賠錢就好。

真正值得投資的項目…其實還有更多是值得投入時間心力。

投資閱讀。買幾本好書,花不了多少錢,用等車、搭車、休息、就寢前的時間看書,花不了多少時間。但這樣的投資卻對人生有長期的影響力,不斷影響我們是否能有足夠的知識解決問題,是否能在重要時刻做出正確判斷,是否能做出關鍵的抉擇,是否能保障辛苦賺來的錢不白白浪費、損失,是否能找到更好的工作,是否能升到更高的職位,是否能對這個世界有多一點點的瞭解,能否多靠知識賺錢而不是勞力。無形有形的好處,將一再驗證書中自有黃金屋的古訓…

投資嗜好,投己所好。用合理的花費,滿足自己的興趣、渴望,會對自己努力爭取的財富更有感覺,更能清楚自己什麼要更努力認真工作。適當滿足物慾,必須量力而為,當想要一樣東西卻買不起時,不應該過度支出,影響到基本的生活,而是要更認真工作,將所得用在自己認為最重要的事物上,這將能帶給自己對努力工作成果的一種肯定。選擇嗜好也很重要,因為攸關我們在投資嗜好之後,能不能獲得比滿足還要更多的東西,許多人在持續投資嗜好後,讓嗜好變成一種副業,甚至以嗜好為自己創業,都是非常不錯的投資報酬。

投資旅行,實踐行萬里路的精神。當背包客的花費有限,靠著平常持續鍛鍊的體力完成旅行,不必花費太多,甚至透過旅行體驗貧窮,更是成本相當低廉的一種投資。在完成幾趟旅行之後,我們往往能獲得許多意想不到的收穫,拓展視野,認識更多人事物,對天地留下更深刻的情感,對大自然的力量有更高的景仰。甚至,我們能在旅途中,發現自己真正想做、卻從沒想過的事。

不管什麼投資都是要花費,而且是顧此失彼的,把付出去的每一分錢都當作是一種投資,並且勇於投資在對自己真正重要的事物上,往往都能得到不錯的報酬。

發行股票的那家公司,幫你操作基金的經理人,如果對你的人生很重要,那你就該勇敢去投資它。但如果你還在花時間去找股價準備一飛沖天的公司,那就該仔細思考自己在賭局中有幾成把握。很多時候做正確的投資,只要多關心自己內心的渴望就可以辦到。

2010年11月12日

樂趣,工作的原力 (三) 做對的事(do the right thing)

工作這件事,可以說是蘿蔔青菜各有所好,有人喜歡穩定,有人喜歡輕鬆,有人隨波逐流,也有人偏好冒險犯難。

什麼才是對的事(the right thing),實際上因人而異。但每個人都應該順從心中的渴望,才會真正從工作中得到快樂。

對於喜歡追求自我突破、人生目標永不設限的工作者,如果到了一個輕鬆安逸、穩定的,雖然在別人眼中可能是份好工作,但心中肯定會不斷有失落、空虛。

從馬斯洛的需求層級來看,工作賺到的錢,能滿足生理、安全的基本需求;加薪仍留不住八零後、七年級生想換工作的現象,就是因為在時空背景下,年輕的工作者重視的不再是基本的需求,能否達成社交、尊重、自我實現需求,甚至Z理論提出的超越個人或靈性需求,才是許多年輕工作者考量的主要因素。

瞭解自己真正需要的是什麼,並認真思考、勇敢抉擇,才是讓工作變成享受,才能讓工作提供源源不絕的樂趣。但抉擇並非許多人採取的換工作,最近出現史上最高的跳槽潮開除老闆變成一種見怪不怪的事,這是在社會普遍觀念轉變所歷經的激烈變革,歷史經驗告訴我們,過度的激進作為,往往只會讓自己成為犧牲者。

做對的事,並非草莽行事、逞匹夫之勇,而是要先充實自己,不斷增加自己的知識、常識,才能做出帶有獨特智慧、順從內心想法的抉擇。

該是改變的時候了,但先問問自己,準備好了嗎?

2010年11月11日

樂趣,工作的原力 (二) 打造熱血工作環境

現在的硬體價格低廉,高效能的電腦設備並不需要多高成本,依賴電腦的工作,一台配備i7處理器、8GB記憶體、2TB硬碟、27吋IPS螢幕(或22吋雙螢幕)及一組好用的鍵盤滑鼠,花費和工程師的一個月薪資差不多,但可以提供工作者1~2年內不會因為電腦慢吞吞而影響產能及心情。
Facebook
在玩樂的場所工作,誰在乎加班到半夜有沒有加班費?
Google
讓人醉心於工作的環境,一天當中能進入腦力時間(神馳狀態)的次數將大幅增加。
Google
可以隨時改變的隔間、座位排列方式,在公司內就可以「換個地方工作」。
Pronet Security
為什麼有些公司總能不斷創新?創意的工作環境總會讓人耳濡目染。
Group8 Studio
他們正在…工作?可以說是工作嗎? :XD
Group8 Studio
培養閱讀的嗜好,是讓工作者不斷自我提升的方法,而且成本非常低廉。只可惜,現實是,許多人在學校只為了考試科目而閱讀,開始就業以後更沒有時間享受閱讀了。
One & Co
「讓我們一起共同努力完成目標吧!」這並不需要每天召集所有工作者重新催眠一次,凝聚團結一心的努力奮鬥,並不是開完會之後就各自回去做各自的,工作環境持續地發生潛移默化的作用。
Predicta
大面積可以塗鴉的白板,往往紀錄著腦力激盪的結果,讓人不時想在上面加點什麼新的發想。
Dataserv
圖片來源:OfficeSnapshots

2010年11月10日

Macbuntu 讓 Ubuntu 10.10 輕鬆換上 Mac 佈景

玩Ubuntu桌面最有趣的事,莫過於有很高的調整彈性,可以打造個人獨特風格的桌面,也可以讓它變得很像其他作業系統 :XD

Macbuntu 是一個整合的安裝工具,只要裝好之後,桌面就會變得很 Mac。

下載後解壓縮執行 install.sh。
tar zxvf Macbuntu-10.10.tar.gz
cd Macbuntu-10.10
./install.sh


下載 Macbuntu

除了 Macbuntu 還有其他套件,可以讓 Ubuntu 桌面變得更漂亮,可以參考這篇教學文章

樂趣,工作的原力 (一) 工作其實是一種享受

天下雜誌的創辦人高希均教授,在《閱讀救自己》一書中提到,他在威斯康辛大學任教,是一生中做了對的選擇(Do the right thing)。他的這份教書工作持續超過三十年之久,因為可以完全自由地從事教書、寫作、研究、演講、旅行。對高希均教授來說,探討經濟問題不是件工作,而是享受。

天下雜誌專訪廣告教父孫大偉「找到最愛,全力以赴」提到,找工作也要考慮興趣,興趣絕對是最忠實的,快樂不快樂,是很重要的。自己的一生,就像鞋子穿得舒不舒服,自己最清楚。

如果工作,能夠做你最喜愛的事情,那其實是一種享受。

2010年10月14日

加速Blogger的SyntaxHighlighter載入速度

不久前發表過一篇Blogger加掛SyntaxHighlighter的教學,最近發現有些速度上的問題。因為一次用了二十幾個<script ...>,所以在網誌每一頁載入時,這些*.js程式碼也會全部都被讀取一次,造成頻寬和記憶體的消耗。

把一些不常用的程式語言拿掉,可以讓速度快一些,但需要的時候還要去修改HTML樣板,感覺很麻煩。

我仔細研究SyntaxHighlighter的autoloader,才發現這功能可以做到「需要用到某個程式語言的著色時,才載入對應的*.js程式碼」,這樣一來不但可以使用SyntaxHighlighter支援的所有程式語言,而且只有在需要用到的時候才實際載入。

修改方式如下:

先找到<b:skin>標籤,在此標籤前加入以下代碼。
<!-- SyntaxHighlighter  3.0.83-->
<link href='http://alexgorbatchev.com/pub/sh/current/styles/shCore.css' rel='stylesheet' type='text/css'/>
<link href='http://alexgorbatchev.com/pub/sh/current/styles/shThemeDefault.css' rel='stylesheet' type='text/css'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shCore.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shAutoloader.js' type='text/javascript'/>

再找到</body>標籤,在標籤前加入以下代碼。
<!-- SyntaxHighlighter  3.0.83-->
<script type='text/javascript'>
SyntaxHighlighter.autoloader(
  'applescript            http://alexgorbatchev.com/pub/sh/current/scripts/shBrushAppleScript.js',
  'actionscript3 as3      http://alexgorbatchev.com/pub/sh/current/scripts/shBrushAS3.js',
  'bash shell             http://alexgorbatchev.com/pub/sh/current/scripts/shBrushBash.js',
  'coldfusion cf          http://alexgorbatchev.com/pub/sh/current/scripts/shBrushColdFusion.js',
  'cpp c                  http://alexgorbatchev.com/pub/sh/current/scripts/shBrushCpp.js',
  'c# c-sharp csharp      http://alexgorbatchev.com/pub/sh/current/scripts/shBrushCSharp.js',
  'css                    http://alexgorbatchev.com/pub/sh/current/scripts/shBrushCss.js',
  'delphi pascal          http://alexgorbatchev.com/pub/sh/current/scripts/shBrushDelphi.js',
  'diff patch pas         http://alexgorbatchev.com/pub/sh/current/scripts/shBrushDiff.js',
  'erl erlang             http://alexgorbatchev.com/pub/sh/current/scripts/shBrushErlang.js',
  'groovy                 http://alexgorbatchev.com/pub/sh/current/scripts/shBrushGroovy.js',
  'java                   http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJava.js',
  'jfx javafx             http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJavaFX.js',
  'js jscript javascript  http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJScript.js',
  'perl pl                http://alexgorbatchev.com/pub/sh/current/scripts/shBrushPerl.js',
  'php                    http://alexgorbatchev.com/pub/sh/current/scripts/shBrushPhp.js',
  'text plain             http://alexgorbatchev.com/pub/sh/current/scripts/shBrushPlain.js',
  'py python              http://alexgorbatchev.com/pub/sh/current/scripts/shBrushPython.js',
  'ruby rails ror rb      http://alexgorbatchev.com/pub/sh/current/scripts/shBrushRuby.js',
  'sass scss              http://alexgorbatchev.com/pub/sh/current/scripts/shBrushSass.js',
  'scala                  http://alexgorbatchev.com/pub/sh/current/scripts/shBrushScala.js',
  'sql                    http://alexgorbatchev.com/pub/sh/current/scripts/shBrushSql.js',
  'vb vbnet               http://alexgorbatchev.com/pub/sh/current/scripts/shBrushVb.js',
  'xml xhtml xslt html    http://alexgorbatchev.com/pub/sh/current/scripts/shBrushXml.js'
);
SyntaxHighlighter.config.bloggerMode = true;
SyntaxHighlighter.all()
</script>

測試:
<pre class="brush: groovy">
println 'Hello World'
println 1 + 2 + 3
</pre>

用Firefox的Firebug外掛,在"網路"監測的功能中,就可以看到實際的作用情形。

2010年10月11日

快快樂樂認識 Groovy 的 Grapes 及 grab()

Grape (The Groovy Adaptable Packaging Engine or Groovy Advanced Packaging Engine) is the infrastructure enabling the grab() calls in Groovy, a set of classes leveraging Ivy to allow for a repository driven module system for Groovy. This allows a developer to write a script with an essentially arbitrary library requirement, and ship just the script. Grape will, at runtime, download as needed and link the named libraries and all dependencies forming a transitive closure when the script is run from existing repositories such as Ibiblio, Codehaus, and java.net.
from http://groovy.codehaus.org/Grape

Grape是一項Groovy的提案(proposal),它用來解決Java長久以來令開發者困擾的一個問題「每次都要到處抓*.jar的函式庫套件」。

Grape的作法是提供一個Grab()方法,指定 groupId(group)、artifactId(module)、version 三個設定值,Groovy程式在執行時,會自動幫忙下載指定的函式庫檔案。

在不久之前,我們通常使用Maven來處理這麻煩事;但是在目前新的Groovy發行版,我們已經可以直接使用Grape的功能,它的實現方式是使用 @Grab 這個標記(annotation),我們直接在一段Groovy程式碼中,直接嵌入@Grab的宣告,不必透過其他軟體(只需要安裝好JDK、Groovy),就可以獨立完成指定的函式庫下載、再執行程式。

舉例來說,安裝好Groovy之後,我們使用 GroovyWS 寫一段 Web Services 的測試程式,需要引用 groovyx.net.ws.WSClient 這個類別。

很不幸地,預設安裝好的Groovy並沒有提供我們需要的套件,也就是缺少了 groovyws-0.5.2.jar 這個檔案。

以下的程式碼加入 @Grab ,再第一次執行的時候會比較慢一些,因為會自動下載 groovyws-0.5.2.jar 以及它相依的套件,第二次以後因為已經取得套件,就會略過直接執行。真的沒有看錯,除了指定版本的套件以外,連這個版本的套件所依賴的其他相關套件, Grape 也會一併幫我們下載。我想任何一個寫過稍微大一點的 Java 程式的人,都會清楚處理相依套件的麻煩,就像沒有yum工具的時代,需要到處找rpm檔案的那種痛苦。

@Grab(group='org.codehaus.groovy.modules', module='groovyws', version='0.5.2')
import groovyx.net.ws.WSClient

def proxy = new WSClient("http://localhost/api/SimpleTest.asmx?wsdl", this.class.classLoader)
proxy.initialize()

如果你堅持認為 @Grab 寫在程式碼裏面很礙眼,Grape也提供另一種選擇,也就是 grape 指令。它的格式如下:
grape install []

查詢已經安裝的套件可以用:
grape list

以剛才 GroovyWS 的例子來說,以下的 grape 指令能完成與 @Grab 相同的工作:
grape install 'org.codehaus.groovy.modules' 'groovyws' '0.5.2'
(這道指令實際上會自動下載數十個.jar檔案,相信我,你不會真的想要一個一個慢慢抓!!!)

因此,如果不想再程式碼裏面寫 @Grab 宣告,就可以把需要用到的套件,都用 grape 指令寫程 bash 或 batch 批次檔,讓我們在development或production階段都能自動完成相依套件的安裝,而不必東找西找還擔心漏掉其中一個。

另外一個好處就是,這些我們的程式需要用到的相關套件,並不必跟程式碼放在一起,Grape預設會把套件檔案都保存到 $USER_HOME/.groovy/grapes 這個資料夾,因此我們只需要維護自己寫的程式碼,而不必在lib資料夾中放一堆雜七雜八的*.jar檔案。

因此...
對於使用SVN管理的Java專案來說,不再需要把雜七雜八的一大堆*.jar檔案放到SVN repository,麻煩的事交給Grape就對了。
對於一個簡單的Groovy程式碼,只有一個檔案,但不小心引用很多個套件,只要簡單地放個 @Grab 宣告,就可以把它發佈出去,而不必夾帶一堆*.jar檔案,還要告訴End User如何設定正確的CLASSPATH。

2010年10月6日

用 VirtualBox 建構開發、測試、服務環境

在建置新的伺服器時,我嘗試用虛擬機器提供對外服務(WEB、FTP、SSH、SVN、MySQL等),而實體機器僅供內部網路存取,這樣做可以建立第一道網路防線,當入侵事件發生時,影響範圍可以被隔離在虛擬機器中。

而虛擬機器的軟體,我選擇不必付費的VirtualBox,對流量不大的網路服務來說,用VirtualBox已經可以提供相當足夠的效能。

伺服器架構:
實體機器 Ubuntu 10.04 Desktop + VirtualBox 3.2.8
虛擬機器(1) Ubuntu 10.04 Server Master
虛擬機器(2) Ubuntu 10.04 Server Slave
虛擬機器(3) Fedora 13
虛擬機器(4) Windows XP

在這新的架構變得很容易維護,當實體機器掛點時,若開機硬碟沒問題,Ubuntu+VirtualBox只要換到新的硬體上就能立即運作;即使開機硬碟也掛點,重灌Ubuntu+VirtualBox並不會需要超過一小時。

對虛擬機器來說,備份的方式有很多選擇,可以從虛擬機器內部系統進行日常備份,也可以定期用實體機器備份整個虛擬機器,或是定時將Master虛擬機器sync到Slave虛擬機器,還可以建立Snapshot等。多了這些方便的措施,也不用擔心伺服器軟體進行全面升級後會發生問題,因為一切都可以先模擬測試一遍。

很多服務並不需要一台獨立的機器,例如SVN、GIT的repository server,只要建立一個記憶體256或512MB的虛擬機器,就足以應付日常需求,以目前新購PC記憶體一條都是2GB起跳的情況,分給四個虛擬機器用都綽綽有餘。

在開發階段使用的工作站,我也同樣以VirtualBox建置可以快速切換不同系統的開發環境,再多的選項組合,例如Windows+Linux+FreeBSD+SQL Sever+Oracle+PostgreSQL+Apache+Tomcat+...等,可以分別建立各專案專屬的虛擬機器,提供開啟後立即可用的開發環境。這樣一來,只需要一台工作站就可以同時在不同開發環境之間切換。

工作站架構:
實體機器 Ubuntu 10.10 Desktop + VirtualBox 3.2.8
虛擬機器 數十種不同組合的開發環境

雖然虛擬機器也要開關機,不過VirtualBox可以不用真的關機就把虛擬機器「關閉」,並且「儲存機器狀態」。其他的虛擬機器軟體也有同樣功能,但是目前用起來VirtualBox給我的感覺最快速,即使虛擬機器設定2G或4G記憶體大小,不管儲存、還原都在滿意的時間內就完成動作,而且還原後可以立即順暢地繼續作業,並不會感到回應遲鈍。在同時需要操作很多個開發環境時,可以把幾個暫時用不到的虛擬機器先關閉,等需要用的時候再還原,因此這功能是否能順暢就很重要。

VirtualBox只需要簡單的設定,將「啟用IO APIC」打勾,就可以直接開啟VMWare的虛擬機器,不僅相容且執行效能也感覺不到差異。將VMWare的虛擬機器轉換給VirtualBox使用很簡單,因此我使用VirtualBox同時管理這兩種異質的虛擬機器。

要建構可以流暢執行多虛擬機器的硬體並不難,因為三個影響效能顯著的零組件:多核心處理器、記憶體、硬碟都已經非常便宜。假設一部四核心、16GB記憶體、8TB硬碟的PC可以同時運作10個虛擬機器,只要購入四部PC就可以打造一個能玩得很開心的實驗環境。

2010年9月23日

WAPP = Windows + Apache + PostgreSQL + PHP5

BitNami WAPPStack greatly simplifies the development and deployment of PHP applications. It includes ready-to-run versions of Apache, PostgreSQL, PHP and phpPgAdmin and required dependencies. It can be deployed using a native installer. BitNami WAPPStack is distributed for free under the Apache 2.0 license.

Windows環境開發PHP5網頁應用,若資料庫搭配MySQL,則有許多All-in-one的整合安裝程式可用,例如XAMPPAppServ等。開發階段需要的Apache+PHP5+MySQL+phpMyAdmin等,都可以一次搞定,省去個別下載、安裝及設定的困擾。

但如果選用PostgreSQL資料庫,是否也有這樣方便的整合安裝程式呢?

當然也可以拿XAMPP、AppServ來加裝PostgreSQL,但BitNami WAPPStack已經幫我們把一切搞定了,它整合以下開發PHP5+PostgreSQL的基本需求軟體。
  • Apache 2.2.14
  • PostgreSQL 8.4.4
  • PHP 5.2.14
  • PHPPgAdmin 4.2.2
下載WAPPStack: http://bitnami.org/stack/wappstack

雖然只要一個安裝程式就能搞定,但我們如果希望它能更方便一點,其實可以自己打包成可攜式的綠色軟體。我們只要將它安裝至特定的路徑,例如 C:\WAPP ,再把整個資料夾打包,就可以放在隨身碟帶著走,需要用它的時候再解到相同位置。

但是少了安裝程式的執行過程,有些動作就必須自己寫批次檔代替,WAPPStack自動設定的服務名稱有wappstackApache、wappstackPostgreSQL兩個。以下的批次檔需要放在WAPP資料夾下,可以幫我們處理掉安裝、移除、啟動及停止服務。

install services
serviceinstall.bat INSTALL

uninstall services
serviceinstall.bat REMOVE

startup services
net start wappstackApache
net start wappstackPostgreSQL


shutdown services
net stop wappstackApache
net stop wappstackPostgreSQL

2010年9月21日

[Lighter Java] Select Java Client / Server VM

最近發現一些啟動java vm的參數,會影響到伺服器運作的效能。若執行的程式很小,不太需要調校,但是對Tomcat、JBoss等J2EE container來說,一些參數的設定就會有比較明顯的影響。

JVM在啟動時,會依據作業系統及處理器核心數量、記憶體容量判別 Client 或 Server 兩種機器類型。

從Oracle提供的「Server-Class Machine Detection」文件來看,Java SE6對伺服器等級機器(server-class machine)的定義為:「至少擁有2個核心以上的處理器、2個Gigabyte以上的實體記憶體。」

實際啟動JVM時,也會根據作業系統的不同而有預設的差異。
  1. 在AMD64平台上,不管Solaris/Windows/Linux預設都是server vm,並且不提供client vm。
  2. 在x86(i586)平台,除Windows是預設client vm,其他Solaris/Linux則是依照伺服器等級,若條件符合就預設server vm,否則還是會使用client vm。
所以需要調整的情況,就是當作業系統為32位元的Windows,擁有足夠的記憶體容量及多核心處理器,而java卻選擇client vm,我們需要手動指定server vm。另一種情況則是32位元的Linux伺服器,雖然未達到Java SE6定義的伺服器等級,但那部伺服器專跑J2EE應用,可以佔用大部分系統資源,仍可指定為server vm。

並非每一種情況用server vm執行都會比較好,依照Oracle提供的文件所述,server vm在啟動時可能會比較慢,但長時間運作來看則會較好的效能。

要判別java預設用哪一種vm,可以用 java -version 查詢。

例如這是一個server vm的輸出。
java version "1.6.0_21"
Java(TM) SE Runtime Environment (build 1.6.0_21-b06)
Java HotSpot(TM) 64-Bit Server VM (build 17.0-b16, mixed mode)

以下則是client vm的輸出。
java version "1.6.0_21"
Java(TM) SE Runtime Environment (build 1.6.0_21-b07)
Java HotSpot(TM) Client VM (build 17.0-b17, mixed mode, sharing)

在java後面添加 -server 或 -client 參數,可以建議java使用指定的 client或server vm。
  1. java -server
  2. java -client
要測試java是否依照參數啟動,同樣用-version指令。
  1. java -server -version
  2. java -client -version
有些情況下, java -server 會跑出以下的錯誤訊息。
Error: no `server' JVM at `C:\Program Files\Java\jre6\bin\server\jvm.dll'.

這種情況是因為安裝的Java Runtime並未包含server vm需要的支援,我們需要將環境變數的PATH設定,重新指定為JDK的bin路徑,例如「c:\Program Files\Java\jdk1.6.0_21」。

"c:\Program Files\Java\jdk1.6.0_21\bin\java.exe" -server -version

要設置 -server 最好不要直接寫在 JAVA_OPTS ,因為對於一些GUI應用程式或Applet來說,用server vm執行並不見得比較好;因此設定在 CATALINA_OPTS (tomcat) 或 JBOSS_OPTS (jboss) 是比較好的選擇。

圖片來源:The Java HotSpot Performance Engine Architecture
根據Java HotSpot白皮書的說明,Client VM的編譯器不像Server  VM執行很多的最佳化,所以花比較少時間分析和編譯代碼,因此Client VM啟動速度較快。


The Client VM compiler does not try to execute many of the more complex optimizations performed by the compiler in the Server VM, but in exchange, it requires less time to analyze and compile a piece of code. This means the Client VM can start up faster and requires a smaller memory footprint.

延伸閱讀:

2010年9月12日

話說退伍後找工作這回事

退伍後最常被問到的問題,就是「在哪裡工作」。

認識的人大多退伍、畢業,準備開始就業,都好關心「工作」這件事,好像沒有工作整個人就會枯萎似的。這種焦急程度和以前在學校時判若兩人,以前那些面對未來的現實還能放慢腳步、神態自若的學子,一夕之間都融入現實社會了。許多人關心在「哪裡」工作,許多人在意是不是一份「好工作」。

我這才察覺到自己似乎也要對「工作」這件事情,抱著嚴肅一點的態度去面對。

有不少人問我幹嘛不去業界找間科技公司待?!這實在很難簡短回答。

只能說,心裡最後的決定都是經過無數次的反覆掙扎,才痛下決心。

在當兵入伍前,我就已經不打算退伍後要急著去找工作,如果按照原訂計畫,我是想先出國一陣子再說,只是計畫趕不上變化,沒辦法按部就班地執行。

大概從七年前開始算起,我雖然一直都是念日校的學生,但其實我花在工作的時間一直遠遠大於課業的時間。有很多時候,我沒去上課,是為了趕案子,報告、考試沒準備就上陣,是因為前天案子做不完,爆肝熬夜到天亮。

為什麼不好好當個學生就好呢?!這也很難回答。

早在我還年幼不懂事的時候,我就已經深刻感覺到自己對念書沒啥興趣,只想把時間揮霍在可以獲得樂趣的東西。所以國中畢業後,我心裡早就沒有要去升學的準備;繼續待在學校當個學生,一來是父母希望我這樣做,二來是出去外面也不知道要幹嘛,第三則是抱持著到學校或許可以遇到相同興趣的人,所以最後隨便就去念了五專。

專四、專五我花大部分的時間在工作、網咖、圖書館,很多時候我並不知道學校老師教過什麼。

五專快畢業的時候,原本已經準備好先當兵找工作的,但莫名其妙居然還考得到一間學校,我從沒想過花兩三個星期看題庫會有什麼效果。這一次是我爺爺希望我繼續念,二來是我覺得最後一張畢業證書能印個國立似乎好看些,第三則是繼續念書我仍可以維持工作及收入。

繼續念二技的選擇,後來我覺得是對的。因為在那段時間,我得到和更多公司合作的機會,不乏能給更好條件的公司,學校給的工讀金拿來付學費也綽綽有餘,多餘收入足夠我繼續在興趣上揮霍。而覺得自己念書不如人,也讓我在這段時間多少知道學校老師教過什麼。

後來繼續念研究所,其實已經完全在意料之外,我並沒太大的興趣做學術研究,但暫緩兵役讓我有時間繼續完成手邊的工作。那兩年我花在學校的時間不多,而在學校大多時間也是幫老師工作。大多數的時間我除了工作,也增加其他不少休閒玩樂,但這並沒有讓我荒廢論文研究的課業,只是爆肝的時間又多了點,白天上課要硬撐著眼皮。這兩年的收入明顯多了些,讓我可以揮霍在更多的興趣上,時間過得很充實,接觸更多東西讓我覺得這段時間值得。直到畢業後才發現,研究所兩年期間的收入加總有超過一百萬。

一直有好長一段時間,每天除了白天上課還要完成好幾件工作,我覺得好累,很不想再工作了。如果有機會真想逃出國去走走,呼吸新鮮空氣。山裡騎單車讓我能短暫滿足幻想,所以我騎車。

作為一個不務正業的學生,我遇到的大多問題都不是來自課業,而是來自工作。

當工作把自己逼到一個懸崖上,就會開始重新思考為什麼工作。

我曾經告訴我的指導教授,以後我不想做軟體設計的工作,他很訝異、覺得可惜。但其實是我已經把職業和志業給混淆了,所以無法分辨什麼才是自己想要的價值所在。

入伍讓我有機會告別手邊所有工作,無事一身輕地放長假去。當兵的日子雖然苦悶又無聊,但卻是我這幾年來,少有的心理休息時間,每天就是慵懶地去完成一連串不需動腦的雜事,無時無刻都有人可以聊天打屁,沒什麼壓力。

在每次夜深人靜站哨時,我經常思考「志業」與「職業」的問題。

退伍後要急著找好工作?!我找不到這麼做的理由為何,與其著急還不如好好休息,思考一下如何發展志業,而不是急促開始一生的職業。

職業是個枷鎖,而志業讓你得以自由。

有了好幾年累積的辛酸路程,在退伍後重構「生活」時,我對於工作更小心謹慎地設下自己的規則,以免落入充滿職業的人生。

找一個在別人眼中似乎還不錯的大公司的工作,然後開始把「job description」的內容上手,凡是要看好的那一面,培養對工作的熱忱及興趣,把被交付的工作做得盡善盡美,努力求表現好取得升遷加薪機會,在這家公司看不到希望就換一家試試,再怎樣都要努力得到退休的機會。

以上,我並不希望發生在自己身上,因為那是我眼中的職業。

我相信每個人都有天賦,但是要讓天賦自由,並不是單單選擇一個好的職業就能辦到。並非每個人都適合到一家大企業任職,有些人天生很適合,有些人則不,沒有好與不好的問題。

發展一條最適合自己的路,並不容易,有時候甚至動輒創業才能找到這條路。這條路不見得是最舒適,它可能滿佈荊棘與泥沼。但只要走上最適合自己的路,很容易就會發現心情是隨時保持愉悅的,每跨出一步都是充滿動力,因為心裡早已清楚自己的目標就在前方。

我知道「設計能幫助別人的好軟體」是我這輩子的理想,我希望自己的志業是成為能對世界作出那麼一點貢獻的軟體設計師,我只是個平凡人,所以只要有一丁點貢獻就心滿意足。軟體設計讓我很容易找到樂趣,但也很容易迷失、迷惘。這把兩面刀刃劃傷自己的時候,就是當我察覺自己正在做軟體設計,但不是為了理想,而只是為了自己的飯碗、為五斗米折腰的時候,那種時候,一點一滴流失的生命,換來的只有錢而沒有快樂。

因此,我對工作仍抱有不少想像。
  • 要有足夠的時間陪家人或自己獨處
  • 興趣即工作,隨時都能得到樂趣,不需要培養就能熱血沸騰
  • 工作會上癮,能沉浸在其中無法自拔,就像打一款經典PC GAME那樣
  • 工作與理想有相同的目標,要對社會有貢獻
  • 能真的發揮所長,心裡很明確知道這是天賦,而不必欺騙自己
  • 每天早上都能興奮地醒來、期待著趕快開始工作
  • 希望時間腳步放慢點,可以繼續沉浸在工作的愉悅中
  • 週末度假時,能抱著期待挑戰下週工作任務的心情 
  • 五個工作天結束時,能驚覺自己完成大量的任務
  • 能夠不斷追求更好的效率,完成更困難的挑戰,而不必計較是否值得
  • 需要休息的時候,隨時能夠放下,不用勉強自己的身心
  • 即使在工作中,仍隨時能感覺到時間屬於自己
  • 收入不必太多,但是和努力、專業程度成正比,能滿足生活所需和合理物質慾望即可
  • 不要把獲利擺第一,至少心裡確實這樣想,雖然實際上還是要賺錢才能活
  • 工作和生活沒有清楚的界線,工作完全是自己生活的一部分
  • 能不斷充實新知、專業,除工作技能,還能不斷學習跨領域知識
  • 一天比一天更專業,有足夠的時間研究、創造新的東西
  • 能夠全力以赴去做自己認為對的事,而不必浪費時間獲得每個人的支持
  • 每天都能有正常的作息、用餐及運動時間
  • 可以得到自己渴望的東西,至少未來有機會
  • 當想法改變時,可以不用因此換工作,就能實現新的想法
  • 理想總有一天會實現
既然志業不是一蹴可藉,那用一輩子時間來換總行吧?

或許,找個工作,有份收入,對初入社會口袋空空的我們來說很重要。但對我來說,我寧願多花點時間讓自己有機會做志業、而非職業。

在決定自己要做什麼工作時,我不在乎自己薪水跟別人比起來是多是少,工作能讓自己得到多少真正想要的價值才是重點。我知道收入是要靠自己努力而不是等公司決定,我也從來不期望一家公司會給工程師「遠高於工程師」的薪水,換句話說也不必期望一家公司會給經理「遠高於經理」的報酬。相較之下,一家出發點良好的微型新創公司,比起金字招牌的大大大公司更吸引我,一個能幫助我完成階段目標的任務,也遠比一個讓別人覺得好聽的職稱更有趣,我只在意自己的能力能成長多少%並發揮多少%。不在一家公司上班的時候,自己還有多少價值才是我所關心。

很多事情都不是在人力銀行急急忙忙找份工作,就可以看得見、想得清楚。比起「在做什麼工作」,「最近玩什麼」、「在研究什麼」、「發現些什麼」,或許更能夠讓你我交流。

找工作這回事,對我來說,慢慢來,比較快!

2010年9月11日

Blogger加掛SyntaxHighlighter,顯示漂亮的彩色程式碼

Syntax Highlighting是一種讓程式碼更容易閱讀的方法,透過不同色彩及字體的標示,讓閱讀者更容易分辨變數、保留字、函式等關鍵字。

以PHP來說,最常用的Syntax Highlighting工具就是老牌的GeSHi,它支援的程式語言種類之多,讓人冒出驚嘆號!而且直到最近它一直都有在維護、改良,我在一個星期前發現它新版不能正確解析Scheme程式語言的程式碼,把bug提交給GeSHi開發者的Issue Tracker,結果很快就釋出改正的新版本。

然而GeSHi需要在伺服器端做處理,如果是自己架設的部落格,要整合GeSHi並不難,而且通常都有現成的外掛可用。

但是以Blogger這種放別人家的網誌服務,就沒辦法用簡單的方法整合GeSHi。

幸好有syntaxhighlighter的出現,僅靠瀏覽器端執行的JavaScript就可以達到相同效果。

最新的syntaxhighlighter版本已經移到這裡「SyntaxHighlighter  3.0.83」,目前仍有在持續維護。雖然支援的程式語言種類沒有GeSHi那樣包山包海,但對於常見的程式語言來說(如下列表),已經相當夠用了。
AS3, Bash, ColdFusion, CSharp, Cpp, Css, Delphi, Diff, Erlang, Groovy, JScript, Java, JavaFX, Perl, Php, Plain, PowerShell, Python, Ruby, Scala, Sql, Vb, Xml

使用SyntaxHighlighter對網頁的SEO也是有幫助的,因為程式碼在HTML原始碼中是完整的呈現,像Pastebin.com用JavaScript的方式內嵌,實際網頁原始碼根本沒有包含程式碼;同時,在最後輸出給瀏覽器的HTML中,<pre>...</pre>之間是原始的程式碼文字,並不會被加入額外的HTML標籤。所以瀏覽者在搜尋時,關鍵字若出現在網誌提供的程式碼中,文章就會更有機會被找到。

讓人興奮的是,SyntaxHighlighter有提供公開的Hosted Version,這意味著純粹使用Blogger寫網誌,而沒有申請其他檔案寄存服務的使用者,並不用再麻煩地去註冊一個空間來放所需的檔案,也不必偷偷使用別人的連結。設定的步驟相當簡單,請參考以下設定步驟。

SyntaxHighlighter預設已有不錯的行號顯示:

在Blogger的後台,打開「設計」、「修改HTML」。

先找到<b:skin>標籤,在此標籤前加入以下代碼。
<!-- SyntaxHighlighter  3.0.83-->
<link href='http://alexgorbatchev.com/pub/sh/current/styles/shCore.css' rel='stylesheet' type='text/css'/>
<link href='http://alexgorbatchev.com/pub/sh/current/styles/shThemeDefault.css' rel='stylesheet' type='text/css'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shCore.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shAutoloader.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushAS3.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushBash.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushColdFusion.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushCSharp.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushCpp.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushCss.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushDelphi.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushDiff.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushErlang.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushGroovy.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJScript.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJava.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJavaFX.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushPerl.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushPhp.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushPlain.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushPowerShell.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushPython.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushRuby.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushScala.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushSql.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushVb.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushXml.js' type='text/javascript'/>

再找到</body>標籤,在標籤前加入以下代碼。
<!-- SyntaxHighlighter  3.0.83-->
<script type='text/javascript'>
     SyntaxHighlighter.all()
</script>

完成修改後,儲存。

接著在編輯網誌文章時,使用「修改HTML」模式,使用<pre>標籤來呈現程式碼,而class屬性則設為「brush: 程式語言代碼」,程式語言代碼請參考在文章開頭的SyntaxHighlighter已支援程式語言列表。
<pre class="brush: groovy">
println 'Hello World'
println 1 + 2 + 3
</pre>

另一個議題是,當我們要放的程式碼文字,包含了HTML的特殊字元,例如大於>、小於<等,這時候就需要用HTML編碼工具先轉換好,否則Blogger會認為文章包含不合法的HTML標籤。

如果您使用的瀏覽器剛好是先進的Firefox,可以參考我們先前發表過的Blogger HTML Encode文章,使用我們開發的Greasemonkey Script即可以輕鬆解決這個問題。

使用Groovy與OpenCSV,動態Class Library加載

由於Java程式依賴CLASSPATH設定,如果將需要的JAR檔都丟到CLASSPATH指定的lib路徑,很一定會造成資料夾內容凌亂不堪;但每次要執行Java程式都要以-cp指定自定CLASSPATH的話,又會是個麻煩事。
對於可以很方便寫小程式的Groovy來說,我喜歡使用懶人做法,把「開始資料夾\Groovy\Start GroovyConsole」打開就開始寫程式,特別是拋棄式的小程式,寫完執行目的達到就可以丟掉的那種,我可不想又為它建一個資料夾、存檔,而且還要跟需要的JAR檔放在一起。
在Groovy程式裡我們可以用this.class.classLoader.rootLoader.addURL()加載需要的JAR檔,而不需要去修改系統變數或是執行參數,JAR檔喜歡放在哪邊都沒關係。
以下的Sample程式碼,展示Groovy如何使用OpenCSV提供的CSVWriter建立一個CSV檔。
jar_file = new File("D:\\javalib\\opencsv-2.2\\deploy\\opencsv-2.2.jar")
csv_file = new File("D:\\yourfile.csv")

this.class.classLoader.rootLoader.addURL(jar_file.toURL())
import au.com.bytecode.opencsv.CSVWriter

String[] row = "one,two,three".split(',')

writer = new CSVWriter(new FileWriter(csv_file), (char)'\t')
writer.writeNext(row)
writer.close()

2010年9月10日

Java / Groovy 的 HTML Encoding

開發網頁應用時,有些情況我們需要將資料庫讀取的文字,先經過編碼後再輸出,因為直接輸出原始文字,有些文字會被當作HTML的標籤或特殊字元處理。

例如程式碼中的 大於"<" 、 小於">" 等符號。

PHP程式可以用:
  • htmlspecialchars
  • htmlentities
在Java及Groovy程式我一直沒認真去找最佳答案,JSTL有escapeXml屬性,EL有 ${fn:escapeXml(problem)} 有些情況用string replace,有些情況用XML generator提供的function,總之,解決方法很多但就是不知道哪個比較好。

今天又遇到需要輸出大量程式碼的問題,再度認真google一下,發現Apache Commons Lang有提供StringEscapeUtils

下載 Apache Commons Lang

直接呼叫static method即可,用起來算是方便。
org.apache.commons.lang.StringEscapeUtils.escapeHtml(source_text)

這是目前我覺得滿意的解決方式,因為 Apache Commons 出品可以信賴,另外它也提供很豐富的功能(參考文末提供function list)。要說有什麼缺點,我想應該就是殺雞用牛刀的問題吧,為了一個小功能又要放進新的library,而且只用到其中一個class的一個method。不過在開發J2EE應用時,我已經不太在乎殺雞是不是用牛刀,目前手邊的專案規模還很小,但 WEB-INF/lib 資料夾就已有36個JAR檔,God bless my java。

CSV、HTML、Java、JavaScript、SQL、XML一包搞定。

static String     escapeCsv(String str)
static void     escapeCsv(Writer out, String str)
static String     escapeHtml(String str)
static void     escapeHtml(Writer writer, String string)
static String     escapeJava(String str)
static void     escapeJava(Writer out, String str)
static String     escapeJavaScript(String str)
static void     escapeJavaScript(Writer out, String str)
static String     escapeSql(String str)
static String     escapeXml(String str)
static void     escapeXml(Writer writer, String str)
static String     unescapeCsv(String str)
static void     unescapeCsv(Writer out, String str)
static String     unescapeHtml(String str)
static void     unescapeHtml(Writer writer, String string)
static String     unescapeJava(String str)
static void     unescapeJava(Writer out, String str)
static String     unescapeJavaScript(String str)
static void     unescapeJavaScript(Writer out, String str)
static String     unescapeXml(String str)
static void     unescapeXml(Writer writer, String str)

Ajaxload 免費提供開發Ajax應用時所需的Loading圖示

開發AJAX應用時,如果在背景更新某個區塊的HTML代碼,會比起重新載入頁面流暢許多,但是在等待網頁伺服器回應的這段時間,使用者會不知道自己剛剛按下去的動作,到底是執行了沒。

這時候可以放一個Loading的圖示,讓使用者知道目前是在等待回應的狀態。

在找合適的Loading圖示時,剛好發現這個 Ajaxload 網站,免費提供多款樣式的圖案,有自訂前景背景及透明背景等選項,很容易就能夠挑到一個滿意的樣式。

2010年9月7日

早該知道的程式設計兩三事

今天一早打開Desire的RSS Reader,就點進這篇文章《Programming Things I Wish I Knew Earlier》,作者Ted Dziuba以linux geek的觀點談論程式設計這件事。

以下引述自原文內容。

會有這些想法,是因為在新創公司工作,軟體開發人員同時必須身兼系統管理員。

兩條簡單的規則,避免過度的複雜化

  1. 避免寫一支程式同時取用兩個以上的資料來源
    最佳情況就是讓程式跟大多數Unix指令工具一樣,一個程式負責一個input產生一個output。
  2. Linux可以做的事,就不要傻傻地自己去做
    除非xargs指令解決不了問題,否則就不要去用Hadoop MapReduce (一種新興雲端概念的框架)
    不要實作自己的鎖定服務,除非Linux的檔案鎖定沒有作用
    盡量用ImageMagick處理影像檔,除非必要否則別去用PIL之類的影像處理函式庫
    現代的Linux發行版已經解決大量的問題,你需要做的只是去找方法
(譯註:如果能解決問題的工具不是OpenSource軟體,身為台灣人,你可以選擇用盜版、也可以自己重新實作,在良心及肝功能之間作抉擇。所幸大部分我所需的功能都有OpenSource替代方案。拿xargs跟Hadoop MapReduce相比有些誇張,換個方式說,能用SQLite/MySQL滿足的需求,就不要傻傻地用SQL Server或Oracle Database搞死公司自己。ImageMagick是很方便的命令列影像處理軟體,最常用的是它的convert轉檔指令,做個縮圖轉格式啥的靠它就能搞定,通常沒必要去用緩慢又要自己handle錯誤的函式庫,但使用ImageMagick要注意安全性問題)

當你真的需要時才去做平行處理,而不是光想要就去做
一台機器處理得不夠快,無法滿足需要時,應該去分析為什麼跑得這麼慢,而不是急著去做更複雜的平行處理。

如何照料一個行程
在一個行程掛點(crash)時,要讓它可以自動重新執行,有Upstart工具可以用,設定檔的範例如下。
respawn
respawn limit 10 600
exec python /path/to/my/program.py

NoSQL is NotWorthIt
Ted嘗試將Redis用在非主要任務的系統,那些應用程式的資料如果流失並不是什麼大不了的事。大多時候可以運作,但問題發生時,Redis伺服器hang住,socket連線接通後卻沒有回應,重新啟動伺服器花了45分鐘才恢復。也許其他NoSQL資料庫情況會好一些,但是問題點還是一樣,為什麼好端端的PostgreSQL同樣可以完成工作不用,而非要去玩新奇卻必須冒險的東西。

Event Loops are Just Okay
Wikipedia上提供的一段Event Loops程式碼示範。

function main
    initialize()
    while message != quit
        message := get_next_message()
        process_message(message)
    end while
end function

簡單說,就是每次收到任務時才開始做事,而且必須做完一件才接受下一個任務。
最危險的是程式設計師搞不清楚自己做了什麼事。在event-loops及thread之間抉擇最佳的方式,必須視I/O bound等軟硬體的特性,有時也可以混著用。

Hardware Matters
雲端運算的強大似乎很有吸引力,當它變得高效能又可靠時,世界各地的不同電腦將成為你程式執行的實體機器。這裡不是在談論Extra Large EC2的容量超大,而是一個系統效能特徵為何。
舉例來說,對輸出資料量龐大的應用程式,你會希望呼叫 fsync (通常是用在實際將資料寫入磁碟) 時盡可能早點結束,fsync是作業系統提供的函式,它你的程式無法控制的黑盒子。當這是一個瓶頸時,必須靠的是硬體升級,裝一個內建電池的RAID控制器,這樣 fsync 呼叫幾乎可以立即完成,因為RAID控制器的記憶體可以先保存資料,即使遇到電源失效,它也能保證資料最後會被寫入。
對於必須讀取大量資料的應用程式,當對檔案的隨機存取動作頻繁時,花多點錢裝上效能不可思議的固態硬碟(SSD),就能夠解決磁碟讀取效能的問題(但是對循序讀取的程式來說差異就沒那麼大)。
硬體開銷是資金的好去處之一。要解決效能的問題,花錢升級硬體比起重寫程式有效率多了。當你用普通的機器執行程式,就不該期望它能跑出不普通的效能。

2010年9月6日

網頁內嵌PDF文件閱讀器使用Google Docs Viewer

Google Docs Viewer  目前支援DOC、PDF、PPT、TIFF三種檔案格式。

這個服務有開放給End User,只要連到下面這個網址,填入檔案位址「必須符合上述幾種有支援的檔案格式」,就可以產生線上閱讀器的連結位址。
http://docs.google.com/viewer


要使用這個閱讀器,檔案必須已經上傳到某網站,且必須是公開可讀取。Google Docs Viewer服務並不提供上傳檔案,因為Google Docs、Google Sites等服務都可以寄存文件檔案。

以下是一份PDF格式的投影片網址,以及產生的線上閱讀器位址。
http://www.ubuntu.com/system/files/u35/Centrify-Final.pdf
http://docs.google.com/viewer?url=www.ubuntu.com%2Fsystem%2Ffiles%2Fu35%2FCentrify-Final.pdf

Google提供Docs Viewer服務,對很多網路應用應該能提供不少幫助。

還記得以前念的學校導入一套網路學習平台(LMS),老師們可以將PDF、PPT、DOC的教學文件丟到線上課程中。但如果沒有另外製作HTML版本的教材,那用起來就挺麻煩,學生的電腦必須裝有PDF Reader、Office Word/PowerPoint等軟體。

這樣子操作起來,線上學習平台變得很像FTP伺服器,只要閱讀軟體跟瀏覽器的整合不是很理想,就必須先下載到自己的電腦才能打開。而且現在的閱讀裝置愈來愈多,小筆電、手機、平板電腦、電子書,只為了看文件而在這些裝置加入肥大的軟體,即使使用者願意裝,也不見得裝置跑的作業系統能允許,即使真能裝上相容的軟體,還不見得能跟學習平台良好整合。

Google Docs Viewer似乎幫我們解決這問題了!(雖然Term of Service內容還看不到@@)

網頁內嵌Docs Viewer簡單到不行,只要幫文件所在網路位址產生一串<iframe>。
<iframe height="780" src="http://docs.google.com/viewer?url=www.ubuntu.com%2Fsystem%2Ffiles%2Fu35%2FCentrify-Final.pdf&amp;embedded=true" style="border: medium none;" width="600"></iframe>

J2EE Servlet request.getParameter() UTF-8 encoding issue

在J2EE平台開發Web Application,編碼是一個要小心處理的問題。儘管我們選擇整個系統採用一致的UTF-8編碼,卻有以下一堆設定要注意:
  1. JSP pageEncoding
  2. contentType in http header and html
  3. response.setCharacterEncoding
  4. request.setCharacterEncoding
  5. useBodyEncodingForURI
  6. URIEncoding
再搭配Groovy或Quercus(php)使用,除了file.encoding問題,還有GET/POST資料處理的編碼問題。

為了做最後一到防線,讓以後碰到編碼問題不必東改西改,我設計一個fetch method來解決GET/POST編碼問題。

pseduo code

class ServletHelper {
  method fetch ( name, defaultValue ) {
    if request.getParameter( name ) not exists {
        return defaultValue
    }
    if request.characterEncoding is UTF-8 {
      return request.getParameter( name ) as UTF-8
    }
    else {
      return request.getParameter( name )
    }
  }
}
lyhcode by lyhcode
歡迎轉載,請務必註明出處!