2012-09-23 47 views
2

我目前在編寫a small argument checking library for Java。檢查被寫在這樣一個流暢的接口方式:參數檢查庫 - 隱式/顯式NULL檢查的參數

Check.that(name).matches("hello .*!").hasLenghtBetween(0, 20); 
Check.that(list).isNullOr().hasSize(0); 
Check.that(args).named("arguments").isNotEmpty(); 

到目前爲止,這些檢查的語義是,他們也隱含斷言參數不爲null。要允許爲空,可以使用第二個示例中的isNullOr()修改器方法。

我想補充的下一件事是檢查反轉這樣的支持:

Check.that(name).not().matches("hello .*!"); 

但現在我覺得默認的NULL的含量操作變得怪異和不直觀。反轉測試的正確方法是現在允許null。要禁止空,一個人必須要明確地預先考慮isNotNull()檢查:

Check.that(name).isNotNull().not().matches("hello .*!"); 

正因爲如此,我的想法改變了語義使NULL的含量總是需要檢查明確。我知道一個項目也是這樣做的:Bean Validation。但缺點是,這可能會使約90%的檢查延長12個字符,因爲無論如何,null通常都是無效的參數。

因此,長話短說:針對隱式空檢查的爭論和反對意見是什麼?也許有其他圖書館或標準可以這樣做或以其他方式?

+0

你有機會看看http://commons.apache.org/lang/api-2.6/org/apache/commons/lang/Validate.html嗎? – Vikdor

+0

是的,他們採取了隱含的策略。但是,這一事實本身並不能幫助我*很多*。 – rolve

回答

1

我想我找到了一個甜蜜的妥協:所有支票隱式空檢查not(),僅反轉實際的檢查和不是空校驗。這樣,我可以寫

Check.that(message).not().containsAny(badWords); 

並假定消息是非空的並且不包含任何不良詞。我認爲這佔用了超過90%的用例。

當然,我還是可以允許空明確寫

Check.that(message).isNullOr().not().containsAny(badWords); 

第二個好處是,這樣的設計分離的其餘檢查,這可能是更直觀的太NULL的含量問題。

1

我會保持API相當簡單,到方法調用順序敏感 - 基本上是一個fluentbuilder模式。要做到這一點,做如下修改:

  • 使其狀態(使用實例,而不是靜態方法)
  • 進行實際檢查的最後一個方法調用

每個方法調用將建立要執行的標準,然後最後執行檢查。

像這樣:

new Check().matches("hello .*!").hasLengthBetween(0, 20).check(name); 

這也將使得Check實例重用 - 這是無狀態(static)版本無法做到的。

此外,如果方法調用順序無關緊要,它完全避免了「邏輯運算符」方法的使用,這隻會導致悲傷,並且您會停止在哪裏?考慮這種荒謬的場景:

new Check().matches("hello .*!").hasLengthBetween(0, 20) 
    .and().openBracket().isLowerCase().or().containsNumbers().closeBracket(); 
+0

謝謝你的回答。但是,我不太明白你的方法的優點。首先,我已經在使用實例('that(...)'返回一個),其次,我也已經在重用這些實例。每個重載的'(...)'方法總是返回相同的對象(在給定的線程中)。 – rolve

+0

是的,但你*開始*要檢查的東西,所以方法調用順序很重要,因爲檢查必須在每次調用時運行。如果你檢查最後一個,你可以使用邏輯,如自動空檢查是否有任何其他方法被調用。即使您將API保留原樣,至少不要提供邏輯運算符。 – Bohemian

+0

我認爲最後要做所有的檢查。但是這種方法存在一個嚴重的問題:如果有人忘記了最後一種方法,則不會發生檢查。這是一個非常難以發現的錯誤,因爲該行看起來非常合理(當然除非該參數未被使用)。 但是,謝謝你的建議。我絕對不會包含像'or()'這樣的二元運算符。但是單獨的not(),僅僅是下一個方法的作用域,似乎並不是一個好主意(如果你不同意,請告訴我)...... – rolve