2009年4月28日 星期二

關西行:廁所大賞

從日本玩回來都快過一年了遊記還沒完成,還是直接寫最有興趣的這篇,剩下的就隨意吧。

說到旅遊方面的事,我可能沒什麼特別自信,但去一個旅遊景點先找廁所這件事,我可是很在行呢!這回去關西特別搜集了多所精美廁所外觀,在這裡和大家分享一下。為什麼沒拍廁所內部呢?一來是內部沒差太多,都是現代化設施;二來是我不想在一個人旅遊時以妨礙風化的罪行被逮補。這次的特集裡,最可惜的是沒拍到清水舞台下面的廁所,那間可說是此行中的冠亞軍之選,但人潮太多,我在那等了十多分鐘都抓不到拍照的時機。

廢話不多說,首先是金閣寺的廁所:

所照片所示,以金閣寺的名聲來說,未免太普通了點,失敗失敗。

上面這張是龍安寺石庭旁的廁所,也是相當普通。再來這張就有點意思了:

仁和寺的廁所看來比較有點格調,為了怕我自己認不出來是廁所,故意選照得到水管的角度。以在關西的第一天來說,就仁和寺的廁所有在水準之內。希望這些水準低下的廁所外觀沒有掃了大家逛大阪的興致,比較正常的風景照和介紹請參見《關西行:抵達京都、前往洛西》

再來這張是風俗博物館內部的廁所,由於該館很小,外觀...就是一扇門,只好改拍內部意思意思,可以看到中間還放了幾個小裝飾。喜歡源氏物語的人可以去看看,詳見之前寫的《關西行:京都洛中》

再貼這類照片下去,相信大家很想關網頁了,只好提前先拿出最有冠軍相的平等院廁所!

是不是看起來相當雅緻呢?而我個人相當中意的伏見稻荷大社,相當地可惜,山中的還算上得了檯面,可是在人潮多的神社旁邊,卻是相當現代化的外觀,真是太不專業了。


( 神社外的廁所 )


( 山中的廁所,拍這張花了我一點時間,雖然在山中,人潮也不算少 )

關於上兩間廁所之外的正常介紹,請見舊文《關西行:京都洛南》

下面這兩張是二条城的廁所,馬馬虎虎,將就將就啦,護城河和城牆這麼美,為什麼廁所卻沒那種霸氣呢?

而下面這張現代化的廁所,竟然位在清水寺,裝個屋瓦並不會改變現代化外觀的事實,真是太令人失望了。所幸在清水寺下面的廁所相當雅緻,為清水寺扳回一些面子。只可惜人潮過多我沒能照成,可說是本次旅遊的一大憾事。

這部份的相關介紹,請見《關西行:京都洛中二条城及洛東清水寺》

最後這張是大阪城公園的廁所,外觀看來頗為氣派,但如同水柱邊泛黃的痕跡所示,廁所內部實在太髒啦!

就這樣,本次的廁所大賞到一段落,感謝各位帶著被玷污的眼睛耐心看完。不知大家心目中關西最漂亮的廁所是那間呢?

最後的最後,我不得不說,TD-Post真是好用啊!

2009年4月25日 星期六

寫 Blog 好幫手 TD-Post!

為了方便寫 Blog,寫了個小程式讀 wiki code 產生 WordPress 吃的格式,順便藉機練習 TDD,沒想到寫了十小時才完成。剛好最近在看虎x龍的動畫,就將它命名為TD-Post (Tiger x Dragon Post) 吧。

緣起

換過多家 WordPress 用的編輯器後,我還是找不到滿意的工具。為縮短寫 Blog 的時間,我決定自己做一個。

寫 Blog 最惱人的事有幾點:

  1. 得輸入麻煩的 HTML,特別是要匹配結束標籤特別麻煩。而且 HTML code 不易閱讀,改文章時很不方便。
  2. 加超鏈結很麻煩,常用的幾個超鏈結,得重附貼多次,像 TDD 我就重貼了許多次。
  3. 無法用自己慣用的編輯器。若能用 Vim 寫 Blog,速度必能大增啊!

功能簡介

對我來說,寫 wiki code 相當方便,所以輸入格式決定用 wiki code。但 wiki 格式有許多種,我比較常用的有 PmWikiDokuWikiTWiki,其中以 PmWiki 語法最簡單,但原始碼沒後兩者好讀。最後聽從 York 的建議,採用 Tracwiki 格式。選它的主要原因除好讀好寫外,我特別喜歡它 Preformatted Text 的格式,很適合用來貼程式碼。

接著,針對第二點問題,加上自動補超鏈結的功能,只要寫過一次超鏈結,TD-Post 就會自動記下來,自動補上對應的位置。像在這段裡,因為我在第一段已寫過 TD-Post 的位置, TD-Post 的超鏈結都會自動補上。初步估計,以後寫一篇 Blog 至少可以省十分鐘,所以差不多用個六十次...這幾天的辛勞就.就回本啦。

程式下載

本程式採 BSD License ( 簡單說就是隨便使用 ),歡迎大家玩玩。雖然沒什麼註解,但我照 TDD 流程寫的,測試碼應該很完整。這裡是一些相關資訊:

  • 下載:http://code.google.com/p/td-post/downloads/list
  • 程式語言:Python
  • 程式碼總行數:682 行
  • 測式碼:346 行 ( 主要是準備測試的例子 )
  • 非測試碼:336 行
  • 實作時間:原本預估兩小時完成,卻花了約十小時。大概是一小時查語法、一到兩小時寫測試。其中花最多的時間在解決 list 和 performatted text 的衝突,這部份從開始實作到結束花了三小時才解決。

其它

有原始碼有真相,最後附上本文的原始碼:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
為了方便寫 Blog,寫了個小程式讀 wiki code 產生 [http://wordpress.org/ WordPress] 吃的格式,順便藉機練習 [http://en.wikipedia.org/wiki/Test-driven_development TDD],沒想到寫了十小時才完成。剛好最近在看[http://zh.wikipedia.org/wiki/虎與龍_(小說) 虎x龍]的動畫,就將它命名為[http://code.google.com/p/td-post/ TD-Post] (Tiger x Dragon Post) 吧。
 
==== 緣起 ====
換過多家 [WordPress] 用的編輯器後,我還是找不到滿意的工具。為縮短寫 Blog 的時間,我決定自己做一個。
 
寫 Blog 最惱人的事有幾點:
 1. 得輸入麻煩的 HTML,特別是要匹配結束標籤特別麻煩。而且 HTML code 不易閱讀,改文章時很不方便。
 1. 加超鏈結很麻煩,常用的幾個超鏈結,得重附貼多次,像 [TDD] 我就重貼了許多次。
 1. 無法用自己慣用的編輯器。若能用 [http://www.vim.org/ Vim] 寫 Blog,速度必能大增啊!
 
==== 功能簡介 ====
對我來說,寫 wiki code 相當方便,所以輸入格式決定用 wiki code。但 wiki 格式有許多種,我比較常用的有 [http://www.pmwiki.org/ PmWiki]、[http://www.dokuwiki.org/ DokuWiki]、[http://twiki.org/ TWiki],其中以 [PmWiki] 語法最簡單,但原始碼沒後兩者好讀。最後聽從 York 的建議,採用 [http://trac.edgewall.org/ Trac] 的 [http://trac.edgewall.org/wiki/WikiFormatting wiki 格式]。選它的主要原因除好讀好寫外,我特別喜歡它 Preformatted Text 的格式,很適合用來貼程式碼。
 
接著,針對第二點問題,加上自動補超鏈結的功能,只要寫過一次超鏈結,[TD-Post] 就會自動記下來,自動補上對應的位置。像在這段裡,因為我在第一段已寫過 [TD-Post] 的位置, [TD-Post] 的超鏈結都會自動補上。初步估計,以後寫一篇 Blog 至少可以省十分鐘,所以差不多用個六十次...這幾天的辛勞就.就回本啦。
 
==== 程式下載 ====
本程式採 [http://zh.wikipedia.org/w/index.php?title=BSD许可证&variant=zh-tw BSD License] ( 簡單說就是隨便使用 ),歡迎大家玩玩。雖然沒什麼註解,但我照 [TDD] 流程寫的,測試碼應該很完整。這裡是一些相關資訊:
 * 下載:http://code.google.com/p/td-post/downloads/list
 * 程式語言:[http://www.python.org/ Python]
 * 程式碼總行數:682 行
 * 測式碼:346 行 ( 主要是準備測試的例子 )
 * 非測試碼:336 行
 * 實作時間:原本預估兩小時完成,卻花了約十小時。大概是一小時查語法、一到兩小時寫測試。其中花最多的時間在解決 list 和 performatted text 的衝突,這部份從開始實作到結束花了三小時才解決。
 
==== 其它 ====
 
有原始碼有真相,最後附上本文的原始碼:{{{
#!html
_QUINE_
}}}
 
身為資工人,這段原始碼當然也是自動貼上的啦,不過我沒用像 [http://en.wikipedia.org/wiki/Quine_(computing) Quine] 那樣的技巧,只是單純地取代關鍵字。

身為資工人,這段原始碼當然也是自動貼上的啦,不過我沒用像 Quine 那樣的技巧,只是單純地取代關鍵字。

2009年4月22日 星期三

中翻英,線上翻譯測試 - Google Strikes Back!

( 這篇寫於 2008-10-26,不知為啥從 Blog 裡消失了,所幸 Google Reader 裡有備份。 )

剛才無聊看看 Google Analytics ,發現本站最熱門的文章還是那篇《中翻英,線上翻譯測試》,我不知該說什麼,這不是件令人高興的事啊。總之,一時興起又來測看看。

最近 Google 翻譯似乎變強了,果然有在學習啊!輸入問題如下:

我要代替月亮來懲罰你

兩年前 Google 的回報令我很失望:

I want to punish you replace Moon

沒想到現在 Google 幾乎翻對了!

I want to punish you in place of the moon

google 一下會發現有不少人提到類似的句子,附帶一提,個人心目中最完美的翻譯是:

In the name of the moon, I will punish you!

其它家翻譯結果沒什麼變,就不再貼了。

另外再測了之前亂測的中文詩詞,有些變化,不過說不上是變好變壞,都很糟就是了。看來博大精測的中文仍是機器翻譯無法跨越的高牆,也是國高中生們無法跨越的牆啦。

強化 Python 在 Vim 裡的顏色

我習慣用 putty 連 Unix server 開 screen,再用 vim 寫 Python。這篇記錄如何改善 Python 的顏色。

啟動 256 色 terminal

首先將可用的色彩數增加為 256 色,先確定 putty 為新版 ( 舊版 putty 沒支援 256 色)。接著參照《讓 Vim、Screen 支援 256 色》將 Screen 和 Vim 設好,記得先用文末提到的 Colortest 測試是否有符合 256 色,成功的話,數字 0 ~ 15 為原本的 16 色,16 ~ 231 為新的顏色 (6 x 6 x 6),232 ~ 255 為新的灰階色。可配合 Colortest 看到數字值和顏色。

這裡備忘該篇提到的步驟:

  • 在 ~/.vimrc 加入:
    1
    
    set t_Co=256
  • 在 ~/.screenrc 加入:
    1
    
    termcapinfo xterm 'Co#256:AB=\E[48;5;%dm:AF=\E[38;5;%dm'

更新 Python script 偵測的格式

更新 syntax/python.vim,讓 Vim 偵測出更多種格式,像是行末多的空白,或是空白行有含空格都會被偵測出來。做法如下:

  1. 下載最新的 python.vim 並放到 ~/.vim/syntax/ 下。
  2. 編輯 ~/.vimrc,加入
    1
    
    let python_highlight_all = 1

    以顯示所有 python.vim 有偵測的格式。參照 python.vim 開頭的註解,了解細部選項。

替換顯示的顏色

  1. 下載 Vim color scheme: Wombat256.vim,並放到 ~/.vim/colors/ 下。
  2. 在 ~/.vimrc 裡加入
    1
    
    colorscheme wombat256

如此一來就有漂亮的顏色啦,wombat256 的 screenshot 見這裡

備註

這個網站有提供許多不同的 color scheme screenshot,可惜沒附 Python 的 screenshot。

2009年4月19日 星期日

最近用 Python + TDD 心得(與 Java 做對照)

最近又用 Python 寫了些程式,剛好和之前用 Java 進行 TDD 做個對照。

若不知道 TDD 的人,可以先參考這篇,TDD 的概念是依以下三個步驟寫程式 ( 順序相當重要 ):

  1. 先寫簡單的單元測試,並執行它。
  2. 用最簡單的方法實作需要的功能,讓程式能通過測試。
  3. 重構程式,並確保重構後的程式仍能通過測試。

實作部份不需多談,這裡先分別對步驟一「寫測試碼」和步驟三「重構」討論,再分享一般性的一點心得。

寫測試碼

Python 寫起測試碼比 Java 簡單許多,可以輕易地抽換所有既有物件,如 module、function、class、method。下面是一個簡單的抽換 method 的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class MyClass(object):
    def hello(self, msg):
        print msg
 
def new_hello(self, msg):
    print msg + " (by replaced method)"
 
obj = MyClass()
obj.hello('Testing rocks!')  # Testing rocks!
mystub = stub.Stub()
mystub.replace(MyClass, 'hello', new_hello)
obj.hello('Testing rocks!')  # Testing rocks! (by replaced method)
mystub.restore(MyClass, 'hello')
obj.hello('Testing rocks!')  # Testing rocks!

註解表示該行輸出結果,其中 Stub 是我寫得一個簡單 class,只有十行多,可以替換和還原物件。可以從 MyClass.hello() 的輸出看出,stub.replace() 後 MyClass.hello() 被換為 new_hello(),stub.restore() 後則換了回來。完整的程式碼請看這裡

方便抽換物件有什麼好處呢?舉例來說,若 class A 有兩個 method B 和 C,其中 B 用到 C ( B 會視 C 傳回結果改變程式流程 )。為了方便測試 B 的行為,得先控制 C 的傳回結果。若是 Python 的話,照上面的例子透過 Stub ( setattr() ) 替換 A.C 即可。但在 Java 的情況,除非將 C 當作參數傳給 B,讓測試程式有機會傳「假的 C 」給 B,不然難以控制 B 內部行為。寫新程式時還有機會改設計,對於舊的程式,修改程式是個災難。用到別人的函式庫或沒程式碼就無解了。不論 Java 有何解法 ( 如採用 injection 的方式 ),解法愈麻煩,表示大眾愈不願意做,因此降低測試碼的品質,連帶影響 TDD 效果。

Mock library 部份,Java 有 EasyMock,Python 有 Mox,兩者用法差不多。後者是前者改來的,學一套兩邊都可以用。

重構

由於 Java 的特性 ( static type ),重構工具相當成熟,我慣用 Eclipse 的重構功能,離開它就不太想寫 Java。其中我最常用的功能是改名稱,包含 variable、method 、 class、 package 等。好的名稱是好程式碼的必要條件之一,好的名稱可以省去冗長的註解、縮短理解程式的時間,同時也有助於作者釐清邏輯,減少犯錯的機會。若發現名稱很難取,也許表示該 object(method / class / package)功能沒規範好,之後容易遇到問題。寫程式難免會犯錯,寫一段時間後才發現命名不夠精確,得回頭修改。若有好的重構工具,改起來快又沒風險,可以提高重構的意願。

反觀 Python 因為 dynamic type,程式碼本身提供的訊息不足(得執行後才清楚全貌),難以透過工具重構。我找了一下相關工具後沒看到滿意的。Eclipse 的 PyDev plugin 有提供重構,但試用後結果是錯的,改 module 名稱時沒動到檔名,執行後才會發現程式碼爛了。另外試了 Rope ,可以正確改名,可是速度有點慢,操作相當不直覺 ( 之後再來試看看 ropevim )。為了長遠發展考量,或許可以試看看自己弄個簡單版的改名工具或改 Rope,工具的功能可以少,但要快、容易操作且結果正確。

結語

只有在三個步驟都確實做到時,TDD 才能發揮應有的威力。依我目前一點點的實作心得,Python 容易寫測試碼、卻不方便重構;而 Java 正好相反。現在我大多有照 TDD 的流程寫程式,即使寫個一小時的小程式,也會用 TDD 。有時寫寫覺得卡卡的,才發現忘了先寫測試碼。

另外,測試碼的範圍抓得準 ( 別測太細,也別懶得測核心) ,效果才會好。我初用 TDD + Python 時就矯枉過正,寫太多測試變成 「over-testing」,省了 over-design 的負擔,卻多花時間寫不必要的測試碼、又增加日後維護的成本 。

養成 TDD 習慣的關鍵,在於寫測試碼的功力,像是如何準備 fixture ,如何改善函式介面以利測試。為了寫測試而改變函式介面並不是本末倒置,通常這會降低函式之間的關聯性,將功能明確切開,讓每個函式的輸入輸出都很乾淨(有簡單的輸入,才方便準備 fixture)。而乾淨的輸入輸出意味著函式更容易被組合使用。