簡體   English   中英

Java POJO是否應該進行字段驗證並在setter方法中拋出異常?

[英]Should Java POJO have field validation and throw exceptions in setter methods?

假設我們有幾十個代表我的域的java POJO,也就是我系統中的數據,它作為我系統不同層之間的對象流動。 該系統可以是Web應用程序,也可以是簡單的桌面應用程序。 域包含的內容並不重要。

在設計我的系統時,我很困惑我應該放置任何驗證邏輯。 我的POJO(域對象)代表我的數據,這些對象中的一些字段必須符合某些條件,但如果我在我的setter方法中放入了很多驗證邏輯,那么告訴調用客戶端的唯一方法是拋出異常。 如果我不希望系統崩潰,則異常必須是必須捕獲和處理的已檢查異常。 這樣做的結果是,每次我使用setter-methods(甚至構造函數)創建一個新對象時,我都會重新拋出該異常或使用try-catch塊。 在許多setter方法上強制使用try-catch是不對的。

所以問題是我應該把我的驗證邏輯放在哪里,這樣我就不會在我的代碼中混淆大量的樣板try-catch塊和重新拋出。 歡迎最優秀的JAVA字節用戶加入討論。

我已經研究過Google,但沒有找到關於這個主題的具體討論,所以我非常熱情地等待,以便更深入地了解事情應該如何完成。

你說的時候,你可能已經回答了自己的問題

這些對象內的一些字段必須符合某些標准

考慮系統中的不變量總是有幫助的,即您想要不惜一切代價維護的東西或必須始終遵循的規則。
您的POJO是數據對象上此類不變量的“最后一道防線”,因此是一個適當的 - 甚至是必要的 - 放置驗證邏輯的地方。 如果沒有這樣的驗證,對象可能不再代表您域中有意義的內容。

這些系統不變量在您的對象(或方法)與其“客戶端”之間形成契約。 如果某人試圖使用它們(與希望記錄良好的合同)相反,拋出異常是正確的做法,因為客戶有責任正確使用系統的各個部分。

隨着時間的推移,我開始偏向未經檢查的異常,而不是任何違反合同的情況,部分是因為你提到的原因,即避免在任何地方使用 try - catch塊。
Java的標准未經檢查的例外包括:

  • 空指針異常
  • 拋出:IllegalArgumentException
  • IllegalStateException異常
  • UnsupportedOperationException異常

最佳實踐指南是在錯誤被視為可恢復時使用已檢查的異常 ,否則使用未經檢查的異常

Joshua Bloch的第9章“ Effective Java,2nd ed。 ”為這個主題提供了更多的智慧:

  • 第57項:僅在特殊情況下使用例外
  • 項目58:對可恢復條件使用已檢查的異常,對編程錯誤使用運行時異常
  • 第59項:避免不必要地使用已檢查的例外
  • 第60項:贊成使用標准例外

以上都不能阻止您在更高級別使用任何適當的驗證邏輯,尤其是強制執行任何特定於上下文的業務規則或約束。

總而言之,我也不認為有適合所有需求的獨特解決方案,它只取決於您的場景和偏好。

從封裝的角度來看,我認為設置器驗證是正確的方法,因為它是決定所提供信息是否正確並提供可能錯誤的詳細解釋的合理位置。 但是我不確定你的意思是:

如果我不希望系統崩潰,則異常必須是已檢查的異常...

為什么系統會崩潰? 未經檢查的異常可以很好地捕獲,就像已檢查的異常一樣。 您需要弄清楚程序在發生此類事件時的行為方式,以便您可以決定在何處捕獲它們以及執行哪些操作。

Checked vs unchecked長期以來一直以各種方式和信念進行辯論,但我認為沒有理由不拋出未經檢查的異常。 只需創建一個常見的ConfigurationException (或使用已經存在的IllegalArgumentException )或任何漂浮你的船,相應地標記你的方法簽名並添加適當的java文檔,以便任何人調用它們知道會發生什么,並在需要時拋出它。

根據您的對象關系和層次結構,另一個解決方案可能是一些構建器 ,它們在創建實例時運行自定義驗證。 但就像我說的那樣,它實際上取決於場景,並且您可能無法阻止其他人手動實例化並錯誤地填充某些對象。

在某些情況下,解決方案是將所有setter設為私有,並為初始化對象提供單一入口點。 然后,所有驗證和異常處理都在該初始化方法中。
這也確保了不能部分初始化任何對象。
對象狀態更改也可以通過這種方式處理,通過使對象不可變,除非通過構造函數/初始化方法,如果濫用,這可能會變得浪費。

雖然您可以將驗證邏輯放在bean setter方法上,但我發現在實踐中,更明確的關注點分離是將任何復雜的驗證移動到另一個特定於驗證的類。 聽我說。

使用bean驗證很好,但在很多情況下(我確信你現在遇到的),一個簡單的注釋將無法進行足夠的驗證。 像Spring這樣的框架有你可以實現的Validator

分離驗證邏輯有很多好處:

  • 代碼重用。 在某些情況下,一個bean的setter驗證可能與另一個bean的setter驗證相同。 這也促進了更簡潔的單元測試。
  • 在許多情況下,您根本不會處理異常,而是向用戶顯示錯誤消息
  • 您可以在不使用日志記錄語句填充POJO或強制它們實現記錄器的情況下進行適當記錄
  • 代碼更具可讀性,更好地理解意圖

希望有所幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM