2013-02-27 16 views
1

我是新來的try-catch並且最近重構了很多代碼以跟上DRY的原理。但是,我仍然有一些我無法解決的情況。例如,在我正在處理的多語言應用程序中,我想讓用戶通過在URL的查詢字符串中傳遞雙字母國家代碼來設置界面語言,或者讓應用程序使用默認語言if用戶沒有要求一個:如何重構這個嵌套的try-catch

// Which language shall we use? 
$language = new language(); 
if(isset($_GET['language_code'])){ 
    try { 
     $language->set_by_language_code($_GET['language_code']); 
    } catch(e_language_not_found $e){ 
     try { 
      $language->set_default_language(); 
      // TODO - use 'e_language_not_found' to display an error in the default language 
     } catch(Exception $e){ 
      exit('No default language found'); 
     } 
    } 
} else { 
    try { 
     $language->set_default_language(); 
    } catch(Exception $e){ 
     exit('No default language found'); 
    } 
} 

的問題是,我已經重複了set_default_language()塊當用戶沒有要求任何語言都沒有。我如何重構代碼,以便在應用程序中只調用一次該方法?謝謝!

+0

我認爲這個問題會更適合**代碼審查Beta版**:http://codereview.stackexchange.com/ – ComFreek 2013-02-27 22:35:33

+0

如果用戶沒有請求任何語言我猜language_code將不會被設置爲第二個set_default_language()將被調用,爲了解決這個問題,您可以在while語言設置中添加另一個條件。但是我不明白你的問題必須與嵌套try-catch – 2013-02-27 22:36:03

回答

2

你在兩個地方調用函數的事實本身並不壞。它不會影響性能,重構它可能會使代碼變得不可讀。

這是我想出了您的代碼:

// Which language shall we use? 
$language = new language(); 
try { 
    try { 
    if(isset($_GET['language_code'])){ 
     $language->set_by_language_code($_GET['language_code']); 
    } else { 
     $language->set_default_language();  
    } 
    } catch(e_language_not_found $e){  
     $language->set_default_language();  
    } 
} catch (Exception $e){ 
    exit('No default language found'); 
} 
+0

對於每個set_default_language()調用,我是否還需要try-catch? – boatingcow 2013-02-27 22:51:55

+0

據我可以告訴這個代碼相當於你的。外部'try {} catch(Exception $ e)'將處理來自'set_default_language()'的所有異常,無論它們在哪裏拋出。 – Mchl 2013-02-27 22:57:14

+0

感謝@Mchl,所以只要'set_default_language()拋出一個'e_default_language_not_found'異常而不是泛型異常,我可以在外部塊中捕獲這個異常? – boatingcow 2013-02-27 23:08:02

3

在我看來,你應該在你language類實現這些方法:

  • language::hasLanguage()返回表示語言的存在一個布爾值(未拋出異常!)

  • language::getDefLang()它返回默認的語言標識符。


// Which language shall we use? 
$language = new language(); 

// fallback 
$langToSet = $language->getDefLang(); 

// use the passed language identifier if it exists 
$passedLangId = isset($_GET['language_code']) ? $_GET['language_code'] : NULL; 
if ($passedLangId !== NULL && $language->hasLanguage($passedLangId)) { 
    $langToSet = $passedLangId; 
} 

try { 
    $language->set_by_language_code($langToSet); 
} 
catch(Exception $e){ 
    exit('No default language found'); 
} 

你也應該指定一個更詳細的Exception型爲catch塊。

您還可以在if語句中使用language::hasLanguage()替換try...catch塊。

+0

確定一個更好的方法去 – Mchl 2013-02-27 22:57:42

+0

正如書面,我仍然需要在getDefLang()方法中的try-catch和異常,以防沒有找到默認的語言,它只是將這個邏輯移動到一個不同的容器 - 是你的意思? – boatingcow 2013-02-27 22:58:08

+0

@boatingcow問題是a)你只調用一次(DRY)'set_by_language_code()'和b)因此你只有一個'try ... catch'塊。你也可以用'hasLanguage()'來替換它(如編輯中所寫)。您應該決定是否將「存在」邏輯存儲在'language'類或用戶代碼中。 – ComFreek 2013-02-28 19:02:42