l

2010年11月25日 星期四

冷笑話

Nov. 25 21:38~21:59

Teddy 剛剛才發現,今年已經寫了 100 篇,這一篇是第 101 篇。原本想補上『消除浪費 (7):Defects』這一篇,但是想了想,defects 或是 bugs 的產生,一定是一種浪費啊,沒什麼好扯的,所以就換個口味,寫兩個 Teddy 『原創』的冷笑話... 不過這兩個笑話僅限於經常搭乘 307 公車往來台北與中和的鄉民們才比較容易體會

冷笑話(一)

話說 Teddy 所搭乘的『大有巴士 307 』正以極快的速度行駛在『華中橋』上,此時 Teddy 所搭乘的公車冷不防的突然被另外一部公車所超越。各位看官,到底是那一路公車居然可以贏過『公車之霸』?

答案:另外一輛大有巴士 307。

冷笑話(二)

Teddy 又搭乘『大有巴士 307 』正準備由中和上『華中橋』進入台北市,而在大有巴士 307 前方有兩輛 『台北巴士 307』。『車中有時速(表),心中無速限』的大有巴士司機,高喊著『衝,衝,衝』的口號,一下子就超過了前方這兩台『台北巴士 307』。

某候選人:『台北超越台北』。

Teddy:應該是『大有超越台北』吧!

***

友藏內心獨白:這一篇真的是『搞冷無關軟工』。

2010年11月20日 星期六

吵什麼吵,韓國都不韓國了

Nov. 20 14:48~16:05

這幾天最熱門的新聞,除了可能是全國第一個經過法院證認的『招妓男』事件以外,就屬亞運跆拳道『楊淑君』事件。該事件發生之後,媒體掀起一股反韓潮。今天 Teddy 也來趕個流行,談一下 Teddy 對於韓國的看法。

屬於 Teddy 這個世代的人,大多對韓國沒什麼好感。這可能是因為我們還沈迷於 10 幾 20 年前,台灣還是亞洲四小龍之首的那個年代,多多少少有點看不起韓國。再加上這幾年韓國不斷宣稱許多中國人所發明的東西其實是韓國人發明的,甚至連黃帝,孔子,李白,鄭和這些人也都是韓國人,著實讓全世界的華人都看不下去(怎麼不說 Teddy 也是韓國人..XD)。為了表達內心的不滿,Teddy 就是一個儘可能不買韓貨,不看韓劇,也不去韓國旅遊的人(Teddy 內心獨白:好,我承認,我在 Costco 買過韓國烤魷魚,吃過韓國石鍋拌飯與泡菜鍋,有時無聊會不小心看了 30 分鐘的韓劇...etc.)。

但是,一味的仇外並不會讓台灣變好。從很多跡象顯示,韓國的確已經超過我們了。Teddy 舉幾個印象中的例子:
  • 韓劇與韓國藝人在亞洲受歡迎的程度。
  • 韓國可以出口核電技術。
  • 韓國的 DRAM 和面板產業。
  • 桃園機場的空橋,居然是韓國貨。
  • 韓國的遊戲產業。
  • Teddy 去柬埔寨玩的時候時,到處可以看到 LG 的冷氣。
  • 當 Teddy 買的國產液晶電視與 LCD 螢幕用了兩年多就壞掉時,讓 Teddy 有一股想買 LG 或 Samsung 產品的衝動 (日系的又太貴買不起)。
  • 有時候看電視不小心轉到韓國的古裝歷史劇,有的還不錯看。想起本土的『一枝番仔火,一桶汽油』...XD

當然台灣因為老共的關係,害我們無法參與國際事物,在加上政客的有心操弄,大家忙於內耗,新聞的重點都是些『誰愛台灣,誰賣了台灣』,『誰和誰喇舌,誰又去討贍養費』,『誰閃電結婚又疑似先上車後補票』,或是一堆帶著強烈廣告色彩的新聞(哪邊又有好吃的店開幕了,誰打折,那些豪宅正在出售...太多太多了)。

***

以前 Teddy 常聽同事說,『日本人很龜毛』,同事們都很怕接日本人的案子,因為為了一個案子日本人動不動就派 7 - 8 個人來台灣和我們『一個』工程師開會,鉅細靡遺的逐一檢討每一條 issue,有時候從早弄到晚上 1,2 點,隔天一早九點又準時跑來開會。對於具有傳統『差不多先生』良好美德的台灣人而言,當然會不習慣如此嚴謹的做事態度。

Teddy 並沒有和日本人合作的經驗,不過好死不死,一個月前剛好有一個案子和『韓國人』合作,我們需要在短時間內提供一個軟體給對方 。以做軟體來說 Teddy 自認在有限的資源之下,已經盡可能做的很嚴謹了,沒想到就在我們把軟體給對方的兩天之後(包含一份還算詳細的使用手冊),他們回覆了一份很詳細的測試報告,並列出幾點疑問。由對方所回覆的測試報告可以發現這些韓國人做事真的很認真。

插花補充一句:之前這些韓國人還在一份約 200 頁的使用手冊中,找到我們文件的一個 bug,這代表他們真的有先去讀手冊之後才去使用我們的軟體。想一想,如果同樣的工作交到我們身上,聰明的台灣人會怎麼處理?


***

當然,Teddy 潛意識對於韓國貨,韓劇還是抱持著能免則免的心態(如果口袋夠深,誰不想買 Sony....XD),不過,國貨也要爭氣,不然真的很難毫無理由的一直挺下去(總不能用一句台灣人要選台灣人就打通關吧)。話說回來,咱們做軟體的,也要加油啊。很多時候『自我要求』不夠,談什麼方法論(ISO,CMMI 甚至是 agile methods)都是白搭。


***

友藏內心獨白:冤枉啊,大人,Teddy 家裡的 LG 冰箱不是 Teddy 買的...

2010年11月18日 星期四

一萬個小時的練習

Nov. 18 21:24~22:18

曾經有一陣子 Teddy 受人之託,積極的招募學弟們念博速班,但是卻都以失敗收場。分析其原因,可能有以下三點:
  • Teddy 一念就念了 N 年才畢業,學弟們被嚇到了。
  • 念完博士要那麼多年,投資報酬率不高,還不如早點投入職場。
  • 裝孝帷,我都恨不得效法二分之一個秦始皇(焚書不坑儒),還叫我念。
博速班原本就是『有緣人』才可以念滴,強求不來。再說,念那麼多書有什麼好處,為何把人生最精華的 25 - 35 歲這一段時間浪費在學校?

除了那一張薄的幾乎忘了它的存在的畢業證書以外,要如何具體且簡短的說明念博速班的優點,除了『興趣』二字以外,還真是不太容易。Teddy 想起去年天下雜誌的一篇文章『異數,作家葛拉威爾:創意來自一萬個小時的練習』,覺得這個葛拉威爾(Malcolm Gladwell)講得還真他馬...總統..的好

該書的重點,一言以蔽之:『不管哪一種專業,成功最大前提,都需要有一萬個小時的不斷練習。』

假設一個博速生一天工作(上課,讀書,讀 papers,找資料,討論,聽演講,做實驗,寫程式...) 6 小時,一年工作 300 天,那麼:

10000 / 6 / 300 = 5.56  年可以畢業,

如果拼一點,每天工作 10 小時,一年工作 300 天,那麼:

10000 / 10 / 300 = 3.3  年可以畢業 。

其實還滿準的耶。所以 Teddy 可以說,念博速班就是給自己一萬個小時的練習,從素人變成達人的一種訓練。Teddy 當年剛念博速班時,指導教授就說過『念個博速起碼要念個 200 - 400 篇 papers』... 至於書就不用說了,多多益善。

路人甲:現在網路那麼發達,任何問題 google 一下不就有答案了?!

Teddy:講是這樣講,但是實際上同樣的『工具』不同的人來使用,就是有不同的效果。更不用提『速度』因素了。在一萬個小時的練習之後,理解很多事情的能力都變強了,有點類似武俠小說所說得『有了九陽神功護體,學什麼都快』。

除了學東西快這個能力以外,決策的速度與品質也提昇了。做軟體的人都知道,舉凡從變數命名,程式對齊這種『小事』,到專案管理,資源安排,時程預估,需求分析,架構設計,唬爛老闆,找人吵架等等『大事』,都必需要在很短的時間內做出『相對合宜』的決斷,否則便會吃虧。所以,學習與決策,速度與品質的提昇了,這些才是真正寶貴的地方。

當然,這一萬小時的訓練也可在『職場』中進行,早點出社會,早點磨練也是不錯滴。但是要小心,確定自己有『磨練』到,而不是每天腦袋空空的卯起來加班,那就虧大了。

結論:一萬小時減掉你在某個領域已經持續練習的時間,就是你變成達人所需的時數。

***
友藏內心獨白:彷彿聽到某人說...哼,小 case...拎杯玩 game 早就超過一萬小時。

2010年11月17日 星期三

無知便是福

Nov. 17 22:06~22:59

想當年 Teddy 用 VB 3.0 寫的第一個收錢的軟體,從開發到驗收交貨,程式內容都由 Teddy 一手包辦。既沒寫『單元測試』(這是一個 Teddy 當年聽都沒聽過的名詞),也沒經過『第三方驗證』。最後在客戶那邊吃了好幾天的雞腿便當之後,在『有力人士』的安排之下,糊里糊塗就結案了。

結案之後 Teddy 就再也沒有收到對方回報的任何 bugs,哇...靠...北..邊站,難道當年 Teddy 就那麼強,寫出傳說中『零錯誤的程式』?全錯,依據 Teddy 的猜測,應該是 users 根本沒在使用該軟體,所以 Teddy 寫出的是江湖中人稱『零使用的程式』,翻譯白話文,就是四個字『消化預算』。

儘管當年那個軟體可能存在千百個 bugs,但是只要沒人發現,你(客戶)不說,我(開發人員)不講,那世上就沒有第三者會會知道了。YA... Happy...

以上故事就呼應了本篇的主題:『無知便是福』。很遺憾,Teddy 當年沒領悟到一點,反而因為害怕自己太無知,而跑去唸了一堆書,以至於如今自食惡果。什麼惡果?接著看下去...

***

最近 Teddy 參與的一個軟體遇到一個問題,就是某項功能在執行了一段時間(例如 2 - 3 小時)之後會出現異常的行為(不是 memory leak),回傳不正確的值。有經驗的鄉民們看到這邊就猜得到,這種『跑了一段時間才出現的 bugs』是不太好解的。該功能的底層用到了前人所開發的 legacy code,該 legacy code 也存在另一個已經 release 多年的軟體中,如果有問題,應該早就被測試出來,或是有使用者回報錯誤才對啊?!可是並沒有,所以應該不是這些 legacy code 的問題... 如果這樣想,就錯,錯,錯,連三錯。

俗話說得好:『前人種樹,後人乘涼。前人擺爛,後人遭殃』。很『帶賽』的 Teddy 總是遇到後者... 在經過一番測試之後,發現相同的問題也會出現在那一個已經 release 多年的軟體上面。所以啦,前人無知便可以享福,而後人沒事學了什麼軟工測試方法,搬了一堆石頭砸自己的腳,就只好幫忙擦屁股了。

還好 Teddy 每次去家X福買衛生紙都是買量販包,一大袋有24小包的那一種(而且是柔柔軟軟的 X 潔,用多了也不會痛喔),所以在擦完自己的屁股之後,還有多餘的衛生紙可以來擦前人的屁股附帶問候前人的親屬

結論就是:前人內心獨白『我選上算我好運要不然你是想怎樣 我軟體能 release 算我好運要不然你是想怎樣。』

***
友藏內心獨白:程式這麼多寫不完,怎麼辦?那就亂寫嘛...



2010年11月11日 星期四

咫尺天涯

Nov. 11 20:28~21:53

各位 Java programmers 有沒有這樣的疑問:跑在同一台電腦上的不同程式,要如何交換資料?有時候寫程式寫到有一種『咫尺天涯』的感覺,明明程式都跑在同一台電腦中,要交換個資料卻是那麼的不容易。

這個問題就是作業系統所講的 Inter-process communication (IPC),學過作業系統的鄉民們應該都知道 IPC 是一個很重要的機制,借用 Wikipedia 的資料幫鄉民們複習一下功課,以下為幾種常用的 IPC 方法:
  • File
  • Signal     
  • Socket
  • Message queue
  • Pipe
  • Named pipe
  • Semaphore
  • Shared memory
  • Message passing (shared nothing)     
  • Memory-mapped file
問題來了,如果你用 Java 開發一個系統,這個系統有好幾支獨立的主程式,這些程式跑在同一台電腦上的不同 VM 中。這些程式要採用哪一種 IPC 方式來交換資料效率會比較好,程式也容易寫?


先去除 Java 沒有『直接』支援的方法:

  • Signal
  • Message queue (JMS 不算...)
  • Named pipe
  • Semaphore
  • Shared memory (JavaSpaces 不算)

對 Teddy 這個『世代』的 programmers 而言,剩下來的方法中,用 socket 可能是最簡單的。但是用 socket 有兩個壞處:
  • 需要佔用一個 port,如果電腦有裝防火牆的話,可能會被擋住,不然就是增加設定的麻煩。
  • 資料傳輸效率較差。明啊明要交換資料的程式都在同一台電腦上,用 socket 還要把傳輸的資料『打包』與『反打包』,速度自然快不起來。
那用 Memory-mapped file,這速度夠快了吧!ㄟ,雖然 Java NIO 有支援,但是 Teddy 還沒試過如何用這種方法來交換資料,所以... 淘汰。那不然用 File 好了。可是要用檔案來交換資料,還要自己處理『同步』的問題(當同時間有多人想讀寫檔案的時候,必須由應用程式自行定義同步機制,以避免資料錯誤),有點麻煩,程式容易出錯也不好測試。


***

同事甲:那要不要用『資料庫』來交換資料?同步的問題資料庫已經幫我們解決了。


路人甲:裝孝帷,用『資料庫』 overhead 不是更高,要啟動 database server,而且要連到資料庫不也是要建一個 socket,佔用一個 port?

Teddy:Java 有沒有那種類似 Microsoft Access 的資料庫,不需要啟動 database server,可以用『檔案』的方式來開啟資料庫?如果有的話,用『資料庫』來當成 IPC 的方法也許就可行了。

Teddy 找到 H2 這個開放原始碼的資料庫,就具有這種功能。H2 支援三種連線模式:
  • Embedded mode (local connections using JDBC)
  • Server mode (remote connections using JDBC or ODBC over TCP/IP)
  • Mixed mode (local and remote connections at the same time)
其中 embedded mode 不需要啟動 database server,可以直接用以下方式來開啟資料庫。

DriverManager.getConnection("jdbc:h2:data:h2:test", "sa", "sa");

但是問題來了,在 embedded mode 之下,一個資料庫同時間只能被一個 VM (加上 class loader)開啟。H2 會拒絕跑在另一個 VM 的另一支程式用 embedded mode 來開啟同一個資料庫(為了避免資料被搞亂)。

同時間只有一支程式(一個 VM)能夠用 embedded mode 來開啟一個資料庫,那這不就破功了?!還好只要在 connection string 加上 FILE_LOCK=SERIALIZED 就可以允許不同 VM 的程式同時開啟同一個資料庫。

DriverManager.getConnection("jdbc:h2:data:h2:test;FILE_LOCK=SERIALIZED", "sa", "sa");

不過這樣的方便是有代價滴,根據 H2 的文件說明:

This locking mode allows to open multiple connections to the same database. The connections may be opened from multiple processes and from different computers. When writing to the database, access is automatically synchronized internally. Write operations are slower than when using the server mode, and concurrency is relatively poor. The advantage of this mode is that there is no need to start a server.

在 Teddy 的應用中,只有一個 process 會 write,其餘的 processes 絕大部分時間都只會 read,而且同時間大概只會有 2 到 3 processes ,所以 concurrency is relatively poor 也可以接受啦  。當 Teddy 心中正在『暗爽』的時候,居然看到:

This feature is relatively new. When using it for production, please ensure your use case is well tested (if possible with automated test cases).

反正 open source 的東西,用了本來就要自負風險。對於每天工作累到走路必須靠北邊走的鄉民們,能夠少寫一行程式,就少寫一行。所以,用這種方式來達到 IPC 也不失為另一種『聰明』的選擇,至少達到了:
  • 不用建 socket。
  • 應用程式不需要自行設計同步機制。
  • 資料操作方法簡單(SQL)。
  • 速度尚可接受。
最後提醒一點,H2 的 jar 檔需要多站 1.2 MB的空間。 

***

友藏內心獨白:以前寫 VB 程式同時間連 access 資料庫有慘痛的資料損毀經驗,希望這個 H2 能夠『有檔頭』一點。

2010年11月10日 星期三

程式卡卡

Nov. 09 23:19~ Nov. 10 00:06

Teddy 9月20日才說要發憤圖強,結果只持續一個月,從10月21日到現在 Teddy 又偷懶快三個禮拜沒寫部落格了。其實也不是 Teddy 故意要偷懶,應該算是天不從人願,每年年底好像是 Teddy『帶賽』的季節,兩個多禮拜前 Teddy 家裡的 Asus MK241H 螢幕壞掉了,電源完全不亮,前幾天才送回來。數一數 Teddy 今年下半年壞掉的設備:

  • Kyocera FS-1030D 印表機一台
  • 奇美 42吋 TL-42W6000D 液晶電視一部
  • WD 1.5 TB 硬碟一台
  • EN7300GT PCI-E 8X  顯示卡一片
  • Asus MK241H 螢幕一部
好懷念以前那種一台電視機可以看 15-20 年都不會壞的時光。

***

言歸正傳,今天談一個技術問題,這是最近 Teddy 在工作上遭遇到的『靈異現象』。話說因故 Teddy 和同事臨時被要求要寫一隻程式,透過 SNMP (Simple Network Management Protocol ) 去查詢遠端電腦的若干資料。在程式中我們使用了 snmp4j 這個 open source library 。我們的程式在 Windows 上面跑得很正常,速度很快,但是當執行在 Linux 上面時,速度卻異常的慢,感覺在 Linux 上面程式好像等待某個事件,等了很久(疑似等到 timeout)才繼續執行,有點卡卡的感覺(Teddy 內心獨白:女神卡卡,讚;程式卡卡,爛)。

同事甲:Java 不是跨平台嗎?

Teddy:你新人啊!


***

既然 SNMP 有用到『網路』,我們一開始『合理懷疑』是不是有甚麼 routing 的問題,或是在 Linux 上面要去得到 host name 之類的資料但是無法取得(以前有類似的經驗),但是經過一番測試之後發現並不是網路的問題。不過還好,既然 snmp4j 是 open source 的軟體,那就把 source 拿出來 trace 一下應該可以看出一些端倪。

在 snmp4j 中,如果要用 SNMP 傳送資料,必須先產生一個 SNMP 物件。在看了 snmp4j 的 source code 之後, 發現產生一個 SNMP 物件的時候,會:

new snmp () ->  initMessageDispatcher() -> SecurityProtocols.getInstance().addDefaultProtocols()

在這個 addDefaultProtocols() method 中,預設會產生下面這六種編碼方式,

        addAuthenticationProtocol(new AuthMD5());
        addAuthenticationProtocol(new AuthSHA());
       
        /// 下面這幾行是嫌疑犯
        addPrivacyProtocol(new PrivDES());
        addPrivacyProtocol(new PrivAES128());
        addPrivacyProtocol(new PrivAES192());
        addPrivacyProtocol(new PrivAES256());

其中屬於 PrivDES 系列的物件,會產生一個 Salt 物件 singleton, Salt 的 constructor 會執行下列程式:

      SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");    
      sr.nextBytes(rnd);  // 卡在這裡

SecureRandom 是 Java 內建的物件,這一行 sr.nextBytes(rnd) 會呼叫 native code。在 Linux 上面會去讀取 /dev/urandom 這個檔案,以得到一個 byte array。但是 /dev/urandom 檔案的內容被讀走之後,會變空的(或是變少),要再等一段時間才會增加。這裡有一篇文章對於 SecureRandom 的問題有詳細的說明,可以參考。http://lists.agentpp.org/pipermail/snmp4j/2005-January/000273.html

***

那... 要如何解?答案就在... google 中...參考這一篇提到的 work around (http://bugs.sun.com/view_bug.do?bug_id=6521844),在啟動 JVM 時設定 -Djava.security.egd=file:/dev/./urandom  這個參數就 OK 了。或是到 jre/lib/security 目錄修改 java.security 這個檔案,把 securerandom.source=file:/dev/urandom 改成 securerandom.source=file:/dev/./urandom 也行。

雖然問題暫時解決了,但是 Teddy 還是不知道 /dev/urandom 和 /dev/./urandom 有什麼不一樣?算了,先混過去再說,又不是要出 paper...XD

 ***

友藏內心獨白:有 Google 固然好,下對 keywords 才是真本事。