話說新年到一家人該是和樂過年的時候,不過呢,吃完飯後閒閒沒事幹之際,大家喝茶嗑牙、談天說地之際,我跟我的父親卻因為對法的看法不同而吵起來了。
先說我父親的背景,他是調查局的公務員退休,對於法律的見解很是道地,他認為人就該奉公守法,社會才會安定。
如果我沒看過李宗吾和吳思兩位前輩的著作的話,我應該會同意他的論調,不過很抱歉,雖然兩位前輩的學說有點偏,但還是比我父親所想的:守法是國民的義務,這個觀點的解釋力來的強多了。
我認為,守法是一種選擇而非義務,當守法對我們有利時,我們才會去「主動」守法。許多法律,由於違犯了法律時,有明確的罰則,而這些罰則如果對我們來說承受不起,在利害計算之下,我們會選擇「被動」守法。
「法行故法在」、「法院是不告不理」,這是法律在實務執行上的限制,所以如果違犯法律被逮到的機率很低,而違法對我有利時,我就會選擇違法。舉例來說:深夜闖紅燈。
而我和我父親起衝突的導火線是,我提出美軍在伊拉克虐囚事件,並質問他:「代表正義的美軍在虐囚時,法律在哪裡?正義又在哪裡?」時,他很不高興的將我貼上「反社會行為」的標籤。
為此,我整個新年都不太愉快。
2007/02/25
2007/02/23
函數設計準則 (4)
這一篇主要是針對 函數設計準則 (2) 所作的修訂,為了讓看的人了解變化的過程,我選擇另開一篇來寫。
在過年前其實已經有定見了,不過前幾天跟我的父親吵了一架,心情不是很好,所以遲了幾天才寫,吵架的原因我會另開一篇說明。
首先是函數的特性,從單一處理到批次處理時,針對失敗與中斷的作法,如果要強調「無縫」的特性,其行為特徵應該改成這樣:
理由很簡單,我們既然不在乎成功或失敗的理由,我們還會在乎失敗的是哪幾個項目嗎?
以一般正常的函數來說,我們所期望的是成功的結果,而非失敗的結果(而目前我們所討論的這類函數,是被嚴格限制的),所以即便是批次處理,也應該遵循一致的作法。
要了解失敗的項目,一般來說是在除錯的時候比較需要,但一旦可以傳回失敗的項目,那麼在應用上就會面臨判斷式的改寫。對於程式流程上的處理,每包一層就要多作判斷,實在是不需要,防止過多的資訊亂竄,也是程式設計要考慮的事項。
接下來讓我們看看改寫後的函數:
function 載入:模組集($模組集){
$模組集 = &條件:陣列($模組集, false);
foreach($模組集 as $模組 => $條件){
if(!載入:模組($模組, $條件)){
return false;
}
}
return true;
}
function 選擇:模組($選擇集){
foreach($選擇集 as $選擇 => $模組集){
if(載入:模組集($模組集)){
return $選擇;
}
}
return false;
}
如此一來,對於批次處理的形式,就會精簡多了,而且把中斷的作用往下層推。
實際上,仍然可以將中斷的作用放在批次處理中,像底下這樣:
function 載入:模組集($模組集, $中斷 = true){
$輸出 = true;
$模組集 = &條件:陣列($模組集, false);
foreach($模組集 as $模組 => $條件){
if(!載入:模組($模組, $條件)){
if($中斷){
return false;
}
$輸出 = false;
}
}
return $輸出;
}
如何設計還是要看實際的需求,不過以這個例子來說,在批次處理時並不需要中斷的設計。
而 載入:模組集 函數中,哪些是屬於失敗處理呢?有兩個地方:
第二個部份,他是屬於偵測失敗的處理,這個觀點是將 載入:模組 函數視為一種測試,而非實際的動作(實際上 載入:模組 兼有兩者的特性,這裡注重其測試的特性)。
在過年前其實已經有定見了,不過前幾天跟我的父親吵了一架,心情不是很好,所以遲了幾天才寫,吵架的原因我會另開一篇說明。
首先是函數的特性,從單一處理到批次處理時,針對失敗與中斷的作法,如果要強調「無縫」的特性,其行為特徵應該改成這樣:
單一 | 批次 | |
(全部)成功 | 傳回 true | 傳回 true |
失敗 | 傳回 false | 傳回 false |
中斷 | 丟出中斷訊息 | 傳回 false |
理由很簡單,我們既然不在乎成功或失敗的理由,我們還會在乎失敗的是哪幾個項目嗎?
以一般正常的函數來說,我們所期望的是成功的結果,而非失敗的結果(而目前我們所討論的這類函數,是被嚴格限制的),所以即便是批次處理,也應該遵循一致的作法。
要了解失敗的項目,一般來說是在除錯的時候比較需要,但一旦可以傳回失敗的項目,那麼在應用上就會面臨判斷式的改寫。對於程式流程上的處理,每包一層就要多作判斷,實在是不需要,防止過多的資訊亂竄,也是程式設計要考慮的事項。
接下來讓我們看看改寫後的函數:
function 載入:模組集($模組集){
$模組集 = &條件:陣列($模組集, false);
foreach($模組集 as $模組 => $條件){
if(!載入:模組($模組, $條件)){
return false;
}
}
return true;
}
function 選擇:模組($選擇集){
foreach($選擇集 as $選擇 => $模組集){
if(載入:模組集($模組集)){
return $選擇;
}
}
return false;
}
如此一來,對於批次處理的形式,就會精簡多了,而且把中斷的作用往下層推。
實際上,仍然可以將中斷的作用放在批次處理中,像底下這樣:
function 載入:模組集($模組集, $中斷 = true){
$輸出 = true;
$模組集 = &條件:陣列($模組集, false);
foreach($模組集 as $模組 => $條件){
if(!載入:模組($模組, $條件)){
if($中斷){
return false;
}
$輸出 = false;
}
}
return $輸出;
}
如何設計還是要看實際的需求,不過以這個例子來說,在批次處理時並不需要中斷的設計。
而 載入:模組集 函數中,哪些是屬於失敗處理呢?有兩個地方:
- $模組集 = &條件:陣列($模組集, false);
- if(!載入:模組($模組, $條件)) 判斷式內
第二個部份,他是屬於偵測失敗的處理,這個觀點是將 載入:模組 函數視為一種測試,而非實際的動作(實際上 載入:模組 兼有兩者的特性,這裡注重其測試的特性)。
2007/02/21
2007/02/15
函數設計準則 (3)
我想對於一些用語不精確,造成誤解與討論上的困難,應該是給出一些定義的時候了。
底下是我用對設計階段的意圖所下的定義:
我認為,資料結構、演算法、重構、設計模式等等,都圍繞在關於「成功」這部份的處理,其他的部份論及較少。
我對於例外處理的態度和這篇相同,除非必要,我盡量不使用例外處理。
在我最近幾年寫過的程式中,有一類處理是必須使用例外處理的,那就是必須使用 eval() 時的場合。
這類處理由於很難在執行完 eval() 之前確認其執行結果,為了防範未然,必須使用例外處理來使得程式可以不因其執行失敗而中斷。
對於中斷與例外處理的概念,可以參考這篇。文章是比較偏向組合語言的說明,但是其觀念是相通的。
底下是我用對設計階段的意圖所下的定義:
- 成功:可由函數名稱看出其執行時的意圖,於流程上預期得出之處理。
- 失敗:與成功相對,於流程上非預期得出之處理。
- 錯誤:觸及程式語言中無法自理的條件,使得執行程式必須終止之處理。
- 例外:觸及區域流程上無法自理的條件,但可能借程式語言更正之處理。
我認為,資料結構、演算法、重構、設計模式等等,都圍繞在關於「成功」這部份的處理,其他的部份論及較少。
我對於例外處理的態度和這篇相同,除非必要,我盡量不使用例外處理。
在我最近幾年寫過的程式中,有一類處理是必須使用例外處理的,那就是必須使用 eval() 時的場合。
這類處理由於很難在執行完 eval() 之前確認其執行結果,為了防範未然,必須使用例外處理來使得程式可以不因其執行失敗而中斷。
對於中斷與例外處理的概念,可以參考這篇。文章是比較偏向組合語言的說明,但是其觀念是相通的。
2007/02/12
PHP 5.2.1 Release
對啦,我是知道新版的 PHP 5.2.1 Release 了,不過我個人是暫時不會去更新有關自行編譯的相關文章。
我只提幾個使用上要注意的地方:
我只提幾個使用上要注意的地方:
- 目前可以在 PECL4WIN 下到比較新的 DLL 來用。
- Suhosin Patch 有對應 PHP 5.2.1 的版本可用。
- Xcache 已有新版對應,雖然有人說拿對應 PHP 5.2.0 版的可以用,不過我自己試的結果是不行。
- 原因大概知道出在哪,因為我用 CGI 模式執行 PHP,所以掛不上去;如果用 Apache Handler 模式執行的話,就可以用。
- 前天才把訊息送到 XCache 的論壇上,馬上就有新版出現,真快!(不過有沒有人可以告訴我,dev 和 trunk 這兩個版本有什麼差異?)
函數設計準則 (2)
石頭在回應這一系列中提到調用者與被調用者的不同觀點,以及四種函數的分別。
我在寫這一系列時其實都想過了,但我著重的部份不是「可不可以」而是「應不應該」,有許多地方我還在調整,但因為部落格可以很快取得不同的迴響,所以我決定先發表再說,文章的內容日後可以再進行整理與修改。
借用石頭的調用者與被調用者的觀點,這篇文章來提一下調用者的部份,先來看個例子:
function 載入:模組集($模組集, $中斷 = true){
$輸出 = array();
$模組集 = &條件:陣列($模組集, false);
foreach($模組集 as $模組 => $條件){
if(!載入:模組($模組, $條件)){
if($中斷){
return $模組;
}
$輸出[] = $模組;
}
}
if(empty($輸出)){
return true;
}else{
return $輸出;
}
}
function &條件:陣列(&$陣列, $預設 = true){
$預設 = ($預設) ? true : false;
if(!is_array($陣列)){
return array($陣列 => $預設);
}
$輸出 = array();
foreach($陣列 as $索引 => $項目){
if(is_bool($項目)){
$輸出[$索引] = $項目;
}else{
$輸出[$項目] = $預設;
}
}
return $輸出;
}
這幾個函數我都還在想有沒有更好的設計方式,所以請不要以為這就是我的定見,只是我上次拋出一個話題,必須要很快的說明相關的設計準則與概念,所以把我思考的筆記與實例拿出來作說明。
「載入:模組集」這個函數,會呼叫「載入:模組」作批次處理。
這個函數經過特化處理,因為「載入:模組」這個函數如果不算「中斷」這個參數的話,他其實只接受一個參數,即模組的名稱。
這裡我依然將「中斷」的概念賦予在批次處理上,這時候的責任關係就很簡單:要不往上丟,要不往下推。
而批次處理時的「中斷」概念,其實比較符合「流程中斷」,因為他並不是最底層,不會牽扯到「錯誤處理」。
這類批次的函數,其特性應與單一處理的函數,有著一致性的行為特徵,我列表在下面:
當然,這是我個人的看法,我關注的部份是「失敗處理」,而非「錯誤處理」或是「例外處理」。
所以,藉由「失敗」而引發的「錯誤」或是「例外」,只是處理的一種「手段」。
有些時候我們很無奈,有心處理但卻無法處理,只好引發「錯誤」或是「例外」,但請不要以為失敗就一定會引發錯誤或是例外,這是兩回事!
我把這類函數的特性再抄一遍:
這是我強調的重點!「在此前提下,所以我會這樣設計」,這是我要拿出來討論的。
那麼調用這些批次函數的狀況又如何呢?這裡有個例子:
function 選擇:模組($選擇集){
foreach($選擇集 as $選擇 => $模組集){
if(true === 載入:模組集($模組集, true)){
return $選擇;
}
}
return false;
}
這個函數是在做一種簡單的策略選擇的判斷,這個判斷會根據一些載入模組的組合來選擇合適的策略。
在討論下去就有點偏離主題了,舉例就到這裡,有三層:選擇:模組->載入:模組集->載入:模組。
為甚麼要特別提出「中斷」的概念?我說不上來,我只知道,沒有中斷的設計,失敗的責任是會累積的。
讓我們再看兩個函數,這兩個函數是我把中斷拿掉後,產生的兩個特例:
// 函數1
function 載入:模組($模組){
$前綴 = (PHP_SHLIB_SUFFIX == 'dll') ? 'php_' : '';
if(!extension_loaded($模組) && !@dl($前綴.$模組.'.'.PHP_SHLIB_SUFFIX)){
$訊息 = '無法載入 '.$模組.' 模組';
exit($訊息);
}else{
return true;
}
}
// 函數2
function 載入:模組($模組){
$前綴 = (PHP_SHLIB_SUFFIX == 'dll') ? 'php_' : '';
if(!extension_loaded($模組) && !@dl($前綴.$模組.'.'.PHP_SHLIB_SUFFIX)){
return false;
}else{
return true;
}
}
看到了嗎?如果是這樣的兩個函數,要如何批次處理?就會造成我之前回應的,要多作檢查去應對。
我不否認這樣的設計比較簡單,但這是完全不承擔責任或是「先斬後奏」的設計方式。
我在寫這一系列時其實都想過了,但我著重的部份不是「可不可以」而是「應不應該」,有許多地方我還在調整,但因為部落格可以很快取得不同的迴響,所以我決定先發表再說,文章的內容日後可以再進行整理與修改。
借用石頭的調用者與被調用者的觀點,這篇文章來提一下調用者的部份,先來看個例子:
function 載入:模組集($模組集, $中斷 = true){
$輸出 = array();
$模組集 = &條件:陣列($模組集, false);
foreach($模組集 as $模組 => $條件){
if(!載入:模組($模組, $條件)){
if($中斷){
return $模組;
}
$輸出[] = $模組;
}
}
if(empty($輸出)){
return true;
}else{
return $輸出;
}
}
function &條件:陣列(&$陣列, $預設 = true){
$預設 = ($預設) ? true : false;
if(!is_array($陣列)){
return array($陣列 => $預設);
}
$輸出 = array();
foreach($陣列 as $索引 => $項目){
if(is_bool($項目)){
$輸出[$索引] = $項目;
}else{
$輸出[$項目] = $預設;
}
}
return $輸出;
}
這幾個函數我都還在想有沒有更好的設計方式,所以請不要以為這就是我的定見,只是我上次拋出一個話題,必須要很快的說明相關的設計準則與概念,所以把我思考的筆記與實例拿出來作說明。
「載入:模組集」這個函數,會呼叫「載入:模組」作批次處理。
這個函數經過特化處理,因為「載入:模組」這個函數如果不算「中斷」這個參數的話,他其實只接受一個參數,即模組的名稱。
這裡我依然將「中斷」的概念賦予在批次處理上,這時候的責任關係就很簡單:要不往上丟,要不往下推。
而批次處理時的「中斷」概念,其實比較符合「流程中斷」,因為他並不是最底層,不會牽扯到「錯誤處理」。
這類批次的函數,其特性應與單一處理的函數,有著一致性的行為特徵,我列表在下面:
單一 | 批次 | |
(全部)成功 | 傳回 true | 傳回 true |
失敗 | 傳回 false | 傳回失敗項目陣列 |
中斷 | 丟出中斷訊息 | 傳回中斷項目 |
當然,這是我個人的看法,我關注的部份是「失敗處理」,而非「錯誤處理」或是「例外處理」。
所以,藉由「失敗」而引發的「錯誤」或是「例外」,只是處理的一種「手段」。
有些時候我們很無奈,有心處理但卻無法處理,只好引發「錯誤」或是「例外」,但請不要以為失敗就一定會引發錯誤或是例外,這是兩回事!
我把這類函數的特性再抄一遍:
- 這類函數進行一些單純的動作,執行結果只有成功或是失敗兩種結果。
- 呼叫該函數時,我們對其成功或失敗的原因不感興趣,我們只希望知道其執行結果到底是成功或是失敗。
- 在其執行失敗時,有時會需要將程式流程中斷下來,我們需要一個條件去指示是否需要進行中斷。
這是我強調的重點!「在此前提下,所以我會這樣設計」,這是我要拿出來討論的。
那麼調用這些批次函數的狀況又如何呢?這裡有個例子:
function 選擇:模組($選擇集){
foreach($選擇集 as $選擇 => $模組集){
if(true === 載入:模組集($模組集, true)){
return $選擇;
}
}
return false;
}
這個函數是在做一種簡單的策略選擇的判斷,這個判斷會根據一些載入模組的組合來選擇合適的策略。
在討論下去就有點偏離主題了,舉例就到這裡,有三層:選擇:模組->載入:模組集->載入:模組。
為甚麼要特別提出「中斷」的概念?我說不上來,我只知道,沒有中斷的設計,失敗的責任是會累積的。
讓我們再看兩個函數,這兩個函數是我把中斷拿掉後,產生的兩個特例:
// 函數1
function 載入:模組($模組){
$前綴 = (PHP_SHLIB_SUFFIX == 'dll') ? 'php_' : '';
if(!extension_loaded($模組) && !@dl($前綴.$模組.'.'.PHP_SHLIB_SUFFIX)){
$訊息 = '無法載入 '.$模組.' 模組';
exit($訊息);
}else{
return true;
}
}
// 函數2
function 載入:模組($模組){
$前綴 = (PHP_SHLIB_SUFFIX == 'dll') ? 'php_' : '';
if(!extension_loaded($模組) && !@dl($前綴.$模組.'.'.PHP_SHLIB_SUFFIX)){
return false;
}else{
return true;
}
}
看到了嗎?如果是這樣的兩個函數,要如何批次處理?就會造成我之前回應的,要多作檢查去應對。
我不否認這樣的設計比較簡單,但這是完全不承擔責任或是「先斬後奏」的設計方式。
2007/02/11
函數設計準則 (1)
話說我個人對函數的設計比類別的設計來的有興趣的多,函數的設計有許多地方是有準則可以遵循的,我希望在我的程式設計生涯中,能找出這些準則。
這篇主要在探討在函數中,執行「中斷」的一些設計準則。
所謂的「中斷」,是一種條件,這種條件使函數執行失敗時跳脫程式既定的「循序流程」,亦可能引發錯誤而使程式停止。
補述:我個人其實並不喜歡「例外處理」,我覺得在使用「例外處理」之前,設計者應盡到責任,將可「自理」的部份做好處理。濫用「例外處理」的結果,就會把「所有的責任」推給作業系統來收爛攤子。
讓我們考慮這一類型的函數:
先舉個例子來看看:
function 載入:模組($模組, $中斷 = true){
$前綴 = (PHP_SHLIB_SUFFIX == 'dll') ? 'php_' : '';
if(!extension_loaded($模組) && !@dl($前綴.$模組.'.'.PHP_SHLIB_SUFFIX)){
if($中斷){
$訊息 = '無法載入 '.$模組.' 模組';
trigger_error($訊息, E_USER_ERROR);
// exit($訊息);
}else{
return false;
}
}else{
return true;
}
}
這是一個載入 PHP Extension 用的函數,在實務上,當我們的 PHP 程式在執行時,有時必須載入某些模組,當這些模組無法載入時,則必須強制停止程式的執行。
先不論這裡的錯誤處理方式是否優雅,我們關注的是,中斷行為是一個(可控)條件,當執行失敗時,我們可以選擇是中斷。
這篇主要在探討在函數中,執行「中斷」的一些設計準則。
所謂的「中斷」,是一種條件,這種條件使函數執行失敗時跳脫程式既定的「循序流程」,亦可能引發錯誤而使程式停止。
補述:我個人其實並不喜歡「例外處理」,我覺得在使用「例外處理」之前,設計者應盡到責任,將可「自理」的部份做好處理。濫用「例外處理」的結果,就會把「所有的責任」推給作業系統來收爛攤子。
讓我們考慮這一類型的函數:
- 這類函數進行一些單純的動作,執行結果只有成功或是失敗兩種結果。
- 呼叫該函數時,我們對其成功或失敗的原因不感興趣,我們只希望知道其執行結果到底是成功或是失敗。
- 在其執行失敗時,有時會需要將程式流程中斷下來,我們需要一個條件去指示是否需要進行中斷。
先舉個例子來看看:
function 載入:模組($模組, $中斷 = true){
$前綴 = (PHP_SHLIB_SUFFIX == 'dll') ? 'php_' : '';
if(!extension_loaded($模組) && !@dl($前綴.$模組.'.'.PHP_SHLIB_SUFFIX)){
if($中斷){
$訊息 = '無法載入 '.$模組.' 模組';
trigger_error($訊息, E_USER_ERROR);
// exit($訊息);
}else{
return false;
}
}else{
return true;
}
}
這是一個載入 PHP Extension 用的函數,在實務上,當我們的 PHP 程式在執行時,有時必須載入某些模組,當這些模組無法載入時,則必須強制停止程式的執行。
先不論這裡的錯誤處理方式是否優雅,我們關注的是,中斷行為是一個(可控)條件,當執行失敗時,我們可以選擇是中斷。
讀書
古人說:「三日不讀書,便覺面目可憎。」
實際上,我已有個把個月沒在讀書了,雖說目前口袋理沒有多餘的閒錢,但也不至於落到李宗吾所說的:「有錢買書,無錢買米。」的地步。
所以我還是花了錢買本書看看,換一下新觀念。
2007/02/10
2007/02/08
PHP6 下的 Unicode 設定
昨天下了 PHP6-dev 來試試看,剛剛裝上去,測試了幾種檔案讀寫狀況,其實在 php.ini 中需要設定的只有底下兩行:
第二行 unicode.filesystem_encoding = BIG5 表示指定檔案系統的編碼,這裡我使用 BIG5 是遷就 Windows 系統,如果是在 Linux / FreeBSD 上,應該可以設成 UTF-8。
有個地方要注意:
這裡有兩份文件,可以參考看看:文件一,文件二。
其他如傳遞參數等狀況,我有空在測試看看。
- unicode.semantics = on
- unicode.filesystem_encoding = BIG5
第二行 unicode.filesystem_encoding = BIG5 表示指定檔案系統的編碼,這裡我使用 BIG5 是遷就 Windows 系統,如果是在 Linux / FreeBSD 上,應該可以設成 UTF-8。
有個地方要注意:
- 除了中文,其他的編碼文字不能出現在檔案名稱中,否則會無法操作檔案。
- 檔案名稱的部份雖然可以用中文,但是寫入檔案時的資料如果含有其他國家的文字,會跑出 Notice ,可以在 fwrite 前加上 @ 來抑制。
- 載入 PHP 的方式若是用 Apache Handler,在某些常數名稱上會出現錯誤,建議使用 CGI 模式載入 PHP。
這裡有兩份文件,可以參考看看:文件一,文件二。
其他如傳遞參數等狀況,我有空在測試看看。
2007/02/06
好用的 VM:VirtualBox
今天看雜誌的介紹,有提到一個叫 VirtualBox 的虛擬機器,剛剛下載回來安裝,速度上不比 MS 的 VPC 差,覺得很滿意。
不過他的 ShareFolder 設定方法比較麻煩,所以我紀錄在這邊:
不過他的 ShareFolder 設定方法比較麻煩,所以我紀錄在這邊:
- 先把一個虛擬機器 Run 起來,裝完作業系統(XP)後 Shutdown。
- 開一個 DOS 視窗,切換目錄到 VirtualBox 的安裝目錄(C:\Program\InnoTek VirtualBox)。
- 執行 VBoxManage sharedfolder add "VM name" -name "sharename" -hostpath "C:\test"
- VM name 指的是虛擬機器的名稱
- sharename 指的是在虛擬機器中的 ShareFolder 名稱
- C:\test 指的是 Host 裡面的路徑名稱
- 或是你也可以直接修改設定檔,你可以看一下 VirtualBox 的 File 選單中的 Global Settings 裡面的 Machines 的目錄,在該目錄底下你可以找到相關的 VM name 的目錄,在該 VM name 的目錄下,有個 xml 檔案,打開來編輯,加入:
- <SharedFolders>
<SharedFolder hostPath="C:\test" name="sharename"/>
</SharedFolders>
- <SharedFolders>
- 啟動虛擬機器,開機完後在虛擬機器中打開 DOS 視窗,執行:
- net use x: \\vboxsvr\sharename
- 打開檔案總管,就可以看到 ShareFolder 了。
介紹兩套樣板系統
上次石頭談了一些有關樣板系統的事情,這次我來介紹我喜歡用的兩套樣板系統:
第一套是 TBS(TinyButStrong),俗稱小強。這套我最早是看到 Neo 的這篇介紹知道的。
這套的優點就是小而快,不過缺點就是要整版輸出,很難用拼版的作法(要繞個彎)。
第二套是 SmartTemplate,這套是我弟介紹給我用的,我當時在找 PEAR::HTML_Template_ITX 的替代品,他就介紹了這套給我。
這套蠻合我的口味,缺點就是修飾子的運用方法不像 TBS 那麼強大。
第一套是 TBS(TinyButStrong),俗稱小強。這套我最早是看到 Neo 的這篇介紹知道的。
這套的優點就是小而快,不過缺點就是要整版輸出,很難用拼版的作法(要繞個彎)。
第二套是 SmartTemplate,這套是我弟介紹給我用的,我當時在找 PEAR::HTML_Template_ITX 的替代品,他就介紹了這套給我。
這套蠻合我的口味,缺點就是修飾子的運用方法不像 TBS 那麼強大。
2007/02/04
以世俗觀點論李嗣涔鎖學生論文
眾所周知,李嗣涔教授關於特異功能的研究,常被學術界的人抨擊。
依我個人看來,這次鎖論文事件,有點「賭氣」的成份在。
在石頭那邊,鎖不鎖學術論文之我見,我用研究道德的觀點做了一些評論,這次我想用一些比較世俗的、權謀的觀點來談這件事。
首先我要提的事情是,學術界其實很黑暗,沒有一般人想像的那麼崇高。
先從碩士論文說起,今天你發表了碩士論文,拿到碩士學位,這不代表你一輩子都是碩士。
因為碩士資格是隨時都會被追回的,只要你的論文作假、抄襲或是有顯著的瑕疵,前面兩者就不談了,但顯著的瑕疵這點是可以雞蛋中挑骨頭的。
一般來說,既然口試委員都願意幫你的論文背書了,基本上頂多事後補強一些東西,修改論文後就過關。但有些研究會有灰色地帶,比如說只有理論推導,沒有直接實證的先期型研究。這類型研究一般來說不會出現在碩士論文中,通常是博士或是博士後研究才會出現。
從那篇論文口試委員的意見中,我們可以得知這篇論文是屬於先期型研究,在加上論文題目的爭議大,我不太能夠了解為何李教授要讓他的學生來發表這篇,照理說,這篇論文並不適合在碩士生的論文中出現。
無論如何,這篇論文已經出現,而鎖論文的時間點又不是一開始就鎖,而是 楊信男教授「質疑」論文內容,想去圖書館找全文時,才發生這個新聞事件。
而我從楊教授的角度來看這件事,如果我真的想看這篇論文的全文,真的沒辦法看得到嗎?非要透過媒體製造新聞事件嗎?不要說這篇論文七月多發表,十月時才鎖,這中間沒人拿到原文是很不可思議的事情,真的要看,難道不會去找李教授當面要嗎?再不然,加入李教授的研究小組,也可以拿到第一手資料,何必搞這一套?
所以我個人認為,李教授鎖論文是有可議之處,但為何他會在楊教授去查全文時才作鎖論文的動作,其不言而喻的的理由便呼之欲出。
所以我建議楊教授,你可以好好的跟李教授請益,畢竟人家也不是小氣鬼,而且當時作研究的人都找的到,有必要搞到這一步嗎?
在學術界有一句話是:站在巨人的肩膀上走出一小步。這是比較好聽的說法,難聽一點就是,拿別人的東西不勞而獲。有骨氣的話,自己作研究去證明真偽,不要去為難小小的碩士生,這樣很難看。
至於為何要鎖論文十年,我個人的想法是,十年後,該研究生在社會上也站穩腳步了,無須碩士光環來找好工作,到時無論這個研究是真是假,都不影響該生在世上安身立命,當然這是比較權謀的說法。
當然,從有新玩具可玩的角度來講,開放論文是比較好的,不過人家就是不給你看也沒犯法,要不自行努力,要不十年後請早。用石頭的說法:在「知識」的眼中,幾千或幾萬年的時間相差無幾,早一千年知道、晚一千年知道,並沒有什麼太大差別。
既然早晚一千年都沒差了,那晚十年會有差嗎?我也不相信楊教授是真的想研究撓場這一塊,在我眼中看來,找碴的成份居多,但是找碴請對正主,不要為難人家的學生。
依我個人看來,這次鎖論文事件,有點「賭氣」的成份在。
在石頭那邊,鎖不鎖學術論文之我見,我用研究道德的觀點做了一些評論,這次我想用一些比較世俗的、權謀的觀點來談這件事。
首先我要提的事情是,學術界其實很黑暗,沒有一般人想像的那麼崇高。
先從碩士論文說起,今天你發表了碩士論文,拿到碩士學位,這不代表你一輩子都是碩士。
因為碩士資格是隨時都會被追回的,只要你的論文作假、抄襲或是有顯著的瑕疵,前面兩者就不談了,但顯著的瑕疵這點是可以雞蛋中挑骨頭的。
一般來說,既然口試委員都願意幫你的論文背書了,基本上頂多事後補強一些東西,修改論文後就過關。但有些研究會有灰色地帶,比如說只有理論推導,沒有直接實證的先期型研究。這類型研究一般來說不會出現在碩士論文中,通常是博士或是博士後研究才會出現。
從那篇論文口試委員的意見中,我們可以得知這篇論文是屬於先期型研究,在加上論文題目的爭議大,我不太能夠了解為何李教授要讓他的學生來發表這篇,照理說,這篇論文並不適合在碩士生的論文中出現。
無論如何,這篇論文已經出現,而鎖論文的時間點又不是一開始就鎖,而是 楊信男教授「質疑」論文內容,想去圖書館找全文時,才發生這個新聞事件。
而我從楊教授的角度來看這件事,如果我真的想看這篇論文的全文,真的沒辦法看得到嗎?非要透過媒體製造新聞事件嗎?不要說這篇論文七月多發表,十月時才鎖,這中間沒人拿到原文是很不可思議的事情,真的要看,難道不會去找李教授當面要嗎?再不然,加入李教授的研究小組,也可以拿到第一手資料,何必搞這一套?
所以我個人認為,李教授鎖論文是有可議之處,但為何他會在楊教授去查全文時才作鎖論文的動作,其不言而喻的的理由便呼之欲出。
所以我建議楊教授,你可以好好的跟李教授請益,畢竟人家也不是小氣鬼,而且當時作研究的人都找的到,有必要搞到這一步嗎?
在學術界有一句話是:站在巨人的肩膀上走出一小步。這是比較好聽的說法,難聽一點就是,拿別人的東西不勞而獲。有骨氣的話,自己作研究去證明真偽,不要去為難小小的碩士生,這樣很難看。
至於為何要鎖論文十年,我個人的想法是,十年後,該研究生在社會上也站穩腳步了,無須碩士光環來找好工作,到時無論這個研究是真是假,都不影響該生在世上安身立命,當然這是比較權謀的說法。
當然,從有新玩具可玩的角度來講,開放論文是比較好的,不過人家就是不給你看也沒犯法,要不自行努力,要不十年後請早。用石頭的說法:在「知識」的眼中,幾千或幾萬年的時間相差無幾,早一千年知道、晚一千年知道,並沒有什麼太大差別。
既然早晚一千年都沒差了,那晚十年會有差嗎?我也不相信楊教授是真的想研究撓場這一塊,在我眼中看來,找碴的成份居多,但是找碴請對正主,不要為難人家的學生。
2007/02/03
在 Windows 下編譯 PHP 模組告一段落
這幾天生病在家修養,沒有在搞東搞西,讓自己沈澱一下。
思考後發現,目前研究如何在 Windows 下編譯 PHP 模組的部份可以暫時告一段落了。
理由是我發現作這件事情對我的目標並沒有實質的效益,我的目標是開發程式,不是產生開發環境,而有關一開始提到的記憶體使用的函數,可以用其他方式達成,我也實做出來了,因此接下去應以程式開發為主了。
思考後發現,目前研究如何在 Windows 下編譯 PHP 模組的部份可以暫時告一段落了。
理由是我發現作這件事情對我的目標並沒有實質的效益,我的目標是開發程式,不是產生開發環境,而有關一開始提到的記憶體使用的函數,可以用其他方式達成,我也實做出來了,因此接下去應以程式開發為主了。
2007/02/01
iconv 和 gettext 的編譯方式
iconv 和 gettext 這兩個 Extensions 必須一起編譯,所以就一同介紹。
要注意的是,目前沒辦法拿最新的版本來編譯,我測試過可以成功的版本號碼如下:
要注意的是,目前沒辦法拿最新的版本來編譯,我測試過可以成功的版本號碼如下:
- iconv:libiconv-1.9.2.tar.gz
- gettext:gettext-0.14.6.tar.gz
- 源碼可從每個 GNU FTP Mirror 取得:FTP 列表。
- 下載後解開至 D:\Work\test\iconv、D:\Work\test\gettext
- 切換目錄至 D:\Work\test\iconv,執行:
- nmake -f Makefile.msvc NO_NLS=1 MFLAGS=-MT
- nmake -f Makefile.msvc NO_NLS=1 MFLAGS=-MT install
- nmake -f Makefile.msvc NO_NLS=1 MFLAGS=-MT distclean
- 切換目錄至 D:\Work\test\gettext,執行:
- nmake -f Makefile.msvc MFLAGS=-MT
- nmake -f Makefile.msvc MFLAGS=-MT install
- 切換目錄至 D:\Work\test\iconv,執行:
- nmake -f Makefile.msvc MFLAGS=-MT
- nmake -f Makefile.msvc MFLAGS=-MT install
- 現在可以從 C:\usr 中找到編譯所需的檔案:
- 複製 C:\usr\include 中的 iconv.h 和 libintl.h 至 D:\Work\win32build\include 中
- 複製 C:\usr\lib 中的 iconv.lib 至 D:\Work\win32build\lib 中
- 複製 C:\usr\lib 中的 intl.lib 至 D:\Work\win32build\lib 中,並更名為 libintl.lib
- 修改 PHP 源碼中的 ext\iconv\config.w32,將第7行:
- if (/*CHECK_LIB("iconv.lib", "iconv", PHP_ICONV) &&*/
- 改為
- if (CHECK_LIB("iconv.lib", "iconv", PHP_ICONV) &&
- 修改 php_conf.bat 加上參數 --with-iconv 和 --with-gettext
- 重新編譯 PHP,執行:php_make.bat
- 編譯完成後安裝請執行:php_make.bat install
- iconv 可以動態連結也可以靜態連結,可以單獨載入(可使用 --without-gettext)
- gettext 只能靜態連結,且必須與 iconv 一同載入(不可使用 --without-iconv)
- 建議將兩者都使用靜態連結
訂閱:
文章 (Atom)