2010-07-15 50 views
10

我經常遇到某種情況可能出現問題的情況,但由於例外情況並非如此,因此使用異常是不對的。有些事情可能會出錯,但它並不是一個例外

例如:

我在設計一個壟斷遊戲。班級有一個方法buyHouse和一個計算剩餘房屋數量的字段(有32個房屋在壟斷中)。有可能出錯的是一個玩家在剩下0時買房子。我應該如何處理這個問題。這是我能想出的3種方法。

1. public void buyHouse(Player player, PropertyValue propertyValue) 
{ 
    if(houseCount < 0) throw new someException; 
    .... 
    //Not really an exceptional situation 
} 

2. public boolean buyHouse(Player player, PropertyValue propertyValue) 
{ 
    if(houseCount < 0) return false; 
    .... 
    //This I think is the most normal approach but changing something 
    //and returning if it was a success seems bad practice to me. 
} 

3. public boolean housesLeft() 
{ 
    if(houseCount > 0) return true; 

    return false; 

    //Introducing a new method. But now I expect the client to call this method 
    //first before calling buyHouse(). 
} 

你會怎麼做?

+0

而不是如果(東西是真的)返回true;返回false;我寧願做最後的布爾retVal; retVal = houseCount> 0;返回(retVal); – TofuBeer 2010-07-15 19:28:49

回答

12

我會一起做3和1。 API的正確用法是在購買之前檢查是否還有房屋。但是,如果開發人員忘記了這麼做,那就拋出一個運行時異常。

如果這是一個多線程的情況(許多人同時購買房屋),它變得更加複雜。在這種情況下,我確實會考慮檢查異常,如果不是tryToBuyAHouse方法返回一個布爾值,而是buyHouse方法的運行時異常。

+2

我也會這麼說。我認爲IllegalStateException是適當的。 – 2010-07-15 02:05:36

+0

謝謝 - 這似乎是正確的選擇。 – 2010-07-15 11:56:23

4

我覺得「例外」的意思是相當主觀的。這意味着任何你想要的意思。您正在設計該功能的界面,您可以決定什麼是特殊的,哪些不是。

如果您不希望houseCount爲< = 0時調用buyHouse,那麼這裏有個例外。即使你確實期望它被調用,你也可以在調用者中捕獲異常來處理這種情況。

2

(1)或(2)是可以接受的,取決於您是否認爲「無房買」的例行結果或特殊情況。

(3)是一個壞主意,有以下幾個原因:

  • 它打破封裝(客戶端必須知道太多關於銀行內部)
  • 你還是要檢查錯誤做(1)或(2)的情況下,客戶砸了
  • 它在多線程情況下
+0

我沒有看到2與3不同,只是更糟 - 如果你忘記檢查,你可以認爲你買了房子,當你沒有。 – Yishai 2010-07-15 01:31:23

+1

我不認爲期望客戶知道並按照遊戲規則進行遊戲並不合適。 – 2010-07-15 02:10:03

1

我會做這樣的事情是有問題的:

public boolean BuyHouse(Player player, PropertyValue propertyValue) { 
     // Get houseCount 
     if(houseCount <= 0) { 
     // Log this to your message queue that you want to show 
     // to the user (if it has a UI) 
     return false; 
     } 
     // Do other stuff if houses are left 
} 

PS:我不熟悉Java,我使用C#

1

這個問題是很難沒有這些實體有-一個房子的情況下回答。從一般的設計角度來看,(1)和(2)之間的調用者之間語義上的差異很小 - 都是嘗試和檢查 - 但是你認爲(1)應該避開完全可預期的狀態。

3

如果連續32次按預期工作,然後無法按預期運行,我認爲如果它是一個孤立的情況,可以證明它是一個例外條件。

考慮到你描述的情況,我認爲使用例外是不合適的,因爲一旦售出32套房子,銀行將繼續退出(這是新的「正常」狀態),而異常處理實際上是與正常處理相比,Java非常慢。

你可以做的一件事是更真實地反映實際的互動。在大富翁中,銀行家只會告訴你,如果沒有剩下的話,你就不能買房。

這種潛在的模型如下:

public House buy(Player player, PropertyValue propertyValue) { 
    House propertyHouse = null; 
    if (houseCount > 0) { 
    propertyHouse = new House(player, propertyValue); 
    houseCount--; 
    } 

    return propertyHouse; 
} 

這也將允許您添加行爲,房屋目標,並請求/買房子多了幾分自然的流動。如果沒有可用的房屋,你不會得到一個。

+0

我認爲這是正確的方向,但我寧願使用Option類型(請參閱http://functionaljava.org)來強制您檢查結果,避免NPE – Landei 2010-07-15 08:52:14

+0

這是一個有趣的方向,我可以看到一些優勢那裏。你有沒有在日常編程中看到過這種範式的重要用途,或者這是更多的學術/研究工具嗎? – mlschechter 2010-07-17 01:27:36

1

你決定的規則在這裏爲用戶&例外誰使用您的API /方法:

housesLeft()可以稱得上檢查 留下的房屋數量 buyHouse()被調用之前。撥打 buyHouse()只要 房屋剩下的數量爲零就是一個例外。

它與在訪問某個數組元素之前進行檢查類似,您在嘗試訪問它之前檢查數組長度,否則將出現異常。

所以它應該是這樣的:

if (housesLeft() > 0) buyHouse(...); 

類似

for (int i=0; i < arrayList.length; i++) System.out.println(arrayList[i]); 
+1

這種模式很容易出現多線程問題。 – samitgaur 2010-07-15 01:38:49

+0

@samG:是的,它很簡單,但可以與其他線程相關的模式結合使用。我認爲多線程在這裏並不是bobjink關心的問題。 – ttchong 2010-07-15 03:32:41

+0

我覺得易has在多線程相關案例上面發佈了一個很好的建議。 – ttchong 2010-07-15 03:36:25

2

其他幾個選項:

  • 你的方法可能會接受一些房屋要求的參數,並檢查玩家的可用餘額和麻木後返回實際購買的房屋數量呃可用的房屋。返回零將是一個完全可以接受的可能性。當然,你依靠調用代碼來檢查實際返回的房子數量。 (這是關於返回布爾值的變體,當然,真/假指示購買的房屋爲1或0)

  • 該主題的變體將返回與房屋成功數目對應的House對象的集合購買,這可能是一個空的集合。大概調用代碼將無法表現,就好像它有更多House對象比你給它。 (這是返回House對象的變體,其中null表示沒有購買房屋,並且對象代表1個房屋,並且通常是將空集合引用爲空引用的一般編碼方法的一部分)

  • 您的方法可能會返回HousePurchaseTransaction對象,該對象本身可查詢以確定事務的成功或失敗,實際成本等。

  • 關於這一主題的更豐富的變化可能使HousePurchaseTransaction抽象,並得出兩個子類:SuccessfulHousePurchaseFailedHousePurchase,所以你可以在不同的行爲與這兩個結果的條件相關聯。將房子安裝到街道上可能需要您傳遞「SuccessfulHousePurchase」對象才能繼續。 (這避免返回一個空爲後一空引用錯誤的根本的危險,並且是在空對象模式的變體)

在現實中,我懷疑採取將取決於您結束在那裏的辦法分配責任將房子安置在董事會上,升級到酒店,執行平等規則,限制在特定街道上購買房屋的數量等等。

+1

一些很好的建議,我沒有想到:) – 2010-07-15 11:53:58

5

這與從一個空棧中彈出一個項目的想法非常相似......這是例外。你正在做一些應該失敗的事情。

考慮一些特殊情況,例如,如果您想通知程序員出現問題,並且您不希望他們忽略它。由於程序員可以忽略它,因此使用簡單的布爾返回值不是「正確的」。還有一個想法,那就是應該調用一個方法來檢查是否有可用的房屋,這是一個好主意。但請記住,程序員在某些情況下會忘記調用它。在這種情況下,這種例外是爲了提醒他們,在獲得房屋之前,他們需要調用該方法來檢查房屋是否存在。

因此,我會提供方法來檢查是否有房屋,並期望人們會調用它並使用真/假返回值。如果他們沒有調用該方法,或者忽略返回值,我會拋出一個異常,以便遊戲不會處於不良狀態。

1

記住,你可以使用

return houseCount > 0; 

而不是

if(houseCount > 0) return true; 

return false; 
+0

我知道,但我更喜歡我的方式:) – 2010-07-15 16:29:24

相關問題