大规模C++软件开发 卷1:过程与架构

大规模C++软件开发 卷1:过程与架构
分享
扫描下方二维码分享到微信
打开微信,点击右上角”+“,
使用”扫一扫“即可将网页分享到朋友圈。
作者: [美] (John Lakos)
2023-08
版次: 1
ISBN: 9787115609779
定价: 149.80
装帧: 平装
页数: 540页
字数: 915千字
6人买过
  • 本书通过具体示例演示大规模C++开发的基本设计设想,为各种规模的项目奠定基础,并演示成功进行大规模实际开发所需的过程、方法、技术和工具。通过阅读本书,读者可以逐步改变自己的设计和开发方法。本书旨在使用软件从业人员熟悉的C++构件来解决现实问题,同时确定(并激发)现代C++替代方案。作者利用超过30年的构建大规模、关键任务的企业系统的实践经验,展示了如何创建和增长软件资本。
      本书专为有经验的C++软件开发者和系统设计师编写,从事大型软件开发工作的架构师或项目负责人等也可以通过阅读本书解决实际工作中的问题。 约翰·拉科斯(John Lakos),《大规模C++程序设计》(Large-Scale C++ Software Design)一书的作者,任职于彭博有限合伙企业,担任高级架构师,同时是全球C++软件开发顾问。2001年他成立了彭博的BDE工作组,按照他的基于组件的方法论、过程和架构来开发细粒度的、可复用的C++软件。他是ACCU、C++Now、CppCon和Meeting C++等业内技术大会的常客,经常发表技术演讲。他自2006年开始任C++标准委员会的投票成员,新一代C++的成型有他的一份功劳,包括C++11的值语义、C++17的PMR分配器和C++20的模块。他于1996年出版的《大规模C++程序设计》一书是用C++做大型系统设计的开山之作,至今还是这个领域的常用参考书。 第0章 动机1

    0.1  目标:进度更快、产品更好、预算更低1

    0.2  应用软件与库软件3

    0.3  协作式软件与可复用软件8

    0.4  层次化可复用软件12

    0.5  易延展软件与稳定软件16

    0.6  物理设计的关键作用24

    0.7  物理形式统一的软件:组件25

    0.8  对层次化复用的量化:一个类比32

    0.9  软件资本51

    0.10  增大投入57

    0.11  保持警觉62

    0.12  小结65

    第 1章  编译器、连接器和组件70

    1.1  知识就是力量:细节决定成败70

    1.1.1 “Hello World!”70

    1.1.2  创建C++程序71

    1.1.3  头文件的作用72

    1.2  C++程序的编译和连接73

    1.2.1  构建流程:编译器和连接器的使用73

    1.2.2  目标文件(.o)的经典原子性77

    1.2.3  .o文件中的节和弱符号79

    1.2.4  静态库79

    1.2.5 “单例”注册表的例子81

    1.2.6  库间依赖84

    1.2.7  连接顺序和构建时行为87

    1.2.8  连接顺序和运行时行为87

    1.2.9  共享(动态连接)库88

    1.3  声明、定义和连结88

    1.3.1  声明与定义88

    1.3.2 (逻辑的)连结与(物理的)连接92

    1.3.3  需要了解连接工具92

    1.3.4  物理“连结”的另一种定义:绑结92

    1.3.5  连接器运作的更多细节93

    1.3.6  对一些需要全程序范围内地址唯一的实体的介绍94

    1.3.7  客户编译器需要看到定义的源代码的构件96

    1.3.8  声明并不一定要带上定义才能起作用97

    1.3.9  客户编译器通常需要看到类定义97

    1.3.10  客户编译器必须看到定义的源代码的其他实体98

    1.3.11  枚举具有外连结,但又会怎样98

    1.3.12  内联函数略有特殊99

    1.3.13  函数模板和类模板99

    1.3.14  函数模板和显式特化100

    1.3.15  类模板及其偏特化104

    1.3.16  extern模板106

    1.3.17  用工具来理解单一定义规则和绑结108

    1.3.18  命名空间108

    1.3.19  对const实体默认连结的阐释109

    1.3.20  本节小结109

    1.4  头文件111

    1.5  包含指令和包含保护符118

    1.5.1  包含指令118

    1.5.2  内置的包含保护符119

    1.5.3  外置的包含保护符(已废弃)121

    1.6  从.h/.cpp文件对到组件123

    1.6.1  组件特性1123

    1.6.2  组件特性2125

    1.6.3  组件特性3126

    1.7  符号和术语128

    1.7.1  概要128

    1.7.2  Is-A逻辑关系130

    1.7.3  Uses-In-The-Interface逻辑关系130

    1.7.4  Uses-In-The-Implementation逻辑关系131

    1.7.5  Uses-In-Name-Only逻辑关系和协议类133

    1.7.6  In-Structure-Only(ISO)协作式逻辑关系135

    1.7.7  受约束模板和接口继承的相似之处136

    1.7.8  受约束模板和接口继承的不同之处137

    1.7.9  3种“继承型”关系各有所长138

    1.7.10  给模板的类型约束编写注释139

    1.7.11  本节小结140

    1.8  Depends-On关系141

    1.9  隐含依赖144

    1.10  层级编号149

    1.11  抽取实际的依赖151

    组件特性4152

    1.12  小结153

    第 2章  打包和设计规则159

    2.1  观全貌159

    2.2  物理聚合161

    2.2.1  物理聚合的一般定义161

    2.2.2  物理聚合谱的小端162

    2.2.3  物理聚合谱的大端162

    2.2.4  聚合的概念原子性163

    2.2.5  聚合依赖的广义定义163

    2.2.6  架构显著性164

    2.2.7  一般发布单元的架构显著性164

    2.2.8  发布单元中具有架构显著性的部分164

    2.2.9  发布单元的什么部分不是架构显著的164

    2.2.10  组件“自然地”具有架构显著性164

    2.2.11  组件必须是一对.h/.cpp文件吗165

    2.2.12  何时不宜写成一对.h/.cpp文件165

    2.2.13  对.cpp文件的划分仅是组织上的改变165

    2.2.14  实体清单和可容许依赖165

    2.2.15  对可容许依赖的包络的表达需求167

    2.2.16  物理层次需平衡得当167

    2.2.17  不仅要层次化,而且要讲究平衡168

    2.2.18  物理聚合超过3级即算过多169

    2.2.19  即使是大型系统,3级也已足够170

    2.2.20  发布单元总有2级或3级的物理聚合171

    2.2.21  平衡得当的3级聚合就已足够171

    2.2.22  发布单元应该是最为架构显著的171

    2.2.23  架构显著的名称必须唯一171

    2.2.24  不要出现循环物理依赖172

    2.2.25  本节小结173

    2.3  逻辑连贯和物理连贯173

    2.4  逻辑名称衔接和物理名称衔接175

    2.4.1  过去对命名空间污染的应对措施175

    2.4.2  名称务必唯一,衔接的命名有益于人175

    2.4.3  既不衔接又不有助记忆的命名荒谬至极176

    2.4.4  需要相互衔接的名称177

    2.4.5  过去/现在对包的定义177

    2.4.6  使用点就应足够敲定位置177

    2.4.7  专有软件须有企业级命名空间182

    2.4.8  逻辑构件署名应锚定于其组件182

    2.4.9  在包级命名空间的作用域中只有类、结构体和自由运算符183

    2.4.10  包的前缀命名不仅仅是编程风格189

    2.4.11  包前缀即其所在包组名192

    2.4.12  using指令和声明往往是坏主意193

    2.4.13  本节小结196

    2.5  组件源代码的组织196

    2.6  组件设计规则202

    2.7  组件私有类和附属组件219

    2.7.1  组件私有类220

    2.7.2  有几种实现方案可待选择220

    2.7.3  下划线的约定用法220

    2.7.4  使用组件私有类的经典案例224

    2.7.5  附属组件227

    2.7.6  本节小结229

    2.8  包229

    2.8.1  用包来分解子系统229

    2.8.2  包间循环是不好的234

    2.8.3  布置、作用域和规模是首要考量235

    2.8.4  包前缀的唯一性对沟通大有裨益236

    2.8.5  本节小结238

    2.9  包组238

    2.9.1  物理聚合的第三层级238

    2.9.2  在部署时对包组的组织245

    2.9.3  在实践中如何使用包组245

    2.9.4  去中心化的(自治的)包的创建248

    2.9.5  本节小结249

    2.10  包和包组的命名249

    2.10.1  平铺直叙的包名不一定好249

    2.10.2  包组的名称250

    2.10.3  包的名称250

    2.10.4  本节小结252

    2.11  子包252

    2.12  遗留软件、开源软件和第三方软件254

    2.13  应用255

    2.14  层次化可测试性的需求258

    2.14.1  将本书的方法论运用于细粒度的单元测试中258

    2.14.2  本节安排(还有卷2及特别是卷3的引子)258

    2.14.3  测试要能层次化地推进258

    2.14.4  测试时的局部组件依赖的相对导入263

    2.14.5  可容许的跨包的测试驱动程序依赖266

    2.14.6  尽量减少测试驱动程序对外部环境的依赖268

    2.14.7  坚持统一(独立)的测试驱动程序调用接口269

    2.14.8  本节小结270

    2.15  从开发到部署271

    2.15.1  不应在软件的灵活部署方面让步271

    2.15.2  .h和.o文件名的唯一性非常关键271

    2.15.3  在开发过程中软件组织会有所变化271

    2.15.4  在全公司范围内让名称保持唯一有助于重构272

    2.15.5  在构建过程中软件组织都可能有所变化272

    2.15.6  即使在正常情况下部署中仍需要灵活性272

    2.15.7  让定制化部署成为可能是灵活性之价值的重要体现273

    2.15.8  头文件中风格化呈现的灵活性273

    2.15.9  库的部署方式不应架构显著273

    2.15.10  出于工程原因对已部署的软件进行划分274

    2.15.11  出于业务原因对已部署的软件进行划分275

    2.15.12  本节小结276

    2.16  元数据276

    2.16.1  元数据即“法令”277

    2.16.2  元数据的类型277

    2.16.3  元数据的呈现281

    2.16.4  本节小结282

    2.17  小结283

    第3章  物理设计和分解290

    3.1  从物理的角度思考290

    3.1.1  纯经典的(逻辑的)软件设计是幼稚的291

    3.1.2  组件充当细粒度的模块291

    3.1.3  软件的设计空间是有方向性的291

    3.1.4  软件有其绝对位置292

    3.1.5  并置与否的准则应该看本质,不应流于表面293

    3.1.6  不规整的非初等功能搜寻十分麻烦293

    3.1.7  包的作用域是一项重要的设计考量293

    3.1.8  禁止循环物理依赖带来的一些限制295

    3.1.9  对友元的约束有意排除了某些逻辑设计297

    3.1.10  一个有正当理由要求包装的 案例297

    3.1.11  本节小结302

    3.2  避免糟糕的物理模块化303

    3.2.1  有很多糟糕的模块化准则,语法是其中之一303

    3.2.2  将用途广泛的软件分解并加入库中非常重要303

    3.2.3  迫于压力未能维持应用/库的模块化303

    3.2.4  可复用组件的持续降级至关重要304

    3.2.5  对应用开发者而言,物理依赖不是实现细节305

    3.2.6  迭代器有助于减少初等功能的开发量309

    3.2.7  既要最小也要初等:实用结构体309

    3.2.8  总结性示例:封装型多边形类接口309

    3.2.9  语义与语法作为模块化准则322

    3.2.10  本节小结323

    3.3  逻辑相近的事物在物理上应分组在一起324

    3.3.1  类并置的4个明确准则324

    3.3.2  组件之上的并置327

    3.3.3  何时让辅助类供其组件私用327

    3.3.4  模板特化的并置329

    3.3.5  附属组件的使用329

    3.3.6  将紧密的相互协作并置于单个发布单元中330

    3.3.7  计算天数的示例330

    3.3.8  最后的示例:单线程引用计数型函子336

    3.3.9  本节小结344

    3.4  避免循环的连接时依赖345

    3.5  层级划分技术351

    3.5.1  经典层级划分技术351

    3.5.2  升级352

    3.5.3  降级357

    3.5.4  不透明指针359

    3.5.5  哑数据365

    3.5.6  冗余367

    3.5.7  回调371

    3.5.8  管理器类389

    3.5.9  分解391

    3.5.10  升级封装392

    3.5.11  本节小结407

    3.6  避免过度的连接时依赖408

    3.6.1  起初分解妥当的日期类会随时间退化408

    3.6.2  将工作日功能添加到日期类中(坏主意)414

    3.6.3  提供一个物理上整块式的平台适配器(坏主意)415

    3.6.4  本节小结418

    3.7  横展架构与分层架构418

    3.7.1  另一个与建筑业的类比419

    3.7.2  (经典的)分层架构419

    3.7.3  对纯组合式设计加以改进421

    3.7.4  最小化累积组件依赖度421

    3.7.5  基于继承的横展架构424

    3.7.6  横展架构与分层架构的测试427

    3.7.7  本节小结427

    3.8  避免不当的连接时依赖428

    3.8.1  不当的物理依赖428

    3.8.2  在单一技术上“押注”(坏主意)431

    3.8.3  本节小结436

    3.9  确保物理互操作性436

    3.9.1  妨碍层次化的复用是坏主意436

    3.9.2  领域特定的条件编译是坏主意437

    3.9.3  在库组件中的应用特定的依赖是坏主意439

    3.9.4  约束并排型复用是坏主意440

    3.9.5  防止故意的滥用不是目的441

    3.9.6  让组件侵占全局资源是坏主意441

    3.9.7  隐藏头文件来实现逻辑封装是坏主意441

    3.9.8  可复用库中存在对不可移植软件的依赖是坏主意443

    3.9.9  将潜在可复用软件隐藏起来是坏主意446

    3.9.10  本节小结447

    3.10  避免不必要的编译时依赖447

    3.10.1  封装不能杜绝编译时耦合447

    3.10.2  共享枚举和编译时耦合449

    3.10.3  C++中的编译时耦合比C语言中更为普遍451

    3.10.4  避免不必要的编译时耦合451

    3.10.5  避免编译时耦合的益处及真实示例454

    3.10.6  本节小结458

    3.11  架构隔离技术458

    3.11.1  封装与隔离的形式化定义459

    3.11.2  用组件的概念阐释封装与  隔离459

    3.11.3  整体隔离与部分隔离460

    3.11.4  架构显著的整体隔离技术461

    3.11.5  纯抽象接口(协议)类461

    3.11.6  完全隔离型具体包装器  组件467

    3.11.7  过程接口471

    3.11.8  隔离和动态加载库484

    3.11.9  面向服务的架构484

    3.11.10  本节小结485

    3.12  用组件进行设计485

    3.12.1  原先陈述的“需求”485

    3.12.2  实际(外延)的需求486

    3.12.3  用C++类型表示日期值487

    3.12.4  确定今天的日期值494

    3.12.5  确定给定日期值是否为工作日496

    3.12.6  解析和格式化功能508

    3.12.7  值的传输与持久化510

    3.12.8  债券计息日数惯例510

    3.12.9  日期数学510

    3.12.10  日期和日历实用件513

    3.12.11  充实分解透彻的实现515

    3.12.12  本节小结527

    3.13  小结529

    结论  536

    参考文献538
  • 内容简介:
    本书通过具体示例演示大规模C++开发的基本设计设想,为各种规模的项目奠定基础,并演示成功进行大规模实际开发所需的过程、方法、技术和工具。通过阅读本书,读者可以逐步改变自己的设计和开发方法。本书旨在使用软件从业人员熟悉的C++构件来解决现实问题,同时确定(并激发)现代C++替代方案。作者利用超过30年的构建大规模、关键任务的企业系统的实践经验,展示了如何创建和增长软件资本。
      本书专为有经验的C++软件开发者和系统设计师编写,从事大型软件开发工作的架构师或项目负责人等也可以通过阅读本书解决实际工作中的问题。
  • 作者简介:
    约翰·拉科斯(John Lakos),《大规模C++程序设计》(Large-Scale C++ Software Design)一书的作者,任职于彭博有限合伙企业,担任高级架构师,同时是全球C++软件开发顾问。2001年他成立了彭博的BDE工作组,按照他的基于组件的方法论、过程和架构来开发细粒度的、可复用的C++软件。他是ACCU、C++Now、CppCon和Meeting C++等业内技术大会的常客,经常发表技术演讲。他自2006年开始任C++标准委员会的投票成员,新一代C++的成型有他的一份功劳,包括C++11的值语义、C++17的PMR分配器和C++20的模块。他于1996年出版的《大规模C++程序设计》一书是用C++做大型系统设计的开山之作,至今还是这个领域的常用参考书。
  • 目录:
    第0章 动机1

    0.1  目标:进度更快、产品更好、预算更低1

    0.2  应用软件与库软件3

    0.3  协作式软件与可复用软件8

    0.4  层次化可复用软件12

    0.5  易延展软件与稳定软件16

    0.6  物理设计的关键作用24

    0.7  物理形式统一的软件:组件25

    0.8  对层次化复用的量化:一个类比32

    0.9  软件资本51

    0.10  增大投入57

    0.11  保持警觉62

    0.12  小结65

    第 1章  编译器、连接器和组件70

    1.1  知识就是力量:细节决定成败70

    1.1.1 “Hello World!”70

    1.1.2  创建C++程序71

    1.1.3  头文件的作用72

    1.2  C++程序的编译和连接73

    1.2.1  构建流程:编译器和连接器的使用73

    1.2.2  目标文件(.o)的经典原子性77

    1.2.3  .o文件中的节和弱符号79

    1.2.4  静态库79

    1.2.5 “单例”注册表的例子81

    1.2.6  库间依赖84

    1.2.7  连接顺序和构建时行为87

    1.2.8  连接顺序和运行时行为87

    1.2.9  共享(动态连接)库88

    1.3  声明、定义和连结88

    1.3.1  声明与定义88

    1.3.2 (逻辑的)连结与(物理的)连接92

    1.3.3  需要了解连接工具92

    1.3.4  物理“连结”的另一种定义:绑结92

    1.3.5  连接器运作的更多细节93

    1.3.6  对一些需要全程序范围内地址唯一的实体的介绍94

    1.3.7  客户编译器需要看到定义的源代码的构件96

    1.3.8  声明并不一定要带上定义才能起作用97

    1.3.9  客户编译器通常需要看到类定义97

    1.3.10  客户编译器必须看到定义的源代码的其他实体98

    1.3.11  枚举具有外连结,但又会怎样98

    1.3.12  内联函数略有特殊99

    1.3.13  函数模板和类模板99

    1.3.14  函数模板和显式特化100

    1.3.15  类模板及其偏特化104

    1.3.16  extern模板106

    1.3.17  用工具来理解单一定义规则和绑结108

    1.3.18  命名空间108

    1.3.19  对const实体默认连结的阐释109

    1.3.20  本节小结109

    1.4  头文件111

    1.5  包含指令和包含保护符118

    1.5.1  包含指令118

    1.5.2  内置的包含保护符119

    1.5.3  外置的包含保护符(已废弃)121

    1.6  从.h/.cpp文件对到组件123

    1.6.1  组件特性1123

    1.6.2  组件特性2125

    1.6.3  组件特性3126

    1.7  符号和术语128

    1.7.1  概要128

    1.7.2  Is-A逻辑关系130

    1.7.3  Uses-In-The-Interface逻辑关系130

    1.7.4  Uses-In-The-Implementation逻辑关系131

    1.7.5  Uses-In-Name-Only逻辑关系和协议类133

    1.7.6  In-Structure-Only(ISO)协作式逻辑关系135

    1.7.7  受约束模板和接口继承的相似之处136

    1.7.8  受约束模板和接口继承的不同之处137

    1.7.9  3种“继承型”关系各有所长138

    1.7.10  给模板的类型约束编写注释139

    1.7.11  本节小结140

    1.8  Depends-On关系141

    1.9  隐含依赖144

    1.10  层级编号149

    1.11  抽取实际的依赖151

    组件特性4152

    1.12  小结153

    第 2章  打包和设计规则159

    2.1  观全貌159

    2.2  物理聚合161

    2.2.1  物理聚合的一般定义161

    2.2.2  物理聚合谱的小端162

    2.2.3  物理聚合谱的大端162

    2.2.4  聚合的概念原子性163

    2.2.5  聚合依赖的广义定义163

    2.2.6  架构显著性164

    2.2.7  一般发布单元的架构显著性164

    2.2.8  发布单元中具有架构显著性的部分164

    2.2.9  发布单元的什么部分不是架构显著的164

    2.2.10  组件“自然地”具有架构显著性164

    2.2.11  组件必须是一对.h/.cpp文件吗165

    2.2.12  何时不宜写成一对.h/.cpp文件165

    2.2.13  对.cpp文件的划分仅是组织上的改变165

    2.2.14  实体清单和可容许依赖165

    2.2.15  对可容许依赖的包络的表达需求167

    2.2.16  物理层次需平衡得当167

    2.2.17  不仅要层次化,而且要讲究平衡168

    2.2.18  物理聚合超过3级即算过多169

    2.2.19  即使是大型系统,3级也已足够170

    2.2.20  发布单元总有2级或3级的物理聚合171

    2.2.21  平衡得当的3级聚合就已足够171

    2.2.22  发布单元应该是最为架构显著的171

    2.2.23  架构显著的名称必须唯一171

    2.2.24  不要出现循环物理依赖172

    2.2.25  本节小结173

    2.3  逻辑连贯和物理连贯173

    2.4  逻辑名称衔接和物理名称衔接175

    2.4.1  过去对命名空间污染的应对措施175

    2.4.2  名称务必唯一,衔接的命名有益于人175

    2.4.3  既不衔接又不有助记忆的命名荒谬至极176

    2.4.4  需要相互衔接的名称177

    2.4.5  过去/现在对包的定义177

    2.4.6  使用点就应足够敲定位置177

    2.4.7  专有软件须有企业级命名空间182

    2.4.8  逻辑构件署名应锚定于其组件182

    2.4.9  在包级命名空间的作用域中只有类、结构体和自由运算符183

    2.4.10  包的前缀命名不仅仅是编程风格189

    2.4.11  包前缀即其所在包组名192

    2.4.12  using指令和声明往往是坏主意193

    2.4.13  本节小结196

    2.5  组件源代码的组织196

    2.6  组件设计规则202

    2.7  组件私有类和附属组件219

    2.7.1  组件私有类220

    2.7.2  有几种实现方案可待选择220

    2.7.3  下划线的约定用法220

    2.7.4  使用组件私有类的经典案例224

    2.7.5  附属组件227

    2.7.6  本节小结229

    2.8  包229

    2.8.1  用包来分解子系统229

    2.8.2  包间循环是不好的234

    2.8.3  布置、作用域和规模是首要考量235

    2.8.4  包前缀的唯一性对沟通大有裨益236

    2.8.5  本节小结238

    2.9  包组238

    2.9.1  物理聚合的第三层级238

    2.9.2  在部署时对包组的组织245

    2.9.3  在实践中如何使用包组245

    2.9.4  去中心化的(自治的)包的创建248

    2.9.5  本节小结249

    2.10  包和包组的命名249

    2.10.1  平铺直叙的包名不一定好249

    2.10.2  包组的名称250

    2.10.3  包的名称250

    2.10.4  本节小结252

    2.11  子包252

    2.12  遗留软件、开源软件和第三方软件254

    2.13  应用255

    2.14  层次化可测试性的需求258

    2.14.1  将本书的方法论运用于细粒度的单元测试中258

    2.14.2  本节安排(还有卷2及特别是卷3的引子)258

    2.14.3  测试要能层次化地推进258

    2.14.4  测试时的局部组件依赖的相对导入263

    2.14.5  可容许的跨包的测试驱动程序依赖266

    2.14.6  尽量减少测试驱动程序对外部环境的依赖268

    2.14.7  坚持统一(独立)的测试驱动程序调用接口269

    2.14.8  本节小结270

    2.15  从开发到部署271

    2.15.1  不应在软件的灵活部署方面让步271

    2.15.2  .h和.o文件名的唯一性非常关键271

    2.15.3  在开发过程中软件组织会有所变化271

    2.15.4  在全公司范围内让名称保持唯一有助于重构272

    2.15.5  在构建过程中软件组织都可能有所变化272

    2.15.6  即使在正常情况下部署中仍需要灵活性272

    2.15.7  让定制化部署成为可能是灵活性之价值的重要体现273

    2.15.8  头文件中风格化呈现的灵活性273

    2.15.9  库的部署方式不应架构显著273

    2.15.10  出于工程原因对已部署的软件进行划分274

    2.15.11  出于业务原因对已部署的软件进行划分275

    2.15.12  本节小结276

    2.16  元数据276

    2.16.1  元数据即“法令”277

    2.16.2  元数据的类型277

    2.16.3  元数据的呈现281

    2.16.4  本节小结282

    2.17  小结283

    第3章  物理设计和分解290

    3.1  从物理的角度思考290

    3.1.1  纯经典的(逻辑的)软件设计是幼稚的291

    3.1.2  组件充当细粒度的模块291

    3.1.3  软件的设计空间是有方向性的291

    3.1.4  软件有其绝对位置292

    3.1.5  并置与否的准则应该看本质,不应流于表面293

    3.1.6  不规整的非初等功能搜寻十分麻烦293

    3.1.7  包的作用域是一项重要的设计考量293

    3.1.8  禁止循环物理依赖带来的一些限制295

    3.1.9  对友元的约束有意排除了某些逻辑设计297

    3.1.10  一个有正当理由要求包装的 案例297

    3.1.11  本节小结302

    3.2  避免糟糕的物理模块化303

    3.2.1  有很多糟糕的模块化准则,语法是其中之一303

    3.2.2  将用途广泛的软件分解并加入库中非常重要303

    3.2.3  迫于压力未能维持应用/库的模块化303

    3.2.4  可复用组件的持续降级至关重要304

    3.2.5  对应用开发者而言,物理依赖不是实现细节305

    3.2.6  迭代器有助于减少初等功能的开发量309

    3.2.7  既要最小也要初等:实用结构体309

    3.2.8  总结性示例:封装型多边形类接口309

    3.2.9  语义与语法作为模块化准则322

    3.2.10  本节小结323

    3.3  逻辑相近的事物在物理上应分组在一起324

    3.3.1  类并置的4个明确准则324

    3.3.2  组件之上的并置327

    3.3.3  何时让辅助类供其组件私用327

    3.3.4  模板特化的并置329

    3.3.5  附属组件的使用329

    3.3.6  将紧密的相互协作并置于单个发布单元中330

    3.3.7  计算天数的示例330

    3.3.8  最后的示例:单线程引用计数型函子336

    3.3.9  本节小结344

    3.4  避免循环的连接时依赖345

    3.5  层级划分技术351

    3.5.1  经典层级划分技术351

    3.5.2  升级352

    3.5.3  降级357

    3.5.4  不透明指针359

    3.5.5  哑数据365

    3.5.6  冗余367

    3.5.7  回调371

    3.5.8  管理器类389

    3.5.9  分解391

    3.5.10  升级封装392

    3.5.11  本节小结407

    3.6  避免过度的连接时依赖408

    3.6.1  起初分解妥当的日期类会随时间退化408

    3.6.2  将工作日功能添加到日期类中(坏主意)414

    3.6.3  提供一个物理上整块式的平台适配器(坏主意)415

    3.6.4  本节小结418

    3.7  横展架构与分层架构418

    3.7.1  另一个与建筑业的类比419

    3.7.2  (经典的)分层架构419

    3.7.3  对纯组合式设计加以改进421

    3.7.4  最小化累积组件依赖度421

    3.7.5  基于继承的横展架构424

    3.7.6  横展架构与分层架构的测试427

    3.7.7  本节小结427

    3.8  避免不当的连接时依赖428

    3.8.1  不当的物理依赖428

    3.8.2  在单一技术上“押注”(坏主意)431

    3.8.3  本节小结436

    3.9  确保物理互操作性436

    3.9.1  妨碍层次化的复用是坏主意436

    3.9.2  领域特定的条件编译是坏主意437

    3.9.3  在库组件中的应用特定的依赖是坏主意439

    3.9.4  约束并排型复用是坏主意440

    3.9.5  防止故意的滥用不是目的441

    3.9.6  让组件侵占全局资源是坏主意441

    3.9.7  隐藏头文件来实现逻辑封装是坏主意441

    3.9.8  可复用库中存在对不可移植软件的依赖是坏主意443

    3.9.9  将潜在可复用软件隐藏起来是坏主意446

    3.9.10  本节小结447

    3.10  避免不必要的编译时依赖447

    3.10.1  封装不能杜绝编译时耦合447

    3.10.2  共享枚举和编译时耦合449

    3.10.3  C++中的编译时耦合比C语言中更为普遍451

    3.10.4  避免不必要的编译时耦合451

    3.10.5  避免编译时耦合的益处及真实示例454

    3.10.6  本节小结458

    3.11  架构隔离技术458

    3.11.1  封装与隔离的形式化定义459

    3.11.2  用组件的概念阐释封装与  隔离459

    3.11.3  整体隔离与部分隔离460

    3.11.4  架构显著的整体隔离技术461

    3.11.5  纯抽象接口(协议)类461

    3.11.6  完全隔离型具体包装器  组件467

    3.11.7  过程接口471

    3.11.8  隔离和动态加载库484

    3.11.9  面向服务的架构484

    3.11.10  本节小结485

    3.12  用组件进行设计485

    3.12.1  原先陈述的“需求”485

    3.12.2  实际(外延)的需求486

    3.12.3  用C++类型表示日期值487

    3.12.4  确定今天的日期值494

    3.12.5  确定给定日期值是否为工作日496

    3.12.6  解析和格式化功能508

    3.12.7  值的传输与持久化510

    3.12.8  债券计息日数惯例510

    3.12.9  日期数学510

    3.12.10  日期和日历实用件513

    3.12.11  充实分解透彻的实现515

    3.12.12  本节小结527

    3.13  小结529

    结论  536

    参考文献538
查看详情
相关图书 / 更多
大规模C++软件开发 卷1:过程与架构
大规模地震预警系统理论、技术与实践
王暾;潘臻;吴军;伍良燕;林鸿潮;韦瑶;刘顺章
大规模C++软件开发 卷1:过程与架构
大规模推荐系统实战
阿星(本名:张友雷
大规模C++软件开发 卷1:过程与架构
大规模储能系统优化规划与运行技术
张澄;黄强;胡泽春
大规模C++软件开发 卷1:过程与架构
大规模存储系统数据消冗
夏文 冯丹 华宇 邹翔宇
大规模C++软件开发 卷1:过程与架构
大规模应急医用物资配置策略及其优化研究
叶永 著
大规模C++软件开发 卷1:过程与架构
大规模MIMO网络的频谱、能量和硬件效率
Emil;Bjornson(埃米尔·比约尔森)
大规模C++软件开发 卷1:过程与架构
大规模C++软件开发 卷1 过程与架构(英文版)
约翰·拉科斯(John Lakos)
大规模C++软件开发 卷1:过程与架构
大规模时滞电力系统特征值计算(第2版)
叶华;刘玉田
大规模C++软件开发 卷1:过程与架构
大规模在线学习动力与质量:社会性知识网络视角
王帆
大规模C++软件开发 卷1:过程与架构
大规模英文语义树构建技术
冶忠林 著
大规模C++软件开发 卷1:过程与架构
大规模网络数据分析与空间自回归模型
黄丹阳
大规模C++软件开发 卷1:过程与架构
大规模深远海养殖模式的研究报告
林鸣
您可能感兴趣 / 更多
大规模C++软件开发 卷1:过程与架构
归属感:如何通过社群获得商业竞争优势
[美]大卫·斯平克斯(David Spinks) 著;颉腾文化 出品
大规模C++软件开发 卷1:过程与架构
《城市的夜晚》2024百班千人暑期书目小学生1年级名师推荐全新正版现货速发
[美]朱莉·唐宁 著;冷玉斌 冷念则 译
大规模C++软件开发 卷1:过程与架构
雪花的故事(用照片展示雪花的秘密,为你揭开冬日奇景的奥秘)
[美]马克·卡西诺[美]乔恩·尼尔森
大规模C++软件开发 卷1:过程与架构
进阶书系-国际史的技艺
[美] 马克·特拉亨伯格
大规模C++软件开发 卷1:过程与架构
杜甫传
[美]弗洛伦斯.艾思柯
大规模C++软件开发 卷1:过程与架构
神奇的数字零:从数字0开始的极简数学史和人类发展史
[美]查尔斯·塞弗(Charles Seife)著 杨杨立汝 译
大规模C++软件开发 卷1:过程与架构
爵士乐史(精装本)
[美]泰德·乔亚 著
大规模C++软件开发 卷1:过程与架构
环境的科学 (平装版)
[美]威廉·坎宁安 后浪
大规模C++软件开发 卷1:过程与架构
美利坚在燃烧:20世纪60年代以来的警察暴力与黑人反抗
[美]伊丽莎白·欣顿 著 胡位钧 译
大规模C++软件开发 卷1:过程与架构
数学侦探 游乐园里的古怪笑脸
[美]丹尼尔·肯尼 艾米丽·博艾尔 著 刘玙婧、王婧 译;小博集出品
大规模C++软件开发 卷1:过程与架构
儒教中国及其现代命运(三部曲)
[美]列文森 作者;[中]季剑青 译者
大规模C++软件开发 卷1:过程与架构
逃家小兔成长绘本系列
[美]玛格丽特.怀兹.布朗