2012-09-03 37 views
3

關於函數調用,是它不如給主叫方檢查,如果一個函數或工作失敗,還是應該由誤差函數自身公佈的責任?錯誤 - 它們屬於邏輯還是表示層?

我問的原因是因爲我不喜歡混合演示文稿和邏輯,但是如果調用者必須進行錯誤檢查,它可能是不準確和繁瑣的,例如。

if(!login($username, $password) 
{ 
    echo 'Login failed. Please try again.'; 
} 

調用者不知道爲什麼失敗。用戶名/密碼組合錯誤,還是數據庫連接失敗?或者其他一些意外的原因?

這不會是一個問題,如果我們可以將錯誤檢查/扔函數中的例外,因爲那樣我們將不得不在代碼例如數據庫連接失敗的特定點的特定錯誤......但是這將是混合呈現和邏輯。這裏最好的做法是什麼?

謝謝。

+0

未通過身份驗證實際上不是「錯誤」。接收不正確的登錄名/密碼是程序正常操作過程中預計的事情。如果密碼匹配,函數應該返回true,否則返回false。 – cleong

+0

@cleong在這種情況下,是的,但我認爲這只是一個通用問題的例子。 – Andy0708

回答

2

我會親自給呼叫者通過在業務邏輯(模型)層拋出異常的責任。然後,可以在控制器中捕獲異常(並在視圖中爲錯誤分配一個變量)。有些人甚至希望直接在表示層中捕獲異常,但這在Web開發的情況下並不適用。只要該例外僅用於視圖中的表示目的,我並不認爲它是一個很大的問題。

所以,我不會做,正如你在簡單的例子做了,因爲主叫方可能並不總是要顯示一個錯誤。通過處理對呼叫者的責任,他或她可以選擇。另外,我不喜歡在業務邏輯中迴應內容(我傾向於拋出異常並保持模型清晰),但是您的代碼很可能只是一個簡單的示例。

編輯:你可以做這樣的事情:

型號:

function login($username, $password) { 
    if (login failed) { 
     throw new Login_Exception(); 
    } 

    else { 
     // Set session 
     return true; 
    } 
} 

控制器:

try { 
    $model->login($username, $password); 
} 

catch (Login_Exception $e) { 
    $view->loginError = 'There was an error logging in.'; 
} 

然後,您可以拋出不同的異常指示究竟哪裏出了問題(例如Wrong_Username_Exception)並相應地處理它。另外,你甚至可以在異常的構造函數中提供一個用戶友好的理由,但在我看來,這會將表示和邏輯耦合得太多。

+0

他問函數/程序,而不是oop –

+0

@VladBalmos你是對的,他沒有明確提到OOP。我只是假設OOP與這些圖層有關。但是,即使沒有控制器/模型類,也可以使用這樣的異常。 – Andy0708

+0

是的,你也是對的,你可以在php中混合使用異常處理和程序代碼。但有點打破一致性 –

0

第一個。調用者應該有錯誤檢查的責任。 如果你想知道什麼樣的錯誤ocured你可以重寫登錄功能,並添加第三個參數,將舉行一個參考的錯誤,像這樣:

<?php 
function login($user, $pass, &$error) { 
    // if user or pass wrong 
    $error = 'Username/pass wrong'; 

    // if db failed 
    $error = 'unable to connect to db' 
}; 

if(!login($user, $pass, $error)) { 
    // do whatever you want with the error 
} 

更重要的是,你可以使用常量錯誤類型

UPDATE

你不想顯示錯誤withing功能如果要設置會話或cookies,您已調用的函數之後。這將打破變薄,你會得到這樣的通知:「頭已經發出......」

+0

但是,如果考慮到錯誤信息是在函數內部的話,是不是還會混合表示和邏輯呢?如果有人想修改錯誤信息,他們將不得不通過實際的代碼。我喜歡你使用常量的建議,最好將它們放在配置文件中,這樣用戶就可以在單獨的文件中定義每個場景的錯誤消息應該是什麼樣子,比在功能邏輯內部簡單得多。 – Kausheel

+0

如果你使用錯誤代碼,那麼你解決演示問題 –

1

與樣品代碼的問題:

if(!login($username, $password) 
{ 
    echo 'Login failed. Please try again.'; 
} 

...是登錄()函數不呼叫者一起工作返回足夠的信息。無論調用者是Web表示層還是其他,這都是一個問題。

更好的login()函數會返回一個對象,讓您的來電者可以這樣做:

$response = login($username, $password); 
if(! $response->isLoggedIn()) { 
    echo "Login failed. " + $response->getErrorMessage(); 
} 

現在您的登錄方法不緊耦合到用戶界面,但是你可以通過一個理由爲用戶登錄失敗。

現在,可以說login()方法中仍然存在「presentation」,因爲它返回的文本是逐字引用給用戶的。如果你想更加鬆散耦合,你可以定義一個錯誤代碼列表,並讓你的表示層將它們轉換成消息。或者你可以返回一個指向消息表的值。閱讀國際化;這是相同的基本域。