2015-12-19 52 views
0

我的整個數據庫層目前都爲我的所有模型返回Future [Option [Model]]。爲什麼要在按ID提取時返回Option [Model]?

我發現它只是使期貨工作更加困難,更重要的是我還沒有遇到一個用例,它甚至有意義返回一個選項。
如果模型沒有被Id找到,我的應用程序基本上應該會崩潰。

我不完全確定爲什麼我選擇了[模型],但什麼被認爲是最佳實踐?

我知道在RubyonRails中,當您通過Id(即Model.find(123))獲取它時,如果找不到它,它將引發異常。

回答

3

在這種情況下我肯定會跟Future[Model]一起去。即使應用不應該「基本崩潰」,Future可能會失敗,這可以很容易地處理。使用Future[Option[...]],在沒有結果的情況下取得成功是有意義的(例如,在數據庫中存在可空關聯的情況下)。

0

閱讀有關使用選項的好處,我想你應該堅持Future[Option[Model]]正是爲了不扔,而不是捕捉異常的原因。如果方法返回類型爲Option[Model],則不能錯過處理模型不在的情況。類型簽名提示可能有沒有什麼可返回的情況。呼叫者必須明確地mapfold而不是Option以擺脫它並且處理內部Model。由於所有異常都未經檢查(並且檢查的異常僅僅是列車殘骸),因此編譯器無法提示您處理異常,所以您可能會在運行時遇到意外。 Scala是一種編譯和靜態類型的語言,使用類型來描述返回數據是一個非常好的主意,因爲編譯器會幫助你把所有東西都搞定。這在Ruby中是不同的!您必須瞭解靜態類型和編譯與運行時錯誤處理的好處。

同樣適用於處理失敗Future S:如果Future始終是成功和失敗的Future唯一表明一些意外的錯誤,從來沒有像普通的東西「的模式沒有發現」,你可以map對他們沒有,如果他們」顯式檢查重新失敗或沒有。

就你而言,Future[Option[Model]爲您提供了更好的錯誤處理和程序流控制。如果你的DAO只是拋出異常,你會得到一個崩潰的應用程序與一些醜陋的堆棧跟蹤錯誤的情況下。但是如果你的DAO返回Future[Option[Model]],來電代碼可能水木清華這樣的:

DAO.findById(id).map { maybeModel: Option[Model] ⇒ 
    maybeModel match { 
    case Some(model) ⇒ processModel(model) 
    case None  ⇒ exitWithError(s"Could not find model with id = $id") 
    } 
} 

(代碼是爲了提高可讀性如此詳細)

上面的代碼爲您提供了在出口點更多的控制權您的應用程序,如果您的需求發生變化,這可能會非常有用,並且如果未找到模型,您就不會崩潰應用程序。例如,您可能會發現所有對exitWithError的呼叫,並將其替換爲logErrorshowErrorMessage種邏輯。如果你遇到異常,這幾乎是不可能的。

另一個例子:假設你有2個DAO方法:findById(id: Long): Future[Option[Model]]countById(id: Long): Future[Int]。他們的類型簽名表明findById可能有沒有任何返回給調用者,這由Option表示。 countById將永遠必須返回東西,這是建議由純Int。在針對此API編碼時,調用者理解這兩種方法的語義。當調用findById時,他們應該考慮2個明確的情況:何時找到模型和何時不是。當致電countById時,只需使用返回的任何值,始終爲Int

希望這可以讓它更清晰:)隨時提出更多問題。

+0

問題在於,處理Future [Option [Mode]]非常複雜,我必須使用地圖然後匹配編寫這麼多的代碼。我在我的應用程序中這麼做很難編寫簡單的代碼。我有很多理解,每個for-compr的開始都有一個對findById的調用。 – Blankman

+0

好吧,如果你分享了一些你的代碼,我可以幫你。您的描述非常含糊。如果你使用'for'解析,你可能不需要'map'。你可以使用'fold'來避免'選項'上的'匹配'。 –

相關問題