2009-10-30 57 views
3

即使在我的程序中沒有可以合理輸入錯誤數據的地方,我總是有習慣總是驗證屬性設置器是否對不良數據有效。我的質量保證人員不希望我拋出異常,除非我能解釋他們會在何處發生。我應該驗證所有屬性嗎?我可以指出這個標準嗎?面向對象設計的問題 - 驗證屬性

例子:

public void setName(String newName){ 
    if (newName == null){ 
     throw new IllegalArgumentException("Name cannot be null"); 
    } 
    name = newName; 
} 

... 

//Only call to setName(String) 
t.setName("Jim"); 
+1

看起來您的質量檢查人員沒有針對這些支票投放分支獲得單元測試覆蓋率。你應該告訴他們停止懶惰,並且將其包含在測試中,因爲它應該是。 – 2009-10-30 19:59:59

+0

單元測試?我們不需要單元測試......(我知道,我知道,但我不能改變一切......) – 2009-10-30 20:03:27

回答

4

你執行你的方法的前提條件,這是其合同的重要組成部分。這樣做沒有問題,它也可以作爲自我記錄代碼(如果我閱讀了你的方法代碼,我立即明白我不應該傳遞給它的代碼),儘管assert可能更適用於此。

1

你做的不錯! 無論是setter還是函數 - 總是驗證並拋出有意義的異常。你永遠不知道什麼時候需要它,你會...

0

這是一個折衷。這是編寫,審查和維護的更多代碼,但如果某個空名稱能夠通過,您可能會發現更快的問題。

我傾向於擁有它,因爲最終你會發現你確實需要它。

我曾經有實用程序類來保持代碼最小。因此,而不是

if (name == null) { throw new ... 

你可以有

Util.assertNotNull(name) 

那麼Java添加斷言的語言,你可以更直接地做到這一點。如果你想要關掉它。

2

在這些瘋狂不可能的情況下,我個人更喜歡使用斷言,只是爲了避免難以閱讀的代碼,但要清楚的是假設在函數的算法正在取得進展。

但是,當然,這在很大程度上是一個主觀判斷的是,必須根據具體情況逐案基礎上做出。你可以看到它(並且我已經看到它)完全失去控制 - 直到一個簡單的函數變成了幾乎從未評估爲真的if語句的纏結。

0

在我看來做得很好。對於空值拋出IllegalArgumentException。對於其他類型的驗證,您應該考慮使用與您的域對象相關的自定義例外層次結構。

1

一般來說,我不贊成這種做法。這並不是說執行驗證是不好的,而是像簡單的制定者那樣,它往往比它在保護漏洞方面的價值更爲混亂。我更喜歡使用單元測試來確保沒有錯誤。

0

我不知道有任何文件標準說'驗證所有用戶輸入',但這是一個非常好的主意。在該程序的當前版本中,可能無法使用無效數據訪問此特定屬性,但這不會阻止它在未來發生。維護過程中會發生各種有趣的事情。哎,你永遠不知道什麼時候有人會在不經過它之前驗證數據的另一個應用程序中重用的類。

1

嗯,這是一段時間以來這個問題被張貼,但我想給一個不同的角度對這個話題。

使用你發佈的具體例子,恕我直言,你應該做驗證,但以不同的方式。

實現驗證的關鍵在於問題本身。想想看:你在處理的是名字,而不是字符串。 字符串是非空名稱。我們還可以考慮使字符串成爲名稱的其他特徵:不能爲空也不能包含空格。

假設您需要添加這些驗證規則:如果您堅持使用您的方法,您會像@SingleShot所說的那樣結束混亂。

另外,如果多個域對象有一個setName setter,你會怎麼做? 即使您使用助手類作爲@dave,代碼仍會被複制:調用助手實例。

現在,想一想:如果您在setName方法中能夠接收到的所有參數都有效,該怎麼辦?當然不需要驗證。 我聽起來過於樂觀,但可以做到。

記住你正在處理的名稱,所以爲什麼不建模名稱的概念? 這裏的香草,虛擬實現,以顯示想法:

public class Name 

    public static Name From(String value) { 
    if (string.IsNullOrEmpty(value)) throw new ... 
    if (value.contains(' ')) throw new ... 

    return new Name(value); 
    } 

    private Name(string value) { 
    this.value = value; 
    } 

    // other Name stuff goes here... 
} 

因爲驗證在制定的過程中發生的事情,你只能得到有效的名稱實例。無法從「無效」字符串創建名稱實例。 不僅驗證代碼已經集中,而且在對它們有意義的上下文中引發異常(創建Name實例)。

您可以閱讀Hernan Wilkinson的「巴塔哥尼亞背後的設計原理」中的偉大設計原則(該名稱示例源自它)。請務必檢查ESUG 2010 Videopresentation slides

最後,我想你可能會發現Jim Shore的文章"Fail Fast"有趣。