#!/usr/bin/perl
# $File: //member/autrijus/Lingua-ZH-Keywords/t/2-utf8.t $ $Author: autrijus $
# $Revision: #3 $ $Change: 3703 $ $DateTime: 2003/01/20 15:02:12 $

use strict;
use Test;

BEGIN {
    eval { require Encode::compat } if $] < 5.007;
    eval { require Encode } or do {
	plan tests => 0;
	exit;
    };
    plan tests => 2;
}

require Lingua::ZH::Keywords;
ok($Lingua::ZH::Keywords::VERSION) if $Lingua::ZH::Keywords::VERSION or 1;

use utf8;
my $data = do { local $/; <DATA> };
Encode::_utf8_on($data);

ok(
    join(',', Lingua::ZH::Keywords::keywords($data, 10)),
    '站台,模組,映射,語言,系統,軟體,程式,作者,典藏,自己'
);

__DATA__

綜合典藏網的禪道

為其他電腦語言建立像 Perl 的 CPAN [1] 這種典藏網，似乎是件熱門的主題。我該知道
的；幾年來，至少有 Python、Ruby 及 Java 社群的人，找上我或其他 CPAN 的核心人物
，詢問「我們怎麼辦到的？」這種問題。最近，我發現 Perl 社群裡更有些人，想要主動
對其他社群提供支援。我在這封「公開信」裡試著說明自己的想法，協助想自行架設 CAN
（綜合典藏網）的朋友。因為這封訊息會傳到其他社群手上，我附上了 Perl 社群（希望
是）早已熟知的各項網址。我接下來敘述的是對 Perl 有效的措施，請自行翻譯成適合其
他語言的辦法。

        [1] http://www.cpan.org/

我會以負面口吻開始，再以較為正面的敘述作結；不過，後者是建築在前面的否定上的。

底下，Mumble 及 mumble 代表 Perl 之外的某種其他語言，或是某些其他語言的統稱。

首先，來看看負面的陳述：

 • CPAN 不該「搭載」他種語言。（換句話說，裡面不該有 mumble/ 這個頂級目錄。）
     □ 理由：CPAN 就是 CPAN 就是 CPAN。CPAN 祗裝 Perl。這句話蘊含了各種明示及
        暗示的協議。
     □ 有些 Mumble 社群裡的人，會反對 CPAN 搭載 Mumble。
     □ 有些 Perl 社群裡的人，會反對 CPAN 搭載 Mumble。
     □ 某些 CPAN 的映射站台，會反對突然還得搭載 Mumble。
     □ 某些 CPAN 的映射站台，會因為搭載 Mumble 而導致資源（頻寬、磁碟）不足。
 • CPAN 沒辦法「搭載」他種語言。
     □ CPAN 的基礎建設、內部管線（基本的目錄結構、PAUSE）相當適合 Perl。我不太
        確定它適合其他各種語言。

接下來，是希望比較具建設性的建議：

首先要說的是－－我不反對其他語言有自己的 CPAN，並且會十分高興。我也願意協助其他
語言的社群。我反對的，祗是太過簡化的「把它丟到 CPAN 旁邊就行了」這種解法。其他
語言跟 Perl 不同，各自有或多或少的差異。讓我們容許這些語言有各自的尊嚴，以及深
思熟慮過的解決方案吧。

接著要回答的是技術問題，也就是「你們怎麼辦到的？」。嗯，有人這樣問的時候，我通
常是啞口無言：「呃... 唔，我就是把這些東西收集起來，整理一下，然後丟到一台 FTP
伺服器上。」之後過了一會，總是有人開口：「然後呢？」「什麼然後？」「就這樣？」
「就這樣。」

CPAN 的組成元件

當然，不祗是這樣而已。上面說的是 CPAN 的誕生。它的成長則是另一個故事：首先，
Larry 將 Perl 設計成具有模組（也就是命名空間）的擴充功能。接下來，有幾位智者（
如 Tim Bunce）規劃了命名方式的良好規範。最後，Andreas Koenig 獨力撰寫了 PAUSE
[2]，提供上載模組的機制，讓 Perl 模組的作者能註冊、送出、管理自己的作品。這導致
了迅速而有秩序的成長。

        [2] http://pause.perl.org/
        （或是 https://pause.perl.org/）

安裝模組並不容易，尤其是需要橋接 C 語言或外部程式庫時。為此，Andreas 和一些朋友
合力寫成了前端與後端兩份程式：前端名為 CPAN (shell) [3]，後端則是 MakeMaker [4]
。Shell（又稱為 CPAN.pm）負責下載元件；後端則建立所需的 Makefile（或類似的建置
工具控制檔），並呼叫相應的建置工具。

        [3] http://search.cpan.org/search?module=CPAN
        [4] http://search.cpan.org/search?module=ExtUtils::MakeMaker

    不幸的是，將安裝模組用的 Shell 與典藏網取同一個名稱，導致了不少的混亂：當有
    人說「CPAN 現在爛掉了」這句話時，便無法判斷他說的是 Shell 裡的瑕疵、他常用
    的映射站台斷線，還是在反對 CPAN 設計上的某些細節。

    另一種很常見的混淆，是以為 CPAN「祗等於」PAUSE，也就是經由 PAUSE 上傳的模組
    集合。這雖然不算錯（CPAN 的絕大多數內容，確實是從 PAUSE 來的），但也不是全
    對。首先，CPAN 確實有 PAUSE 之外的來源：CPAN 合併了一些小網站，而且某些檔案
    （例如冷門平台上的 Perl 二進制釋出套件）仍然是手動取得（因為它們更新得慢）
    。此外，還有 ports 網頁，列出 Perl 的二進制釋出套件；其中有些放在 CPAN，有
    些則連結到其他地方。

對（半）自動化的安裝工具來說，最重要的就是簡易取得依存資訊的功能。簡單的文件產
生流程，能降低線上瀏覽文件的難度，讓使用者能更容易決定是否要取用某個模組，並且
將它用得更好。

由於 CPAN Shell 日漸老邁，並且缺乏良好的應用程式介面，因此有了 CPANPLUS [5] 這
個新的計劃。理想情況下，它應該能直接取代 CPAN Shell 這位老忠僕，又能提供更高的
彈性與延展性。同樣的，也有個取代 MakeMaker 的計劃，叫作 Module::Build [6]。

        [5] http://search.cpan.org/search?module=CPANPLUS
        [6] http://search.cpan.org/search?module=Module::Build

要注意的是，雖然每個 Perl 釋出套件裡都附上 CPAN.pm 及 MakeMaker，仍然可以利用其
他工具來安裝模組：ActiveState 自己有一套針對 ActivePerl 設計的 ppm（
Programmer's package manager，原名 Perl package manager）。

隨著 CPAN 的快速成長，要找到想要的東西愈來愈費力。幸好，Graham Barr 自己解決這
個問題的成果，及時以 search.cpan.org [7] 的名稱公諸於世。此外還有別的 CPAN 搜尋
引擎，像是 Randy Kobes 的搜尋器 [8] 以及 WAIT [9]；不過，search.cpan.org 似乎是
最熱門的一個。

        [7] http://search.cpan.org/
        [8] http://kobesearch.cpan.org/
        [9] http://wait.cpan.org/

稍後，Andreas 加入了 backPAN [10]，用來存放作者刪除的舊版模組；這呼應了核心伺服
器的必備要件之一，也就是良好的備份。

        [10] http://history.perl.org/backpan/

cpan-testers 是個郵遞論壇（由 Graham Barr 及 Chris Nandor 創設），其中的訂戶自
行下載最新的模組，嘗試執行其中的測試程序，再將成功與否回報到郵遞論壇上、載入資
料庫，並回報給原作者。這對增進模組的跨平台、跨環境性能，提供了重要的協助。還要
注意的一點，是模組附上測試程式的必要－－不然，怎麼知道它到底能不能運作呢？

        [11] http://testers.cpan.org/

最後，對模組的使用回饋（瑕疵回報、功能建議、感謝函等等）可以經由 Jesse Vincent
架設的 RT 申請單處理系統 [12] 來反映給作者。

        [12] http://rt.cpan.org/

映射站台

CPAN 映射站台 [13] 呢？它們是怎麼出現的？一開始的十幾個說來容易：我祗不過是寫信
詢問提供 CPAN 原始資料的各站台，是否願意搭載這個稍大些的彙整而已。嗯，他們傻呼
呼地答應了... 我必須再重申一次，CPAN 原本是個 FTP 典藏站。不是網站。它到今天仍
然如此；search.cpan.org 祗是個好看的介面而已。十分抱歉，但我是個乏味的資訊工程
師，不是美術設計師。重要的是資訊，而不是動畫。

        [13] http://mirrors.cpan.org/

噢，回來講 CPAN 映射站台。在起初的幾個之後，我們靠 Perl 社群的口耳相傳，慢慢成
長了一陣子。然而，因為那時候還沒有價值上億元的光纖舖進地底，所以網路連線仍然不
太穩定。因此，我開始做兩件事情：檢查 FTP 紀錄，找出顯然在映射 CPAN 卻沒有註冊的
站台，以及能代表所屬頂層網域的站台（特別是七大 TLD 之外的網域）。這樣一來，我就
能找到 Perl 使用者的所在地點，並請求這些站台加入映射，減低主站台的流量負荷。之
後，我造訪了 sunsites 等廠商或公家支援的大站，填滿了幾個空缺的國家。我通常總能
連絡上對方的系統管理員，得到善解人意的回應。

CPAN 映射站台的狀態每天更新四次，由位於不同大陸的兩台機器負責監視。過期的映射站
台幾乎等於無用，有時更可能造成危險。隨著映射站台數的增加，一次掃瞄往往不能確認
全部的軑況：總是會有網路或伺服器的問題，讓某幾站的連線失敗。除非各站自己執行檢
查，否則想確認所有站台上每個檔案的內容，簡直是天方夜譚。CPAN 仰賴一個簡單的小技
巧：CPAN 主站每小時上載一個特殊的檔案，裡面放時間戳記（以國際標準時表示）。祗要
從映射站台下載這個檔案、解出時間戳記，就可以輕易得出上次更新的時間。

關於映射站台這段話的總結：我找的是喜愛或使用 Perl 的站台。我無法確認他們是否也
愛用 Mumble。映射站台捐出了他們的頻寬、儲存空間以及管理員的時間，提供 Perl 社群
使用。如果我們要擴增其中的任何一項，都得先取得各站台的同意纔行。

CPAN 組成元件圖

要進一步暸解 CPAN 的歷史，請參考 Perl 大事紀 [14]。事情不是一天造成的。

        [14] http://history.perl.org/PerlTimeline.html

命名

良好的模組命名方式，對作者和使用者都很重要。Perl 與 CPAN 的命名方式雖然差強人意
，但至少是精心設計、再依需求演化過後的產物。恰當的命名方式，不但能呈現階層式的
瀏覽介面，也可以提供良好的提示給搜尋引擎使用（恰當的模組名稱，實際上就是一組獨
一無二的關鍵字串），並且協調社群的內部分工。此外，在多人競爭同名的模組時，解決
糾紛的機制也是必要的。更重要的，是將這些規範清楚寫下來，並且公開所有的流程。

    個人覺得，Perl 5 命名系統的缺憾之一，就是採用「先來先贏」的程序，導致每個名
    稱祗能由一位作者擁有。這可能有意無意間造成「佔名為王」的情況，或是過於情緒
    性的爭論；這兩者都對社群不利。

在設計作者、模組等階層時，應該要考慮延展性。我們一開始犯了個小錯，將作者名稱視
做同一個目錄下的次目錄；這很快就成了系統的瓶頸。（後來的解法很簡單，祗要用前兩
個字元做「雜湊」就是了。）最好考慮許多種檢視資料的方式：依作者、依模組、依類別
、依日期、依關鍵字等等。不要以為有階層目錄就夠了：總有一天會需要搜尋功能的。

授權條款

從開張的第一天起，就該把授權原則想清楚。不對，要從前一天起。這年頭的每份軟體，
最好都能標明它的授權條款。套件封裝工具在設計時，就該建議（甚或要求）使用者選擇
一種授權。這樣一來，模組的使用者和傳播者就不用自己瞎猜了。

跟授權條款有密切關係的，當然還有商業軟體的問題。CPAN 採取了簡潔明確的政策，禁止
一切專屬軟體，包括共享軟體、罪惡感軟體、捐獻軟體等等。我們認為，別種政策必然會
有爭議的空間，甚至會招來法律問題；作為一個純由志願者組成的團隊，我們並沒有處理
這種事情的時間與資源。

確保安全

不消說，典藏網的核心伺服器應該採取最嚴格的安全措施，並且謹慎維護；但是在此還是
叮嚀一句。

是否應該要使用 PGP/GPG 金匙，以及歃血為盟的強力簽章？也許吧。目前 CPAN 祗有 MD5
加總檢查－－但是目前為止是夠用了。話說回來，考慮到近來針對自由軟體發動的特洛伊
木馬攻擊案件，也許會需要更高層次的信任。社群裡有些計劃，讓使用者能藉由 PGP/GPG
金匙確定套件的來源；但就和所有公開金匙系統一樣，剛開始建立起信任鏈總是最難的一
關，也令某些人懷疑是否值得。公開金匙要放哪裡呢？顯然不是在散佈模組的同一個地方
。你又信任哪個公開金匙伺服器呢？如果不用公開金匙系統，也可以將原始的加總檢查檔
分散在許多位置，讓攻擊者無從一一下手。但在其中某個環節上，你幾乎還是非得信任
DNS 系統不可。

確保開放

品質控管？評分、評語？交叉評比？「正式核准」的軟體開發套件呢？這些都是熱烈討論
中的議題，在此不加贅述。畢竟，CPAN 現在及未來都會是開放而自由的場域，由作者自行
決定上載的內容；其後任何的揀選，都屬於各別的討論範圍。此外，評分或核准機制會產
生瓶頸，而瓶頸不是好事。

要照顧到 Intel Linux 及 Windows 之外的系統沒必要把口味獨特的使用者當做陌路人。
有一天他們會幫上忙的。

讓典藏網的內容能透過許多途徑呈現不要祗提供 HTTP 而已；也要考慮到 FTP 和 rsync。
話說回來，先支援基本的協定就好了－－不要興奮過度，一下就要建個花團錦簇的 Web
Service 平台，或其他什麼正在流行的東西。這呼應了不依賴特定平台的要求：模組的封
裝方式，應該讓儘可能多的人能夠安裝。

CPAN 程式集

維護 CPAN 的程式，真是簡單得要命。它們祗是些由 Cron 定時啟動的 Shell 命令稿，將
A、B ... Z 等站台複製到位於 ftp.funet.fi 的 CPAN 主站而已。大部份用的是古老的 
mirror [15]，有些則祗是 rsync [16] 而已。這沒什麼奧妙的；我真的沒有一份神奇的
CPAN 咒語袋，裝滿威力強大的卷軸。CPAN 主站上最複雜的程式，就是檢查各個映射站台
更新狀況的命令稿 [17]－－它也不是什麼高科技產物，祗是多工傳輸 FTP 及 HTTP 下載
，再比對時間戳記而已。

        [15] http://www.cpan.org/CPAN/scripts/ftpstuff/
        [16] http://www.rsync.org/
        [17] http://www.cpan.org/CPAN/misc/CPAN-code/

Andreas 已將 PAUSE 的網站源碼公佈在網站上 [18]。這份程式比 CPAN 的核心源碼、
PAUSE 的支援程式都要複雜些；但即使如此，它也是公開可取的。我們袖子裡並沒有藏著
什麼祕密。

        [18] ftp://pause.perl.org/pub/PAUSE/PAUSE-code/

結語

這種事是沒有魔法的。一開始，祗需要有幾個人著手讓一些東西動起來，多粗糙也無妨。
此後，一步步地改善它。別試圖規劃出包羅萬有的完美藍圖；它祗會將你淹沒而已。

上面說的，也可以用寶貴的 KISS 準則來概括－－Keep It Simple, Stupid.。避免複雜的
系統；從簡單的開始。

另一項重要的座右銘是：避免瓶頸與交互依賴。分散權力。建立並鼓勵另類的解法。。舉
例來說，CPAN 上最受歡迎的搜尋引擎，其實並不在 CPAN 核心服務之中；
search.cpan.org 祗是從 CPAN 映射檔案，從中建立索引及查詢介面而已。這樣一來，
CPAN 就能有好幾個搜尋引擎。同樣的，我們目前使用 CPAN.pm + MakeMaker 來安裝模組
，但是這兩者並非不可替代，而社群也在開發下一代的工具了。各項服務間應保持鬆散連
結。如此不同的人纔能各自開發新的功能，而不會彼此牽制。

而最需要的，或許還是執著：總有人得讓事情動下去。一個緩緩淍萎的典藏網，就算不如
什麼都沒有，起碼是更令人傷感的。

Oook，退場。

─────────────────────────────────────── 

    在撰寫本文的過程中，得到了許多朋友的珍貴回饋：感謝 CPAN 核心團隊，以及 
    use.perl.org（Perl 的新聞及社群站台）的讀者們。特別感謝 Neil Kandalgaonkar
    分享他在 ActiveState 內部工作時的甘苦談。

─────────────────────────────────────── 
本文是自由文件，可以依與 Perl 相同的授權條款散佈。允許引用、連結、翻譯或使用插
圖，惟必須保留原文的網址（http://www.cpan.org/misc/ZCAN.html）。
─────────────────────────────────────── 

$Date: 2003/01/20 $

Jarkko Hietaniemi, CPAN 館長

