C#函式式編程:編寫更優質的C#代碼

C#函式式編程:編寫更優質的C#代碼

《C#函式式編程:編寫更優質的C#代碼》是2019年1月清華大學出版社出版的圖書,作者是[美] 恩里科·博南諾(Enrico Buonanno) 。

基本介紹

  • 中文名:C#函式式編程:編寫更優質的C#代碼
  • 作者:[美] 恩里科·博南諾(Enrico Buonanno)
  • 出版社:清華大學出版社
  • 出版時間:2019年1月
  • 定價:98 元
  • ISBN:9787302510550
內容簡介,圖書目錄,

內容簡介

函式式編程將改變你思考代碼的方式!利用FP技術,C#開發人員可極大地提升狀態管理、並發處理和事件處理能力,並更好地長期維護代碼。C#提供了靈活性,使你能充分利用函式式技術的優勢。《C#函式式編程 編寫更優質的C#代碼》從全新視角賦予你強大力量。
《C#函式式編程 編寫更優質的C#代碼》引導你在C#語言中使用函式式思想來解決現實問題;首先介紹函式式編程的原理,分析如何藉助C#語言特性實現函式式編程,然後在多個緊貼實用的示例的引導下,講述函式組合、數據流編程、不可變數據結構以及使用LINQ構建單子組合等主題。

圖書目錄

第Ⅰ部分 核心概念
第1章 介紹函式式編程 3
1.1 什麼是函式式編程 4
1.1.1 函式作為第一類值 4
1.1.2 避免狀態突變 4
1.1.3 編寫具有強力保證的程式 5
1.2 C#的函式式語言 8
1.2.1 LINQ的函式式性質 9
1.2.2 C# 6和C# 7中的函式式特性 10
1.2.3 未來的C#將更趨函式化 13
1.3 函式思維 13
1.3.1 映射函式 13
1.3.2 在C#中表示函式 14
1.4 高階函式 18
1.4.1 依賴於其他函式的函式 18
1.4.2 適配器函式 20
1.4.3 創建其他函式的函式 20
1.5 使用HOF避免重複 21
1.5.1 將安裝和拆卸封裝到HOF中 23
1.5.2 將using語句轉換為HOF 24
1.5.3 HOF的權衡 25
1.6 函式式編程的好處 27
練習 27
小結 28
第2章 為什麼函式純潔性很重要 29
2.1 什麼是函式的純潔性 29
2.1.1 純潔性和副作用 30
2.1.2 管理副作用的策略 31
2.2 純潔性和並發性 33
2.2.1 純函式可良好地並行化 34
2.2.2 並行化不純函式 35
2.2.3 避免狀態的突變 36
2.3 純潔性和可測性 38
2.3.1 實踐:一個驗證場景 39
2.3.2 在測試中引入不純函式 40
2.3.3 為什麼很難測試不純函式 42
2.3.4 參數化單元測試 43
2.3.5 避免標頭接口 44
2.4 純潔性和計算的發展 47
練習 47
小結 48
第3章 設計函式簽名和類型 49
3.1 函式簽名設計 49
3.1.1 箭頭符號 50
3.1.2 簽名的信息量有多大 51
3.2 使用數據對象捕獲數據 52
3.2.1 原始類型通常不夠具體 53
3.2.2 使用自定義類型約束輸入 53
3.2.3 編寫“誠實的”函式 55
3.2.4 使用元組和對象來組合值 56
3.3 使用Unit為數據缺失建模 58
3.3.1 為什麼void不理想 58
3.3.2 使用Unit彌合Action和Func之間的差異 59
3.4 使用Option為數據可能缺失建模 61
3.4.1 你每天都在使用糟糕的API 61
3.4.2 Option類型的介紹 62
3.4.3 實現Option 65
3.4.4 通過使用Option而不是null來獲得健壯性 68
3.4.5 Option作為偏函式的自然結果類型 69
練習 73
小結 74
第4章 函式式編程中的模式 77
4.1 將函式套用於結構的內 部值 77
4.1.1 將函式映射到序列上 77
4.1.2 將函式映射到Option 79
4.1.3 Option是如何提高抽象層級的 81
4.1.4 函子 82
4.2 使用ForEach執行副作用 83
4.3 使用Bind來連結函式 85
4.3.1 將返回Option的函式結合起來 85
4.3.2 使用Bind平鋪嵌套列表 87
4.3.3 實際上,這被稱為單子 88
4.3.4 Return函式 88
4.3.5 函子和單子之間的關係 89
4.4 使用Where過濾值 90
4.5 使用Bind結合Option和IEnumerable 91
4.6 在不同抽象層級上編碼 92
4.6.1 常規值與高級值 93
4.6.2 跨越抽象層級 94
4.6.3 重新審視Map與Bind 95
4.6.4 在正確的抽象層級上
工作 96
練習 96
小結 97
第5章 使用函式組合設計程式 99
5.1 函式組合 99
5.1.1 複習函式組合 100
5.1.2 方法鏈 101
5.1.3 高級值界域中的組合 101
5.2 從數據流的角度進行 思考 102
5.2.1 使用LINQ的可組合
API 102
5.2.2 編寫可組合性更好的函式 103
5.3 工作流編程 105
5.3.1 關於驗證的一個簡單
工作流 106
5.3.2 以數據流的思想進行重構 107
5.3.3 組合帶來了更大的靈活性 108
5.4 介紹函式式領域建模 109
5.5 端到端的伺服器端 工作流 110
5.5.1 表達式與語句 112
5.5.2 聲明式與命令式 112
5.5.3 函式式分層 113
練習 115
小結 115
第Ⅱ部分 函式式風格
第6章 函式式錯誤處理 119
6.1 表示輸出的更安全方式 120
6.1.1 使用Either捕獲錯誤細節 120
6.1.2 處理Either的核心函式 123
6.1.3 比較Option和Either 124
6.2 連結操作可能失敗 125
6.3 驗證:Either的一個完美用例 127
6.3.1 為錯誤選擇合適的表示法 128
6.3.2 定義一個基於Either的API 129
6.3.3 添加驗證邏輯 130
6.4 將輸出提供給客戶端應用程式 131
6.4.1 公開一個類似Option的接口 132
6.4.2 公開一個類似Either的接口 134
6.4.3 返回一個DTO結果 134
6.5 Either的變體 136
6.5.1 在不同的錯誤表示之間進行改變 136
6.5.2 Either的特定版本 137
6.5.3 重構Validation和Exceptional 138
6.5.4 保留異常 141
練習 142
小結 142
第7章 用函式構造一個應用程式 145
7.1 偏函式套用:逐個提供參數 146
7.1.1 手動啟用偏函式套用 147
7.1.2 歸納偏函式套用 148
7.1.3 參數的順序問題 150
7.2 克服方法解析的怪癖 150
7.3 柯里化函式:最佳化偏函式套用 152
7.4 創建一個友好的偏函式套用API 155
7.4.1 可文檔化的類型 156
7.4.2 具化數據訪問函式 157
7.5 應用程式的模組化及
組合 159
7.5.1 OOP中的模組化 160
7.5.2 FP中的模組化 162
7.5.3 比較兩種方法 164
7.5.4 組合應用程式 165
7.6 將列表壓縮為單個值 166
7.6.1 LINQ的Aggregate方法 166
7.6.2 聚合驗證結果 168
7.6.3 收穫驗證錯誤 169
練習 170
小結 171
第8章 有效地處理多參函式 173
8.1 高級界域中的函式應用程式 174
8.1.1 理解套用式 176
8.1.2 提升函式 177
8.1.3 介紹基於屬性的測試 179
8.2 函子、套用式、單子 181
8.3 單子定律 182
8.3.1 右恆等元 183
8.3.2 左恆等元 183
8.3.3 結合律 184
8.3.4 對多參函式使用Bind 185
8.4 通過對任何單子使用LINQ來提高可讀性 186
8.4.1 對任意函子使用LINQ 186
8.4.2 對任意單子使用LINQ 188
8.4.3 let、where及其他LINQ子句 191
8.5 何時使用Bind或Apply 192
8.5.1 具有智慧型構造函式的驗證 192
8.5.2 使用套用式流來收集錯誤 194
8.5.3 使用單子流來快速失敗 195
練習 196
小結 196
第9章 關於數據的函式式思考 199
9.1 狀態突變的陷阱 200
9.2 理解狀態、標識及變化 202
9.2.1 有些事物永遠不會變化 203
9.2.2 表示非突變的變化 205
9.3 強制不可變性 207
9.3.1 永遠不可變 209
9.3.2 無樣板代碼的拷貝方法的可行性 210
9.3.3 利用F#處理數據類型 212
9.3.4 比較不變性的策略:一場醜陋的比賽 213
9.4 函式式數據結構簡介 214
9.4.1 經典的函式式鍊表 215
9.4.2 二叉樹 219
練習 223
小結 224
第10章 事件溯源:持久化的函式 式方法 225
10.1 關於數據存儲的函式式思考 226
10.1.1 為什麼數據存儲只能追加 226
10.1.2 放鬆,並忘卻存儲狀態 227
10.2 事件溯源的基礎知識 228
10.2.1 表示事件 228
10.2.2 持久化事件 229
10.2.3 表示狀態 230
10.2.4 一個模式匹配的插曲 231
10.2.5 表示狀態轉換 234
10.2.6 從過去的事件中重建當前狀態 235
10.3 事件溯源系統的架構 236
10.3.1 處理命令 237
10.3.2 處理事件 240
10.3.3 添加驗證 241
10.3.4 根據事件創建數據的視圖 243
10.4 比較不可變存儲的不同方法 246
10.4.1 Datomic與
Event Store 247
10.4.2 你的領域是否受事件驅動? 247
小結 248
第Ⅲ部分 高級技術
第11章 惰性計算、延續以及單子組合之美 251
11.1 惰性的優點 251
11.1.1 用於處理Option的惰性API 252
11.1.2 組合惰性計算 254
11.2 使用Try進行異常處理 256
11.2.1 表示可能失敗的計算 257
11.2.2 從JSON對象中安全地提取信息 257
11.2.3 組合可能失敗的計算 259
11.2.4 單子組合:是什麼意思呢? 260
11.3 為資料庫訪問創建中間件管道 261
11.3.1 組合執行安裝/拆卸的函式 261
11.3.2 逃離厄運金字塔的秘方 263
11.3.3 捕獲中間件函式的本質 263
11.3.4 實現中間件的查詢模式 265
11.3.5 添加計時操作的中間件 268
11.3.6 添加管理資料庫事務的中間件 269
小結 271
第12章 有狀態的程式和計算 273
12.1 管理狀態的程式 274
12.1.1 維護所檢索資源的快取 275
12.1.2 重構可測試性和錯誤處理 277
12.1.3 有狀態的計算 278
12.2 一種用於生成隨機數據的語言 279
12.2.1 生成隨機整數 280
12.2.2 生成其他基元 281
12.2.3 生成複雜的結構 282
12.3 有狀態計算的通用模式 284
小結 287
第13章 使用異步計算 289
13.1 異步計算 290
13.1.1 對異步的需要 290
13.1.2 用Task表示異步操作 291
13.1.3 Task作為一個將來值的容器 292
13.1.4 處理失敗 294
13.1.5 一個用於貨幣轉換的HTTP API 296
13.1.6 如果失敗,請再試幾次 297
13.1.7 並行運行異步操作 297
13.2 遍歷:處理高級值列表 299
13.2.1 使用單子的Traverse來驗證值列表 301
13.2.2 使用套用式Traverse來收集驗證錯誤 302
13.2.3 將多個驗證器套用於單個值 304
13.2.4 將Traverse與Task一起使用以等待多個結果 305
13.2.5 為單值結構定義Traverse 306
13.3 結合異步和驗證(或其他任何兩個單子效果) 308
13.3.1 堆疊單子的問題 308
13.3.2 減少效果的數量 310
13.3.3 具有一個單子堆疊的LINQ表達式 311
小結 312
第14章 數據流和Reactive Extensions 315
14.1 用IObservable表示數據流 316
14.1.1 時間上的一個序列的值 316
14.1.2 訂閱IObservable 317
14.2 創建IObservable 318
14.2.1 創建一個定時器 319
14.2.2 使用Subject來告知IObservable應何時發出信號 320
14.2.3 從基於回調的訂閱中創建IObservable 320
14.2.4 由更簡單的結構創建IObservable 321
14.3 轉換和結合數據流 323
14.3.1 流的轉換 323
14.3.2 結合和劃分流 325
14.3.3 使用IObservable進行錯誤處理 327
14.3.4 融會貫通 329
14.4 實現貫穿多個事件的邏輯 330
14.4.1 檢測按鍵順序 330
14.4.2 對事件源作出反應 333
14.4.3 通知賬戶何時透支 335
14.5 應該何時使用IObservable? 337
小結 338
第15章 並發訊息傳遞 339
15.1 對共享可變狀態的需要 339
15.2 理解並發訊息傳遞 341
15.2.1 在C#中實現代理 343
15.2.2 開始使用代理 344
15.2.3 使用代理處理並發請求 346
15.2.4 代理與角色 349
15.3 “函式式API”與“基於代理的實現” 350
15.3.1 代理作為實現細節 351
15.3.2 將代理隱藏於常規API的背後 352
15.4 LOB應用程式中的並發訊息傳遞 353
15.4.1 使用代理來同步對賬戶數據的訪問 354
15.4.2 保管賬戶的註冊表 356
15.4.3 代理不是一個對象 357
15.4.4 融會貫通 359
小結 361
結束語:接下來呢? 363

相關詞條

熱門詞條

聯絡我們