2010-08-26 56 views
2

我的代碼庫有很多#if DEBUG/#endif語句,這些語句大多都有斷言類型邏輯,我不敢在生產環境中運行。與#if/#endif相比,條件屬性有什麼缺點?

[Conditional("DEBUG")] 
public void CheckFontSizeMath() 
{ 
    //This check must not block SellSnakeOil() in production, even if it fails. 
    if(perferredSize+increment!=increment+preferredSize) 
    throw new WeAreInAnUnexpectedParallelUniverseException(); 
} 

我會後悔改變所有這些到新的做事方式嗎?

UPDATE:我正在尋找兩種相似但不同的語法樣式的特性之間的區別做斷言。我知道有一個其他方式來演示應用程序工作的世界,我也這樣做。我還沒有準備好完全放棄斷言。

另外我更新了一個現實的僅限調試版本的方案名稱。

+0

你在想什麼「新方法」? – SwDevMan81 2010-08-26 18:37:42

+1

Matthew談論'[Conditional(「DEBUG」)]'。 – Andreas 2010-08-26 18:39:43

+0

更重要的是,什麼是好處? – 2010-08-26 19:04:45

回答

3

這樣做沒有問題。目前更多的方法是使用Code Contracts

+0

我也使用代碼合同,但代碼合同也可以在Release中關閉。如果沒有進行靜態分析檢查(似乎可供支付額外費用的人),代碼合同似乎只是語法糖。我想下一個問題是,如果將所有#if/#endif和[Conditional()]代碼更改爲代碼合同? – MatthewMartin 2010-08-27 13:43:10

+0

我不明白,你想在Release中關閉它,對吧?代碼合同就像機器人,飛行汽車和jetpack,這是未來的人。 – 2010-08-27 13:54:59

+0

我認爲jetpacks是過去,未來是關於磁性投影和被射出大炮。我將要進入階梯營。 – 2010-08-27 14:03:34

2

寫測試!那麼你不必擔心你的代碼正在做一些你在開始進行這些改變時並不期望的事情。

一旦你在測試中得到你的代碼,你可以重構你心中的內容。

沒有測試的代碼,甚至是昨天寫的,都是遺留代碼... 獲取Working Effectively with Legacy Code的副本,這是一本用於管理遺留代碼的出色書籍; 32個評論5星。

+0

這是很好的建議,但與我的問題正交。 – MatthewMartin 2010-08-27 13:28:46

1

您擁有的其他選項是使用Hans建議的代碼合同或使用命名空間System.Diagnostics.Debug中的斷言方法,例如,

Debug.Assert(1 + 1 == 2, "Math went wrong!"); 

構建發佈版本時會自動刪除此檢查。

+0

閱讀本文,http://stackoverflow.com/questions/762299/is-it-worth-using-debug-assert-in-asp-net這種方法似乎存在嚴重的缺點。格式錯誤的web.config會阻止這些運行,並且ASP.NET中失敗的斷言可能表現爲永不返回的請求! – MatthewMartin 2010-08-27 13:46:41

1

的缺點:

  1. 這不是一樣強大堅硬的檢查和異常獨立構建功能配置。考慮到大多數代碼應該在發佈模式下處理錯誤這一事實是一個好主意。

  2. 不同配置之間的行爲可能有所不同。如果你不小心,最終可能會在條件方法中添加一些非調試邏輯或添加副作用,以便生產代碼無法正常工作(基本上與C++中的ASSERT()宏中意外調用方法的方法相同; side效果吸!)這裏最大的問題是例外。條件方法不允許您出於任何原因返回值,以消除一個潛在的錯誤。但是,它們確實允許您拋出異常,這會極大地改變發生錯誤情況時所採用的路徑。這使得事情難以理解和維護。

  3. 在調用站點,調用條件方法並不明顯。你只看到「DoSomething();」。我更喜歡通過一個公約來命名我的條件方法,我知道這是一個有條件的方法;例如DEBUG_SanityCheckBufferContents()。

  4. 如果你沒有#if方法體,你的調試代碼將仍然存在,它可以通過反射和其他方式進行檢查/調用。該方法的IL仍然發射,呼叫站點不是。

  5. 它使單元測試非常困難,因爲配置之間的行爲不同。這與第2點相同,但是我將它作爲一個單獨的點添加,因爲從測試的角度來看它真的很糟糕。大多數開發人員將在簽入之前在調試或發行版中運行測試,但不能同時運行兩者。我們的CI運行了兩套測試,所以在通過所有測試之後檢查某些內容,只是發現你打破了調試配置,但是因爲運行了發佈版本(或反之亦然)而通過了測試,所以很煩人。

總之我的經驗法則是:

  • 不想硬檢查&異常單元測試。使用條件的方法,其中這是不可能的(例如性能是至關重要的檢查)
  • 名稱條件方法顯然
  • 附註#IF出方法體的代碼
  • 非常謹慎改變在條件方法程序控制流的(我個人更喜歡使用Debug.Assert而不是使用條件方法時的異常,但我已經看到大量其他程序員使用異常,所以這可能需要辯論)
+0

#4解決了這個問題,其他問題都是#if/#endif和[Conditional()]屬性的缺點。但#4,似乎隻影響裝配尺寸。 – MatthewMartin 2010-08-27 13:40:57

+0

它不僅影響裝配尺寸。條件方法代碼仍然存在,可以檢查/調用。即如果你不想讓人們在周圍徘徊,就不要在條件方法中加入任何東西。 – 2010-08-27 20:41:32