Thursday, November 04, 2004

我是苦命 patcher

我是苦命 patcher,我想來說說 VSS 的壞話。

在我進公司之前,老闆選了 Microsoft Visual SourceSafe (VSS) 作為部門的 version control system。這,是苦命的開始。理論上,使用 version control system,可以幫助程式員們,彼此協同開發。我以前就有過這樣子的經驗,和學弟兩人,使用 CVS 一起開發一套社群軟體。兩人卯足了勁拼命 commit,彼此分工合作,絲毫不會有程式互相「蓋到」的情況發生。可是,現在在公司上班,與同事協同開發的感覺,完全變了一個樣。在我們部門裡, VSS 根本就只是被當作一個 source deposit,而沒有發揮 source control 應該要有的功能。

在我們部門裡,典型的協同開發的流程,就如同下面這個故事一般:

  1. A 君寫了一套軟體的初版,程式已經可以動作,初版的功能皆已齊備了,然後他趕緊在 VSS 裡建一個專案,或是找一個相對應的位置,把程式放進去。
  2. 然 後,老闆找了 B 君來做一個新功能,於是 B 君就找 A 君要程式,A 君說,放在 VSS 裡,於是 B 君就回去自己的電腦前,想要把程式 checkout 出來,卻發現他沒有權限。於是,B 君再回去找 A 君,然後 A 君就打開他的 VSS,加了 B 君的帳號。就在 B 君要回自己位子上去工作前,A 君拉住了 B 君,對 B 君說:「你不要亂 commit 喔,程式寫好了之後,拿給我看看,沒問題再 commit。」
  3. 於是,B 君便辛勤地與新功能奮鬥。其間,歷經了若干次因當機或其他不明原因,系統 crash,導致程式流失。還好,B 君平時有做備份的習慣,因此在 B 君的電腦裡,最後一共存了十幾份程式的備份檔,其中有約 1/4,因為在備份的時候,忘了標註日期時間,最後變成了讓人根本搞不清楚到底內含了什麼東西的一沱廢物。
  4. 由 於新功能的解法未定,在開發過程中,為了嘗試各種解 法,B 君的電腦裡的程式目錄,又分成了好幾個不同的目錄,好比 FooProj-Method1、FooProj-Method1+Method2、FooProj-Solution7、FooProj- Method1+Method3、FooProj-Mess、FooProj-HalfSolved 等等讓人有點明瞭又有點模糊的奇怪目錄名。
  5. 另 外,B 君覺得,有些程式可以抽離出來,成為一個 utility library,好比對檔名的分析與處理等。因此,B 君便將這些程式抽離出來,另外做成了一個 library。然後在原本的程式裡,呼叫這個 library。當然,這個 library,又是放在另外一個目錄裡。
  6. 很不幸地,可以被抽離出來的程式,其種類越來越多,於是這個 utility library 就越來越龐大。更麻煩的是,這個 utility library 裡,有些功能種類已經寫完了,有些功能種類還沒有寫完,另外還有些功能種類,B 君一改再改,卻仍是還沒有改出覺得可以滿意的版本。也因此,FooProj-Method1 目錄的程式,必須搭配 UtilLib-Initial 目錄下的 utility library,然後 FooProj-Method1+Method2 目錄必須搭配 UtilLib-StrOK 目錄,FooProj-Solution7 目錄必須搭配 UtilLib-StrOK+SQLTemp 目錄,而 FooProj-Method1+Method3 所對應的 utility library 的目錄,已於上次當機而遺失了,FooProj-Mess 搭配 UtilLib-Good1、FooProj-HalfSolved 搭配 UtilLib-Good1+I18nTemp+SQLBad。老實說,連 B 君都快搞不清楚這些目錄彼此之間,錯綜複雜的關係了。
  7. 總 算,B 君改出了一個可以跑的版本了,於是 B 君將 FooProj-OK1 與 UtilLib-Good2 包成兩個 zip 檔,寄給 A 君,然後來到 A 君的電腦前,與 A 君討論。A 君打開信件,把 FooProj-OK1 裡的所有 .cpp 檔,全部 copy 到自己專案目錄下的 src/ 目錄下,然後 compile 程式,瞬間指著上千個 error message 對 B 君發飆。B 君只好很委屈地對 A 君解釋說,還需要加上 UtilLib-Good2 才行。於是 A 君與 B 君,手忙腳亂地花了好一陣子,才順利地把 UtilLib-Good2 裝進 A 君的電腦裡,並把相關設定都設好。此時,B 君的程式,才能正確地在 A 君的電腦上跑。
  8. 看 完程式之後,A 君對 B 君的程式,尚稱滿意。不過,因為 B 君的程式,是用 C++ 寫的,A 君對 C++ 並不怎麼熟悉,再加上,A 君不太願意,在他偶爾還會改進的這套程式裡,加上 UtilLib-Good2 這個拖油瓶,因此,A 君對 B 君說:「嗯,不錯,不過你還是先不要 commit 好了,等這個新功能穩定之後,我們再來弄個最終版本。喔,對,這幾天我又稍微改了一下程式,現在程式應該會快了一些,你看是不是要把新的程式 merge 一下。」由於 A 君較為資深,因此 B 君便無異議地答應了。
  9. 回到自己的電腦前,B 君開始手動 merge 兩份程式。很快地,B 君發現,光用 diff 找出相異處,根本不可行,因為兩人的程式排版風格差異太多了。好比,A 君習慣用 i++,而 B 君則習慣用 ++i;A 君習慣用 if (p) s();,B 君習慣用 if (p) { s(); }。類似這種不算差異的差異,不勝枚舉,B 君改的煩不勝煩,幾乎每一個 diff 回報的差異,都必須用人眼仔細檢視,才能確定該怎麼修改。這次 merge,B 君花了三天才完成,因為第一次 merge 完之後,發現程式跑了會當,而又找不出到底是哪裡漏了,所以 B 君只好又再重新 merge 了一次。
  10. 這樣的故事,週而復始,不斷地發生……

當然,上面的故事,點出了許多的問題。不過做人處事嘛,最好還是對事不對人。因此,咱們來罵罵 VSS 吧。

Alan De Smet 的「Visual SourceSafe: Microsoft's Source Destruction System」這篇文章裡,整理出了許多 VSS 的邪惡之處。另外,Alan De Smet 也介紹了這一篇「Visual SourceSafe Version Control: Unsafe at any Speed?」,不過這篇的排版比較差,看起來很辛苦,所以我就懶得看了。以上當然不是事情的全部,以下,則是我的抱怨:

夜了,剛總算把 2/3 的專案給人工 merge 完畢,剩下一個全域變數不曉得跑到那個檔案去了。我是苦命 patcher,我覺得我比 VSS 還要厲害。-.-||


[Thunderbird]怎樣知道IMAP Server上的信件夾,有哪些有新信?

個人習慣自己架 IMAP Server,透過 fetchmail + procmail + spamassassin 來收信、分信以及擋信。把信全放在 IMAP Server 有一個好處是,到哪裡都可以灌個 MUA 來看信,至不濟還可以用 webmail 遷就一下。

可是,由於信件已經在 server 上事先用 procmail 自動分到不同的信件夾去了,因此,我在看信的時候,便需要知道,哪一個信件夾有新信件。由於會被自動分信的,多半是屬於電子報或郵遞論壇類型的信件,不需 急著看其內容,僅需依據標題,再來決定是否需要花費時間下載觀看。另外,廣告信也是一種其實並不需要下載的信種,不過為了避免誤判,所以還是需要稍微瀏覽 一下標題,因此也屬於這類僅需要下載標題的信種。

在 Outlook Express 裡面就有這樣子的一個功能,可以對每一個 IMAP 信件夾,分別指定其下載的方式,可以為不下載、只下載信頭,以及全部下載等三種方式。透過將有可能會有新信的信件夾,設定成只下載信頭,其他的信件夾,設 定成不下載,然後 INBOX 設定成全部下載,我便可以達到我所希望的效果,在 INBOX 裡的信件,多是確定要看得信件,已經下載完畢直接可以閱讀,而其他的信件夾裡,則是新的電子報或郵遞論壇信件,等我去決定是否要觀看,歸類用的信件夾,則根本不需要下載。

然而,Thunderbird 似乎並無法達到這樣「細緻」的功能。請問有任何網友有類似的經驗與需求,或知道有任何的 extensions 或 extensions 的組合,甚至搭配 server-side 設定的辦法,可以達到我上述的需求嗎?懇請賜教。

--
我的微笑,堅持要有鼻子。:-)


有關此問題的討論:Mozilla@Taiwan


This page is powered by Blogger. Isn't yours?

Subscribe to Comments [Atom]