功能Java示例 第5部分–将I / O移到外部
這是稱為“ Functional Java by Example”的系列文章的第5部分。
在上一部分中,我們停止了對文檔的變異,并返回了數據的副本。 現在,我們需要移走一些I / O。
如果您是第一次來,最好是從頭開始閱讀。 它有助于了解我們從何處開始以及如何在整個系列中繼續前進。
這些都是這些部分:
- 第1部分–從命令式到聲明式
- 第2部分–講故事
- 第3部分–不要使用異常來控制流程
- 第4部分–首選不變性
- 第5部分–將I / O移到外部
- 第6部分–用作參數
- 第7部分–將失敗也視為數據
- 第8部分–更多純函數
我將在每篇文章發表時更新鏈接。 如果您通過內容聯合組織來閱讀本文,請查看我博客上的原始文章。
每次代碼也被推送到這個GitHub項目 。
將I / O移到外面
還記得我們以前留下的東西嗎?
class FeedHandler {Webservice webserviceDocumentDb documentDbvoid handle(List<Doc> changes) {changes.findAll { doc -> isImportant(doc) }.each { doc ->createResource(doc).thenAccept { resource ->documentDb.update(setToProcessed(doc, resource))}.exceptionally { e ->documentDb.update(setToFailed(doc, e))}}}private CompletableFuture<Resource> createResource(doc) {webservice.create(doc)}private boolean isImportant(doc) {doc.type == 'important'}private Doc setToProcessed(doc, resource) {doc.copyWith(status: 'processed',apiId: resource.id)}private Doc setToFailed(doc, e) {doc.copyWith(status: 'failed',error: e.message)}}我在本系列的每個部分中發展的示例是某種“提要處理程序”,用于處理文檔。
處理效果如何?
Web服務可以是REST服務(因為我們在談論資源 ),數據庫可以是CouchDB或MongoDB的文檔存儲(因為我們在談論文檔 ),但這并不重要。
重要的是通常在任何系統中都涉及一些I / O(輸入/輸出)。 從文件系統讀取信息,將信息存儲到數據庫中,在Web服務之間通過網絡進行通信。
正如我們在上一期文章中所見,我們希望我們的功能盡可能純凈 ,沒有任何副作用。 不幸的是,真正的系統必須與外界交互才能有意義。
我們還如何獲取輸入到系統中的信息,或向用戶輸出什么呢? I / O的一些示例是:
- 文件系統訪問
- 網絡插座
- HTTP請求
- JDBC操作
- 啟動線程
- 系統時鐘訪問
我們已經通過setToProcessed / setToFailed方法擺脫了對數據庫的訪問,方法是將其上移到調用鏈上一步,但是它仍在FeedHandler 。
我們能做的最好的就是將I / O移到系統外部。
我們可以做的最明顯的改變是完全擺脫數據庫,而只是從handle()返回新的更新文檔。
擺脫數據庫
更改
.thenAccept { resource ->documentDb.update(setToProcessed(doc, resource)) } .exceptionally { e ->documentDb.update(setToFailed(doc, e)) }至
.thenApply { resource ->setToProcessed(doc, resource) } .exceptionally { e ->setToFailed(doc, e) }擺脫documentDb 。
我們只是在通話鏈的更遠處返回所有修改過的文檔。 這就是為什么我們還必須……
…擺脫虛無
從更改返回類型
void handle(...)至
List<Doc> handle(...)因此處理過的文檔會一直返回到外部。
并不是說我們不再與任何數據庫進行任何交互,而是不再需要我們的FeedHandler組件! 通過將任何I / O移至系統的外圍,中間的所有內容都可以盡可能地純凈。
還記得Haskell,這是一種“純”功能語言嗎? 從“ 學到了偉大的Haskell” :
事實證明,Haskell實際上擁有一個非常聰明的系統來處理具有副作用的功能,這些功能將我們程序的純凈部分和不純凈的部分整齊地分開了,這就像在與之交談一樣,可以完成所有骯臟的工作。鍵盤和屏幕。 將這兩個部分分開,我們仍然可以推理我們的純程序,并利用純凈提供的所有功能,例如惰性,健壯性和模塊化,同時與外界進行有效的通信。
當它在90年代被發明時,它引入了IO monad來處理I / O。 任何函數,例如從外部讀取,都必須使用返回類型IO ,該類型實際上是由編譯器檢查的。
這有一些好處,例如Haskell編譯器在重新排序所有非IO代碼以進行優化方面具有一定的自由度。 從純函數和I / O :
因為純函數代碼就像代數,所以編譯器可以將所有非IO函數視為數學方程式。 這有點類似于關系數據庫如何優化查詢。
在Java中,我們沒有針對這些事情的特定編譯器支持,但是有一些事情我們可以照顧好自己。
記住: void是一個沉Kong。 任何返回void方法要么沒有意義,要么具有副作用,例如寫入顯示,網絡,文件或數據庫,即與外部系統的交互。 代替執行I / O作為副作用,而是向調用方返回一個值,以描述與外部系統的交互。
現在就這樣!
翻譯自: https://www.javacodegeeks.com/2018/11/functional-java-example-move-outside.html
總結
以上是生活随笔為你收集整理的功能Java示例 第5部分–将I / O移到外部的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: howmany是什么意思 怎么理解how
- 下一篇: 网工路由基础(3)RIP原理与配置