新書推薦:
《
没有一种人生是完美的:百岁老人季羡林的人生智慧(读完季羡林,我再也不内耗了)
》
售價:HK$
56.9
《
日耳曼通识译丛:复原力:心理抗逆力
》
售價:HK$
34.3
《
海外中国研究·未竟之业:近代中国的言行表率
》
售價:HK$
135.7
《
我们为何建造(城市与生态文明丛书)
》
售價:HK$
89.7
《
算法经济 : 商业逻辑与人类生活的智能演进(生动呈现AI与算法的创新应用与商业价值)
》
售價:HK$
79.4
《
家书中的百年史
》
售價:HK$
79.4
《
偏爱月亮
》
售價:HK$
45.8
《
生物安全与环境
》
售價:HK$
56.4
|
編輯推薦: |
图书特色:
编写可读的、团队友好的代码
熟悉异步和数据流
从根本上改进错误处理
事件溯源及其他FP模式
随书赠送示例代码和练习资料,下载地址见书封底二维码。
|
內容簡介: |
函数式编程将改变你思考代码的方式!利用FP技术,C#开发人员可极大地提升状态管理、并发处理和事件处理能力,并更好地长期维护代码。C#提供了灵活性,使你能充分利用函数式技术的优势。《C#函数式编程编写更优质的C#代码》从全新视角赋予你强大力量。 《C#函数式编程编写更优质的C#代码》引导你在C#语言中使用函数式思想来解决现实问题;首先介绍函数式编程的原理,分析如何借助C#语言特性实现函数式编程,然后在多个紧贴实用的示例的引导下,讲述函数组合、数据流编程、不可变数据结构以及使用LINQ构建单子组合等主题。
|
關於作者: |
Enrico Buonanno 毕业于哥伦比亚大学计算机科学系,是一名出色的开发人员、架构师和培训师,拥有15年的工作经验。
|
目錄:
|
目 录
第Ⅰ部分 核心概念
第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
|
內容試閱:
|
前 言
《C#函数式编程 编写更优质的C#代码》旨在展示如何利用C#中的函数式技术编写简洁、优雅、健壮和可维护的代码。
《C#函数式编程 编写更优质的C#代码》读者对象
《C#函数式编程 编写更优质的C#代码》是为那些具有雄心壮志的开发人员所编写的。你需要了解C#语言和.NET框架。你需要具备开发实际应用的经验,熟悉OOP的概念、模式和最佳实践。并且,你正在寻求通过学习函数式技术来扩展编程技能,以便可以充分利用C#的多范式语言特性。如果你正在尝试或正在计划学习一门函数式语言,那么《C#函数式编程 编写更优质的C#代码》也将是非常有价值的,因为你将学习如何在一门你所熟悉的语言上进行函数式思考。改变自己的思考方式是很难的;而一旦做到,那么学习任何特定语言的语法将变得相对容易。
《C#函数式编程 编写更优质的C#代码》的组织结构
全书共15章,分为3个部分:
● 第Ⅰ部分介绍函数式编程的基本技术和原理。我们将初窥函数式编程是什么,以及C#是如何支持函数式编程风格的。然后,将研究高阶函数的功能、纯函数及其与可测性的关系、类型和函数签名的设计,以及如何将简单的函数组合到复杂的程序中。在第Ⅰ部分的最后,你将很好地感受到一个用函数式风格所编写的程序是什么样的,以及这种风格所带来的好处。
● 第Ⅱ部分将加快速度,转向更广泛的关注点,例如函数式的错误处理、模块化和组合应用,以及理解状态和表示变化的函数式方法。到第Ⅱ部分结束时,你将掌握一系列工具的用法,将能利用函数式方法来有效地完成许多编程任务。
● 第Ⅲ部分将讨论更高级的主题,包括惰性求值、有状态计算、异步、数据流和并发性。第Ⅲ部分的每章都介绍一些重要技术,它们可能彻底改变你编写软件的方式和思考方式。
你会在每章中找到更详细的主题分类,并在阅读任何特定章节之前,都能从《C#函数式编程 编写更优质的C#代码》的内封了解到需要预先阅读哪些章节。
为实际应用编码
《C#函数式编程 编写更优质的C#代码》旨在让实际场景保持真实。为此,很多例子都涉及实际任务,例如读取配置、连接数据库、验证HTTP请求;对于这些事情,你可能已经知道如何做了,但你将用函数式思维的新视角来重新看待它们。
在《C#函数式编程 编写更优质的C#代码》中,我使用了一个长期运行的例子来说明在编写LOB应用时,FP是如何提供帮助的。为此,我选择了一个在线银行应用,它是虚拟的Codeland银行BOC 我知道这或许有些生搬硬套了,但至少它有了必需的三个字母的缩写。由于大多数人都可访问在线银行设施,因此很容易想象其所需的功能,并且清楚地看到所讨论的问题是如何与实际应用关联的。
我也使用了场景来说明如何解决函数式风格中典型的编程问题。在实际的例子和FP概念之间的不断反复,将帮助我们弥合理论与实践之间的差异。
利用函数式库
诸如C#的语言具有函数式特性,但为了充分利用这些特性,你将经常使用便于实现常见任务的库。Microsoft已经提供了几个库,以便进行函数式风格的编程,包括:
● System.Linq这是一个功能库。我假定你是熟悉它的,因为它是.NET的一个重要组成部分。
● System.Collections.Immutable这是一个不可变集合的库,第9章将开始使用它。
● System.Reactive这是.NET的Reactive Extensions的实现,允许你使用数据流,第14章将讨论这些数据流。
当然还有其他许多重要的类型和功能未列举,这些都是FP的主要部分。因此,一些独立的开发人员已经编写了一些开源的代码库来填补这些空白。到目前为止,其中最完整的是LanguageExt,这是由Paul Louth编写的一个库,用于在进行函数式编码时改进C#开发人员的体验。
《C#函数式编程 编写更优质的C#代码》并没有直接使用LanguageExt;相反,将向你展示如何开发自己的函数式实用工具库,且将其命名为LaYumba.Functional,尽管它与LanguageExt在很大程度上是重叠的,但这在教学方面会更有用,原因有如下几点:
● 在《C#函数式编程 编写更优质的C#代码》出版后,将保持代码的稳定。
● 你可以透过现象看本质,将看到看似简单实则强大的函数式构造。
● 你可以专注于基本要素:我将以最纯粹的形式向你展示这些构造,这样你就不会被一个完整的库所处理的细节和边缘情况分散注意力。
代码约定和下载
代码示例使用了C# 7,大部分与C# 6兼容。C# 7中专门介绍的语言特性仅用于第10章及之后章节另外,1.2节的几个示例中明确地展示了C# 7。可在REPL中执行许多较短的代码片段,从而获得动手练习的实时反馈。更多的扩展示例可通过下载,其中还配有练习的设置和解决方案。
《C#函数式编程 编写更优质的C#代码》中的代码清单重点讨论了正在讨论的主题,因此可能会省略命名空间namespace、using语句、简单的构造函数,或先前代码清单中出现的并保持不变的代码段。如果你想查看代码清单的完整编译版本,可在代码存储库中找到它。
另外,读者也可扫描封底的二维码下载相关资料。
图书论坛
购买《C#函数式编程 编写更优质的C#代码》后,可免费访问由Manning出版社运行的私人网络论坛,你可在这里提交有关《C#函数式编程 编写更优质的C#代码》的评论,询问技术问题,并获得作者和其他用户的帮助。可通过访问该论坛。你也可通过了解更多关于Manning论坛及论坛行为准则的信息。
Manning出版社为读者提供一个场所,在这里,读者之间以及读者和作者之间可以进行有意义的对话。但不承诺作者的任何具体参与度,作者对论坛的贡献是自愿的并且是无偿的。我们建议你尝试向作者提出一些具有挑战性的问题,以免他的兴趣流失!只要《C#函数式编程 编写更优质的C#代码》还在市场上销售,论坛和之前所讨论的内容存档将可从出版商的网站上直接访问。
|
|