2011-06-03 61 views
4

這更像是一個概念性問題。使用Try/catch和Do /雖然

它是aceptable /良好的編程混合做/同時用try/catch語句的循環?

例如:

<?php 
function main() { 

    $failure = 0; 
    do { 
     $failure += foo(); 
     $failure += bar(); 
     ... 
     if ($failure) { return $failure; } 
    } 
    while ($failure == 0); 
} 

function foo() { 
    try { 
     echo 'DO FOO STUFF<br />'; 
     return 0; 
    } 
    catch (Exception $e) { 
     return 1; 
    } 
} 

function bar() { 
    try { 
     echo 'DO BAR STUFF<br />'; 
     return 0; 
    } 
    catch (Exception $e) { 
     return 1; 
    } 
} 
?> 

我問的原因是我讀的地方,兩個混合是不好的做法。你應該創建你自己的例外,並「拋出」它們。但是這不是一點矯枉過正?

編輯: 爲了解釋這一場景這個問題出現了,可想而知,必須遵循一條線的機器人。機器人每進行一步計算其位置(X位置,Y位置,Z位置和「姿勢」位置)並將信息發送到服務器。服務器會重新檢查這些信息。如果發現任何異常,服務器會向機器人發送「停止」信號。機器人停下來,重新計算其位置,重新發送信息並等待「去」信號。

此循環示例基於從機器人接收的數據饋送。如果出現問題(例如無線鏈路斷裂,障礙物或失誤),機器人必須停下來以防止誤入歧途或墜落等任何事情。我們不知道哪裏出了問題,或者爲什麼出問題,只是它出錯了(或不是)。 (這實際上是在代碼的另一部分,而不是基於PHP的調試模塊)。

編輯2: 像其他人指出的那樣,似乎是正確的做法是適當提高/處理異常。 由於大家似乎都同意這一點,我不知道誰給予「正確答案」打勾。 我會等幾天,如果沒有問題的話,可以給予更多選票。

+1

對不起,脫離主題,但在迴路中「返回」不是一個好的選擇。 – 2011-06-03 04:21:54

+0

不!如果建設性的話,所有的投入都很好。順便說一句,爲什麼從循環返回不好?轉到會更好嗎? – Tivie 2011-06-03 04:45:18

+1

在你上面的例子中,它永遠不會檢查while()的條件,因爲在do {}中之前都返回了一切。 – 2011-06-03 04:50:53

回答

3

沒有理由避免混合try/catchdo/while

但是您提供的示例在do/while等問題上的問題較少,並且在try/catch塊中吞嚥異常。

捕獲基本的異常類型併吞服它在任何語言,PHP或其他語言中都是不好的做法。最好只捕獲特定的異常類型,並讓其餘部分通過catch塊。例如,如果你正在訪問一個文件,並且發現了異常(如果PHP中有這樣的事情),那就沒問題了。

但是,如果你捕捉到所有的異常類型,那麼你將會看到像OutOfMemoryException這樣的東西。如果你正確地處理了它,並且確保它不會再次拋出,這將會很好。但就你而言,你可能不是「爲那件事情做正確的事情」,所以你應該讓它落空。

你不想吃異常(不記錄它們)的原因是,如果它進入鎖定的生產環境,你將無法調試你的代碼。如果發現異常,那麼用戶只會看到錯誤行爲,並且不能提交給您足夠的信息來調試它的錯誤報告。他們可能會給你重複步驟,但這是相當不可靠的。這對間歇性問題來說也是毫無價值的。

如果你吃了這個例外,你基本上就會拋棄那些用於調試的最有用的數據。

東西,讓這個不太真實:

  • 有時頂級網頁代碼,你會想要趕上例外,記錄它,然後吞下它,因此用戶不會看到它(但回報從函數,所以你不要在一個錯誤的狀態下執行更多的代碼)。這使得用戶看不到有關代碼的信息(堆棧跟蹤)。
  • 如果您正在進行異常處理的語言對異常的支持不足,並且沒有派生異常類型。我對PHP沒有太多瞭解,所以在這種語言中可能會也可能不會。
1

如果要吞下例外,只是報告故障,那麼這是好的。你必須做類似

$failure &= bar(); 

雖然,否則你將失去foo()的失敗條件。

如果您希望能夠對調用堆棧進一步採取行動,那麼最好讓它獨立,或者至少重新拋出它,以便您可以將其捕獲到要處理它的位置。

+0

是的,我簡化了代碼並創建了一些沒有任何意義的東西= P – Tivie 2011-06-03 04:18:39

1

沒有通用的理由,以避免使用try /稱爲裏面做的職責範圍內趕上/ while循環。

取決於你實際上是在做什麼,你有醒目的循環內的異常的選擇內循環,並退出上的錯誤狀態返回,或包裹整個while循環在try/catch塊。

你應該決定如何根據什麼異常意味着你的代碼做任何特殊情況:

  • 可以例外地從收回?
  • 需要採取什麼行動來應對拋出的異常?
  • 在拋出和處理特定異常之後,您的程序應保留在什麼狀態?

在您的示例中,即使foo()生成錯誤,也會執行bar()。這可能是也可能不是你想要的。在循環外捕獲異常不會允許此選項。 此外,如果foo()隨後返回true,則bar()返回false時,循環將不會終止 - 這可能是一個錯誤。捕捉循環外的任何異常意味着循環將在錯誤點處終止。再次,這可能會或可能不會取決於您的應用程序。

此外,不同的異常可能需要以不同的方式處理。重要的是,如果您捕獲基本的異常類型,而不是更具體的派生類型,那麼您將失去執行此操作的能力。捕獲更具體的異常(包括自定義例外)將幫助您:

  • 確保你沒有 誤吞意外 例外,你並不想趕上。
  • 具有由相同的捕獲 塊處理多個不同的錯誤 場景(由投擲相同的自定義 例外爲每個這些錯誤 場景)。
+0

是的,你可能是對的。該代碼基於機器人在地板上沿着一條線並且不斷向服務器提供反饋的RL情況。服務器處理很多信息,例如機器人的絕對位置,相對位置,到目標的距離等等,但僅用於過程檢查。它給機器人的響應實際上是0或1,即繼續或停止。因此,過程中拋出的任何異常都意味着數據不可行和/或不可恢復,並且過程必須重新開始,也就是說,機器人必須「重新思考」他在哪裏以及如何達到目標。 – Tivie 2011-06-03 04:37:47

+0

這段代碼是指文件上傳和流式傳輸。如果由於某種原因切斷了機器人的無線連接,則文件上傳會中斷,導致文件不完整/被破壞。由於數據是即時創建的,無法重新創建,所以我們不能要求「重試」(而且我們也不想要P =),所以我們無法從錯誤中恢復。機器人必須停下來,重新思考並要求允許再次移動。 – Tivie 2011-06-03 04:51:58

+1

是的,但請注意,由於您正在捕獲基本Exception類型(而不是派生類型),因此您可能還會捕獲整個過程無法從中恢復的異常(而不僅僅是當前階段或迭代)。這就是爲什麼它總是能夠更好地捕捉你可以優雅地處理的特定異常,並讓其他人更上一層樓。我對我的答案做了一個小小的修改,強調了這一點。 – Ergwun 2011-06-03 06:29:15