日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

java 示例_功能Java示例 第4部分–首选不变性

發布時間:2023/12/3 java 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java 示例_功能Java示例 第4部分–首选不变性 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

java 示例

這是稱為“ Functional Java by Example”的系列文章的第4部分。

在上一部分中,我們討論了一些副作用,并且我想進一步詳細說明如何通過將不可變性引入代碼中來防止意外地對數據進行操作。

如果您是第一次來,最好是從頭開始閱讀。

它有助于了解我們從何處開始以及如何在整個系列中繼續前進。

這些都是這些部分:

  • 第1部分–從命令式到聲明式
  • 第2部分–講故事
  • 第3部分–不要使用異常來控制流程
  • 第4部分–首選不變性
  • 第5部分–將I / O移到外部
  • 第6部分–用作參數
  • 第7部分–將失敗也視為數據
  • 第8部分–更多純函數

我將在每篇文章發表時更新鏈接。 如果您通過內容聯合組織來閱讀本文,請查看我博客上的原始文章。

每次代碼也被推送到這個GitHub項目 。

純功能

關于我們之前討論的內容的小結。

  • 函數式編程鼓勵使用無副作用的方法(或:函數),以使代碼更易理解且易于推理 。 如果某個方法僅接受某些輸入并每次都返回相同的輸出(這使其成為一個純函數),則各種優化都可以在后臺進行,例如通過編譯器或緩存,并行化等。
  • 我們可以再次用純函數的(計算出的)值代替純函數,這稱為參考透明度 。

這是上一部分重構后當前的內容:

class FeedHandler {Webservice webserviceDocumentDb documentDbvoid handle(List<Doc> changes) {changes.findAll { doc -> isImportant(doc) }.each { doc ->createResource(doc).thenAccept { resource ->updateToProcessed(doc, resource)}.exceptionally { e ->updateToFailed(doc, e)}}}private CompletableFuture<Resource> createResource(doc) {webservice.create(doc)}private boolean isImportant(doc) {doc.type == 'important'}private void updateToProcessed(doc, resource) {doc.apiId = resource.iddoc.status = 'processed'documentDb.update(doc)}private void updateToFailed(doc, e) {doc.status = 'failed'doc.error = e.messagedocumentDb.update(doc)}}

我們的updateToProcessed和updateToFailed是“不純的”-它們都將更新現有文檔in 。 正如你可以通過它們的返回類型,見void ,在Java中,這表示:沒有出來 。 下沉Kong。

private void updateToProcessed(doc, resource) {doc.apiId = resource.iddoc.status = 'processed'documentDb.update(doc) }private void updateToFailed(doc, e) {doc.status = 'failed'doc.error = e.messagedocumentDb.update(doc) }

這些類型的方法都圍繞您的典型代碼庫。 因此,隨著代碼庫的增長,在將數據傳遞給這些方法之一后,往往很難對數據的狀態進行推理。

請考慮以下情形:

def newDocs = [new Doc(title: 'Groovy', status: 'new'),new Doc(title: 'Ruby', status: 'new') ]feedHandler.handle(newDocs)println "My new docs: " + newDocs // My new docs: // [Doc(title: Groovy, status: processed), // Doc(title: Ruby, status: processed)] // WHAT? My new documents aren't that 'new' anymore

罪魁禍首一直在破壞我文件的地位; 首先,它們是“新的”,其次不是。 那不行! 一定是該死的FeedHandler。 誰創作的東西? 為什么會觸碰我的數據?

考慮另一種情況,即有多個參與者處理您的業務。

def favoriteDocs = [new Doc(title: 'Haskell'),new Doc(title: 'OCaml'),new Doc(title: 'Scala') ]archiver.backup(favoriteDocs)feedHandler.handle(favoriteDocs)mangleService.update(favoriteDocs)userDao.merge(favoriteDocs, true)println "My favorites: " + favoriteDocs // My favorites: [] // WHAT? Empty collection? Where are my favorites????

我們從一組項目開始,然后通過4種方法發現我們的數據不見了。

在每個人都可以改變任何事物的世界中,很難在任何給定時間推斷任何狀態。

它本身甚至還不是“全局狀態”,任何擁有(引用到)數據的人都可以清除傳遞給方法的集合,并可以更改變量。

首選不變性

那是什么 如果對象在實例化后不更改其狀態,則該對象是不可變的。

看起來合理吧?

圖片來源: 應對并適應持續變化

關于如何使用您的特定語言進行操作,這里有大量資源。 例如,Java默認不支持不變性。 我必須做些工作。

如果有第三方在處理過程中發生問題并更改數據(例如清除我的收藏夾),則可以通過將我的收藏夾傳遞到不可修改的包裝中來快速清除麻煩制造者,例如

def data = [... ]// somewhere inside 3rd-party code data.clear()// back in my code: // data is empty *snif*

預防故障:

def data = Collections.unmodifiableCollection([])// somewhere inside 3rd-party code data.clear() // HAHAA, throws UnsupportedOperationException

在您自己的代碼庫中,我們可以通過最小化可變數據結構來防止意外的副作用(例如,我的數據在某處更改)。

在大多數FP語言中,例如Haskell , OCaml和Scala ,默認情況下 ,語言本身會促進不變性 。 雖然不是真正的FP語言,但使用ES6編寫不可變JavaScript也趨于成為一種好習慣。

首先只讀

使用到目前為止所學的原理,并努力防止意外的副作用,我們希望確保實例化實例后, 不能對Doc類進行任何更改 ,甚至不能對updateToProcessed / updateToFailed方法進行更改

這是我們當前的課程:

class Doc {String title, type, apiId, status, error }

Groovy不需要進行使Java類變為不可變的所有手動工作,而是借助Immutable -annotation進行了搶救。

當放置在類上時,Groovy編譯器進行了一些增強,因此創建后再也沒有人可以更新其狀態。

@Immutable class Doc {String title, type, apiId, status, error }

該對象實際上變為“只讀”,并且任何嘗試更新屬性的操作都將導致恰當命名的ReadOnlyPropertyException

private void updateToProcessed(doc, resource) {doc.apiId = resource.id // BOOM! // throws groovy.lang.ReadOnlyPropertyException: // Cannot set readonly property: apiId... }private void updateToFailed(doc, e) {doc.status = 'failed' // BOOM! // throws groovy.lang.ReadOnlyPropertyException: // Cannot set readonly property: status... }

但是,等等,這是否意味著updateToProcessed / updateToFailed方法實際上將無法將文檔status更新為“已處理”或“失敗”?

吉普,這就是不變性帶給我們的。 如何修復邏輯?

復制第二

Haskell關于“不可變數據”的指南為我們提供了有關如何進行操作的建議:

純功能程序通常在不可變數據上運行。 代替更改現有值,而是創建更改的副本并保留原始副本。 由于結構的未更改部分無法修改,因此它們通常可以在舊副本和新副本之間共享,從而節省了內存。

答:我們克隆它!

我們沒有更新的原始數據,我們應該做的一個副本-原來不是我們的,應保持不變。 我們的Immutable -annotation支持一個名為copyWith的參數。

@Immutable(copyWith = true) class Doc {String title, type, apiId, status, error }

因此,我們將更改方法以制作狀態已更改 (以及api id和錯誤消息) 的原始副本,并返回此副本 。

(總是返回Groovy方法中的最后一條語句,不需要顯式的return關鍵字)

private Doc setToProcessed(doc, resource) {doc.copyWith(status: 'processed',apiId: resource.id) }private Doc setToFailed(doc, e) {doc.copyWith(status: 'failed',error: e.message) }

數據庫邏輯也已上移,將返回的副本存儲起來。

我們已經控制了我們的狀態!

現在就這樣

如果您以Java程序員的身份擔心過多的對象實例化對性能的影響,請在此處發表一篇令人放心的文章 。

作為參考,這是重構代碼的完整版本。

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)}}

翻譯自: https://www.javacodegeeks.com/2018/06/functional-java-part-4-immutability.html

java 示例

總結

以上是生活随笔為你收集整理的java 示例_功能Java示例 第4部分–首选不变性的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。