首页>参考读物>计算机科学与技术>软件与程序设计

Julia设计模式
作者 : [美]汤姆·邝(Tom Kwong) 著
译者 : 方明 译
丛书名 : 华章程序员书库
出版日期 : 2021-08-23
ISBN : 978-7-111-68949-2
定价 : 129.00元
扩展资源下载
扩展信息
语种 : 简体中文
页数 : 369
开本 : 16
原书名 : Hands-On Design Patterns and Best Practices with Julia
原出版社: Packt Publishing Ltd.
属性分类: 店面
包含CD : 无CD
绝版 : 未绝版
图书简介

本书兼顾Julia编程语言的优势和不足,全面介绍了Julia编程语言,介绍了模式所依赖的编程语言特性,同时涵盖了一些高级的内容。全书分为四部分,第1部分介绍设计模式,第二部分就少Julia基础,第三部分介绍设计模式实现,第四部分介绍一些进阶主题。

图书特色

Julia联合创始人Stefan Karpinski作序推荐

图书前言

Julia是一个为开发出高性能应用程序而设计的高级编程语言,旨在提高开发人员的生产力。其动态特性可以让你快速做一个小规模的测试,然后移植到大的应用程序中。它的内省工具可以通过分析高级代码如何翻译成低级代码及机器码来实现性能优化。它的元编程更能帮助高级开发人员为特定领域的使用建立自定义的语法。它的多重分派和泛型方法功能使得开发人员可以轻松地在已有的方法上扩展新功能。鉴于以上优点,Julia是可以在许多行业广泛使用的优秀程序开发语言。
这本书满足了那些期望编写高效代码、提升系统性能以及设计出易维护软件的Julia开发人员的需求。从Julia语言诞生到2018年8月的里程碑版本1.0,许多源于Julia核心开发人员和Julia资深用户的优秀设计模式都已尽收囊中。这些设计模式有时在博客或峰会中被提及,有时出现在Julia的Discourse论坛的某一次讨论中,还有时出现在Julia Slack社区成员间的非正式谈话中。本书收录了这些设计模式,阐述了设计高质量的Julia应用程序的最佳实践。
本书的首要目标是规范这些被充分证明过的设计模式,以便于Julia开发者社区吸收和利用。
总结和命名这些模式有如下好处:
能让开发者之间的交流变得更加容易。
能让开发者更好地理解和使用这些设计模式的代码。
能让开发者明确何时正确地使用设计模式。
本书的目标简单但十分强大,读完本书,你会在使用Julia语言设计和开发软件时变得轻松。除此之外,本书提供的材料对未来关于Julia设计模式的讨论十分有用。根据以往经验,新的设计模式将会随着Julia语言的持续演化不断地加入进来。
希望你能尽享阅读本书的乐趣!
本书的读者对象
本书的目标读者是那些想为大型应用程序编写符合Julia语言特性的代码的初中级Julia开发人员。本书不是一本基础书籍,所以希望你有一定的编程基础。如果你对面向对象编程范式很熟悉,会发现本书非常有用,它会告诉你如何采用不同的方法解决同一个问题,而Julia的方式常常是更好的。
本书提及的许多设计模式广泛适用于所有领域和使用场景。不管你是数据科学家、研究员、系统开发人员还是企业软件开发者,都会因在你的项目中使用这些设计模式而获益。
本书结构
第1章介绍设计模式的历史和如何利用设计模式开发应用程序。它包含了一些适用于任何编程语言和编程范式的工业级软件设计原则。
第2章探讨如何规划大型程序及如何管理其依赖关系,其中解释了如何开发新的数据类型和表示层级关系。
第3章解释函数是如何定义的以及多重分派是如何运行的,还讨论了参数化方法和接口。针对这些方法和接口,不同的函数可以基于预定契约彼此正确地工作。
第4章介绍宏和元编程以及如何将源代码转换成另外一种形式,还描述了一些高效开发和调试宏的技巧。
第5章介绍与代码重用相关的设计模式,包含通过组合实现代码重用的委托模式、更正式的Holy Traits模式,以及从参数化的数据结构创建新类型的参数化类型模式。
第6章介绍与提高系统性能相关的设计模式,包含更好的类型稳定的全局常量模式、通过数据重排达到最佳布局的数组结构模式、通过并行计算优化内存的共享数组模式、缓存前面计算结果的记忆模式,以及通过函数特化提升性能的闸函数模式。
第7章介绍与代码可维护性相关的设计模式,包含便于管理大型代码库的子模块模式、便于创建数据类型的关键字定义模式、用较少代码定义许多相似函数的代码生成模式,以及为特殊领域创建新的语法规则的领域特定语言模式。
第8章介绍帮助你编写更加安全的代码的设计模式,包含为字段提供标准访问权限的访问器模式、控制字段的访问的属性模式、限制变量范围的let块模式,以及处理错误的异常处理模式。
第9章介绍前面提到的几类模式之外的设计模式,包含动态分派的单例类型分派模式、构建独立测试的打桩/模拟模式,以及建立线性数据处理流水线的函数管道模式。
第10章介绍需要避免的设计模式。最主要的反模式就是海盗反模式,例如为数据类型定义和扩展那些不属于你的函数,还包含降低系统性能的窄参数类型反模式和分散的非具体字段类型反模式。
第11章介绍GoF的Design Patterns: Elements of Reusable Object-Oriented Software中描述的设计模式,还探讨在Julia中如何简化或以不同方式实现这些设计模式。
第12章探讨Julia如何支持继承,以及为什么在Julia中继承会被设计为和主流面向对象编程语言中的完全不同。然后讨论类型变体(关于多重分派使用的数据类型之间的子类型关系的重要概念)。
如何充分利用本书
你可以在Julia的官方网站(https://julialang.org/)下载最新版本。
本书每章所提及的代码都在Github中如“技术要求”所述。编写本书时,这些代码都在Julia 1.3.0上通过了测试。克隆这些项目的操作如下所示。

你最好在阅读的过程中运行和体验这些示例代码。这些代码都是以如下格式存储的:
Julia源代码中的代码片段,这些片段可以复制并粘贴到REPL。
代码属于某个包目录,这个包可以像下面一样被实例化,例如第5章中的内容。

要使用这些DelegationPattern的代码,直接在该目录中使用 --project=. 命令行参数启动一个Julia REPL。

然后进入包模式,输入instantiate命令来实例化包。

之后就可以正常使用包了。

如果这是测试目录,你可以读取并运行这些测试脚本。
下载示例代码
本书的代码在Github的https://github.com/PacktPublishing/Hands-on-Design-Patterns-and-Best-Practices-with-Julia中。任何修改都会更新到Github的代码仓库中。
排版约定
本书中使用了以下排版约定。
代码体:指示文本中的代码,例如变量名、函数名、数据类型等。例如“format函数采用格式化程序和数值x,并返回格式化的字符串”。
代码块设置如下:

REPL的任何实验或输出均显示为屏幕截图。

表示重要说明。
表示提示和技巧。

上架指导

计算机\程序设计

封底文字

设计模式是开发可重用和可维护代码的基本技术。它提供了一套经过验证的解决方案,使开发人员可以快速解决软件开发中的问题。本书将演示如何在实际应用中利用设计模式。
本书首先概述应用程序设计中的设计模式和最佳实践。你将了解Julia的一些基本的功能,例如模块、数据类型、函数、接口和元编程。然后,你将掌握用于构建大型应用程序的现代Julia设计模式,重点在于性能、可重用性、鲁棒性和可维护性。本书还介绍了反模式以及如何避免开发中的常见错误和陷阱。你将学习如何在Julia中以不同方式更有效地实现传统的面向对象的设计模式。本书包含各种用例和示例,例如Julia开发专家如何在其开源包中使用设计模式。
从本书中你将学到改善软件设计、可扩展性和可重用性的方法,并能够有效地使用设计模式来应对软件开发中的常见挑战。

通过阅读本书,你将:
掌握Julia语言功能,这些功能对于开发大型软件应用程序至关重要。
发现设计模式以改善整体应用程序架构和设计。
学会开发模块化、可扩展、高性能且易于维护的可重用程序。
学会权衡对用例使用不同设计模式的利弊。
探索从面向对象编程过渡到使用等效或更高级的Julia技术的方法。

图书序言

设计模式是编程语言的负空间,这些技术是开发人员为了撬动某一编程语言,以补偿它的不足而想出来的。不管是有意还是无意,其实我们都在使用设计模式。出自四人组(Gang of Four,GoF)的Design Patterns: Elements of Reusable Object-Oriented Software收录了我们已经使用的设计模式,并进行分类编目,更重要的是,该书命名了常见的设计模式,这样开发人员就可以轻松快速地理解常见模式。它给软件开发这个行业的工具提供了共同语言。
传统的设计模式书籍都以熟练掌握编程语言为前提,几乎只专注于模式本身,而本书兼顾Julia编程语言的优势和不足。本书介绍模式所依赖的编程语言特性,即使那些不熟悉Julia编程的读者也能快速上手。此外,本书将深入讨论那些被Julia魔法化的著名的设计模式。当你读完本书,一定会掌握这门编程语言。不过话说在前头,与其他经典的编程书籍一样,你可能需要反复阅读才能完全掌握本书内容。
创建一个被广泛使用的编程语言,有趣的一点是看到人们利用它做出非凡且令人惊讶的事情。这包括人们用Julia构建的令人难以置信甚至会改变世界的应用程序——从指定FAA的下一代防撞系统到绘制所有可见宇宙的天体,再到以前所未有的准确性和分辨率对气候变化进行建模。它还包括人们想出巧妙的编程技巧来帮助自己达到目标。
我最喜欢的是(Tim)Holy Traits技术,它利用了Julia可以根据需要有效分配任意数量的参数这一特性,以解决该语言缺乏多重继承的问题,这一点我们将在第5章中讨论。Julia不仅能做好工作,而且很多时候都能超出预期。比如特质(trait)可以依赖于类型的计算属性,允许表示多继承不能表示的关系等。这表明Julia仅用一个聪明的设计模式就成功解锁了这个语言的强大功能。
Tom的背景使他对编程语言及设计模式提出了专业、细致且平衡的观点。他最开始使用BASIC编程,但是从那时起,他就在专业环境中使用多种语言,包括C++、Java、Python、TypeScript、Scheme,还有Julia。他也将这些编程语言应用到了诸多行业,如金融、搜索引擎、电子商务、内容管理和资产管理。Julia在许多领域都获得了广泛认可,特别是那些有密集计算需求的领域,这可能并不是巧合。
我们的个人经历往往造就了我们看待这个世界的方式,有时你会发现某个新的工具就是为你量身打造的。某个时候,你遇到一个新的编程语言,突然意识到这就是你一直梦寐以求的编程语言。对Tom和许多人来说,Julia就是这样一门语言。期望它对你来说也一样。
无论你是第一次尝试Julia编程,还是已经使用Julia多年,如果想学习更多的高级技术,你会在本书中找到你想要的。享受用Julia编程的乐趣吧!

Stefan Karpinski
Julia语言联合创始人
Julia计算公司(Julia Computing, Inc.)联合创始人

图书目录

序言
前言
作者简介
审校者简介
第一部分 从设计模式开始
第1章 设计模式和相关原则 2
1.1 设计模式的历史 2
1.1.1 设计模式的兴起 3
1.1.2 关于GoF模式的更多思考 3
1.1.3 在本书中我们如何描述设计模式 4
1.2 软件设计原则 4
1.2.1 SOLID原则 5
1.2.2 DRY原则 6
1.2.3 KISS原则 6
1.2.4 POLA原则 7
1.2.5 YAGNI原则 7
1.2.6 POLP原则 8
1.3 软件质量目标 8
1.3.1 可重用性 8
1.3.2 性能 9
1.3.3 可维护性 10
1.3.4 安全性 11
1.4 小结 11
1.5 问题 12
第二部分 Julia基础
第2章 模块、包和数据类型 14
2.1 技术要求 14
2.2 程序开发中不断增长的痛点 15
2.2.1 数据科学项目 15
2.2.2 企业应用程序 15
2.2.3 适应增长 16
2.3 使用命名空间、模块和包 16
2.3.1 理解命名空间 17
2.3.2 创建模块和包 17
2.3.3 创建子模块 23
2.3.4 在模块中管理文件 24
2.4 管理包的依赖关系 24
2.4.1 理解语义版本控制方案 24
2.4.2 指定Julia包的依赖关系 25
2.4.3 避免循环依赖 28
2.5 设计抽象类型和具体类型 29
2.5.1 设计抽象类型 29
2.5.2 设计具体类型 33
2.5.3 使用类型运算符 37
2.5.4 抽象类型和具体类型的差异 39
2.6 使用参数化类型 39
2.6.1 使用参数化复合类型 40
2.6.2 使用参数化抽象类型 42
2.7 数据类型转换 43
2.7.1 执行简单的数据类型转换 44
2.7.2 注意有损转换 44
2.7.3 理解数字类型转换 45
2.7.4 重温自动转换规则 45
2.7.5 理解函数分派规则 47
2.8 小结 48
2.9 问题 49
第3章 设计函数和接口 50
3.1 技术要求 50
3.2 设计函数 51
3.2.1 用例——太空战争游戏 51
3.2.2 定义函数 51
3.2.3 注释函数参数 52
3.2.4 使用可选参数 55
3.2.5 使用关键字参数 57
3.2.6 接受可变数量的参数 58
3.2.7 splatting参数 59
3.2.8 第一类实体函数 60
3.2.9 开发匿名函数 61
3.2.10 使用do语法 62
3.3 理解多重分派 63
3.3.1 什么是分派 63
3.3.2 匹配最窄类型 64
3.3.3 分派多个参数 65
3.3.4 分派过程中可能存在的歧义 67
3.3.5 歧义检测 68
3.3.6 理解动态分派 70
3.4 利用参数化方法 71
3.4.1 使用类型参数 71
3.4.2 使用类型参数替换抽象类型 72
3.4.3 在使用参数时强制类型一致性 73
3.4.4 从方法签名中提取类型信息 74
3.5 使用接口 75
3.5.1 设计和开发接口 75
3.5.2 处理软契约 79
3.5.3 使用特质 80
3.6 小结 81
3.7 问题 81
第4章 宏和元编程 82
4.1 技术要求 83
4.2 理解元编程的需求 83
4.2.1 使用@time宏测量性能 83
4.2.2 循环展开 84
4.3 使用表达式 86
4.3.1 试用解析器 86
4.3.2 手动构造表达式对象 88
4.3.3 尝试更复杂的表达式 90
4.3.4 计算表达式 93
4.3.5 在表达式中插入变量 94
4.3.6 对符号使用QuoteNode 95
4.3.7 在嵌套表达式中插值 96
4.4 开发宏 97
4.4.1 什么是宏 97
4.4.2 编写第一个宏 98
4.4.3 传递字面量参数 98
4.4.4 传递表达式参数 99
4.4.5 理解宏扩展过程 100
4.4.6 操作表达式 101
4.4.7 理解卫生宏 104
4.4.8 开发非标准字符串字面量 105
4.5 使用生成函数 107
4.5.1 定义生成函数 108
4.5.2 检查生成函数参数 109
4.6 小结 110
4.7 问题 110
第三部分 实现设计模式
第5章 可重用模式 114
5.1 技术要求 114
5.2 委托模式 114
5.2.1 在银行用例中应用委托模式 115
5.2.2 现实生活中的例子 119
5.2.3 注意事项 120
5.3 Holy Traits模式 120
5.3.1 重温个人资产管理用例 121
5.3.2 实现Holy Traits模式 122
5.3.3 重温一些常见用法 126
5.3.4 使用SimpleTraits.jl包 129
5.4 参数化类型模式 130
5.4.1 在股票交易应用程序中使用删除文本参数化类型 132
5.4.2 现实生活中的例子 135
5.5 小结 138
5.6 问题 139
第6章 性能模式 140
6.1 技术要求 141
6.2 全局常量模式 141
6.2.1 使用全局变量对性能进行基准测试 141
6.2.2 享受全局常量的速度 143
6.2.3 使用类型信息注释变量 143
6.2.4 理解常量为何有助于性能 144
6.2.5 将全局变量作为函数参数传递 145
6.2.6 将变量隐藏在全局常量中 145
6.2.7 现实生活中的例子 146
6.2.8 注意事项 147
6.3 数组结构模式 147
6.3.1 使用业务领域模型 148
6.3.2 使用不同的数据布局提高性能 150
6.3.3 注意事项 155
6.4 共享数组模式 155
6.4.1 风险管理用例介绍 156
6.4.2 准备示例数据 157
6.4.3 高性能解决方案概述 158
6.4.4 在共享数组中填充数据 159
6.4.5 直接在共享数组上分析数据 161
6.4.6 理解并行处理的开销 163
6.4.7 配置共享内存使用情况 164
6.4.8 确保工作进程可以访问代码和数据 166
6.4.9 避免并行进程之间的竞态 167
6.4.10 使用共享数组的约束 167
6.5 记忆模式 168
6.5.1 斐波那契函数介绍 168
6.5.2 改善斐波那契函数的性能 169
6.5.3 自动化构造记忆缓存 171
6.5.4 理解泛型函数的约束 172
6.5.5 支持具有多个参数的函数 173
6.5.6 处理参数中的可变数据类型 174
6.5.7 使用宏来记忆泛型函数 176
6.5.8 现实生活中的例子 177
6.5.9 注意事项 178
6.5.10 使用Caching.jl包 178
6.6 闸函数模式 180
6.6.1 识别类型不稳定的函数 181
6.6.2 理解性能影响 182
6.6.3 开发闸函数 183
6.6.4 处理类型不稳定的输出变量 183
6.6.5 使用@inferred宏 186
6.7 小结 187
6.8 问题 187
第7章 可维护性模式 188
7.1 技术要求 188
7.2 子模块模式 189
7.2.1 理解何时需要子模块 189
7.2.2 理解传入耦合与传出耦合 190
7.2.3 管理子模块 191
7.2.4 在模块和子模块之间引用符号和函数 191
7.2.5 删除双向耦合 193
7.2.6 考虑拆分为顶层模块 195
7.2.7 理解使用子模块的反论点 195
7.3 关键字定义模式 195
7.3.1 重温结构定义和构造函数 196
7.3.2 在构造函数中使用关键字参数 196
7.3.3 使用@kwdef宏简化代码 197
7.4 代码生成模式 198
7.4.1 文件日志记录器用例介绍 199
7.4.2 函数定义的代码生成 201
7.4.3 调试代码生成 202
7.4.4 考虑代码生成以外的选项 204
7.5 领域特定语言模式 205
7.5.1 L系统介绍 206
7.5.2 为L系统设计DSL 207
7.5.3 重温L系统核心逻辑 208
7.5.4 实现L系统的DSL 210
7.6 小结 215
7.7 问题 215
第8章 鲁棒性模式 216
8.1 技术要求 217
8.2 访问器模式 217
8.2.1 识别对象的隐式接口 217
8.2.2 实现getter函数 218
8.2.3 实现setter函数 219
8.2.4 禁止直接访问字段 220
8.3 属性模式 220
8.3.1 延迟文件加载器介绍 220
8.3.2 理解用于字段访问的点符号 222
8.3.3 实现读取访问和延迟加载 223
8.3.4 控制对对象字段的写入访问 226
8.3.5 报告可访问字段 227
8.4 let块模式 228
8.4.1 网络爬虫用例介绍 228
8.4.2 使用闭包将私有变量和函数隐藏起来 230
8.4.3 限制长脚本或函数的变量范围 232
8.5 异常处理模式 233
8.5.1 捕捉和处理异常 233
8.5.2 处理各种类型的异常 233
8.5.3 在顶层处理异常 235
8.5.4 跟随栈帧 236
8.5.5 理解异常处理对性能的影响 238
8.5.6 重试操作 239
8.5.7 异常时选用nothing 241
8.6 小结 242
8.7 问题 243
第9章 其他模式 244
9.1 技术要求 244
9.2 单例类型分派模式 245
9.2.1 开发命令处理器 245
9.2.2 理解单例类型 245
9.2.3 使用Val参数化数据类型 246
9.2.4 使用单例类型进行动态分派 247
9.2.5 理解分派的性能优势 249
9.3 打桩/模拟模式 251
9.3.1 什么是测试替身 251
9.3.2 信贷审批用例介绍 252
9.3.3 使用打桩执行状态验证 253
9.3.4 使用Mocking包实现打桩 255
9.3.5 将多个打桩应用于同一函数 256
9.3.6 使用模拟执行行为验证 257
9.4 函数管道模式 259
9.4.1 Hacker News分析用例介绍 260
9.4.2 理解函数管道 264
9.4.3 设计可组合函数 265
9.4.4 为平均得分函数开发函数管道 266
9.4.5 在函数管道中实现条件逻辑 269
9.4.6 沿函数管道进行广播 270
9.4.7 有关使用函数管道的注意事项 271
9.5 小结 272
9.6 问题 272
第10章 反模式 273
10.1 技术要求 273
10.2 海盗反模式 274
10.2.1 I类海盗—重新定义函数 274
10.2.2 II类海盗—不用自己的类型扩展 275
10.2.3 III类海盗—用自己的类型扩展,但目的不同 277
10.3 窄参数类型反模式 279
10.3.1 考虑参数类型的多种选项 279
10.3.2 评估性能 284
10.4 非具体字段类型反模式 285
10.4.1 理解复合数据类型的内存布局 285
10.4.2 设计复合类型时要考虑具体类型 287
10.4.3 比较具体字段类型和非具体字段类型的性能 288
10.5 小结 289
10.6 问题 289
第11章 传统的面向对象模式 290
11.1 技术要求 290
11.2 创建型模式 291
11.2.1 工厂方法模式 291
11.2.2 抽象工厂模式 292
11.2.3 单例模式 294
11.2.4 建造者模式 296
11.2.5 原型模式 297
11.3 行为型模式 298
11.3.1 责任链模式 298
11.3.2 中介者模式 300
11.3.3 备忘录模式 302
11.3.4 观察者模式 304
11.3.5 状态模式 305
11.3.6 策略模式 306
11.3.7 模板方法模式 308
11.3.8 命令模式、解释器模式、迭代器模式和访问者模式 310
11.4 结构型模式 310
11.4.1 适配器模式 310
11.4.2 组合模式 313
11.4.3 享元模式 314
11.4.4 桥接模式、装饰器模式和外观模式 316
11.5 小结 316
11.6 问题 317
第四部分 进阶主题
第12章 继承与变体 320
12.1 技术要求 320
12.2 实现继承和行为子类型化 321
12.2.1 理解实现继承 321
12.2.2 理解行为子类型化 323
12.2.3 正方形–矩形问题 324
12.2.4 脆弱的基类问题 326
12.2.5 重温鸭子类型 327
12.3 协变、不变和逆变 328
12.3.1 理解不同种类的变体 328
12.3.2 参数化类型是不变的 328
12.3.3 方法参数是协变的 331
12.3.4 剖析函数类型 331
12.3.5 确定函数类型的变体 333
12.3.6 实现自己的函数类型分派 335
12.4 再谈参数化方法 336
12.4.1 指定类型变量 337
12.4.2 匹配类型变量 337
12.4.3 理解对角线规则 338
12.4.4 对角线规则的例外 339
12.4.5 类型变量的可用性 339
12.5 小结 340
12.6 问题 341
问题答案 342

教学资源推荐
作者: 史涯晴 贺汛 编著
作者: Kenneth Barclay;John Savage
作者: (美)Al Kelley Ira Pohl
作者: [美]兰德尔·海德(Randall Hyde) 著
参考读物推荐
作者: (美) Emad Benjamin 著
作者: 黄桂钦,于中华
作者: Mark Lutz
作者: (美)Kevin Brothaler 著