基本信息
- 原书名:Large-Scale C++ Software Design
- 原出版社: Addison-Wesley Professional

编辑推荐
由世界级软件开发大师John Lakos撰写,深度解析C++大型系统的物理设计和逻辑设计,是C++程序设计领域最有影响力的著作之一。
从物理设计和逻辑设计两方面,全方位阐释大型和超大型C++软件开发应该遵循的一系列设计规则,结合大量编程实例,深入探讨设计易测试、易维护和可重用的高质量大规模C++软件产品的各种技术和方法规模。
内容简介
计算机书籍
《大规模C++程序设计》由世界级软件开发大师John Lakos亲笔撰写,是C++程序设计领域最有影响力的著作之一。作者结合自己多年从事大规模C++项目的开发经验,详细介绍了大规模C++程序设计涉及的一系列概念、理论、原理、设计规则及编程规范,并通过大量真实世界的编程示例,深入解析物理设计与逻辑设计的一些新概念和新理论,阐明在开发大型和超大型C++软件项目时应该遵循的一系列设计规则,论述了设计具有易测试、易维护和可重用等特性的高质量大规模C++软件产品的方法。
《大规模C++程序设计》分为三部分,共11章:第0章是概述;第一部分(第1-2章)介绍C++语言开发的一些基础知识、通用设计模式,以及C++项目开发中应该遵守的一些基本软件设计原则:第二部分(第 3-7章)全面介绍优秀物理设计的基本概念,设计的基本单元组件、物理层次结构、系统分层技术、隔离技术等,详细阐述如何利用合理的物理设计层次结构,通过隔离、增量和分层测试以更低的成本获得更高的可靠性,如何利用分层技术降低系统内的链接依赖性,如何利用隔离技术减轻或消除编译时依赖性,并讲解如何将这些技术应用到超大型系统中;第三部分(第8-10章)讲解逻辑设计问题,包括组件总体设计需要考虑的重要因素,详细阐述创建一个组件的功能接口所涉及的问题,以及在大型项目环境中实现对象的特定组织问题。
作译者
世界级软件开发大师,现为Bloomberg公司经理,带领BDE团队使用基于组件的方法和过程开发精密可重用的C++软件,同时,他还经常指导其他软件基础设施部门的工程师和团队主管。Lakos自1987年起就一直使用C++进行专业编程,之前曾担任 Mentor Graphics公司高级软件工程师、哥伦比亚大学计算机学院客座教授、Bear Stearns公司MDP(Managing Director Principie)。
刘冰
重庆邮电大学计算机科学与技术学院讲师,重庆大学计算机学院在读博士生。先后荣获重庆邮电大学优秀青年教师、优秀班主任等荣誉称号。曾获国家专利授权1项,编著教材5部,译著1部,参与国家级项目3项,主研重庆市市级项目4项。
张林
重庆邮电大学讲师,主要从事嵌入式系统、无线宽带网络、未来网络研究。发表论文5篇,编写教材2部。主要讲授的课程包括:大学计算机基础、C语言程序设计、面向对象编程——C++、软件技术基础、Windows程序设计、面向对象编程——Java。
目录
译者序
前 言
第0章 概述 1
0.1 从C到C++ 1
0.2 使用C++开发大型项目 2
0.3 重用 9
0.4 质量 10
0.5 软件开发工具 12
0.6 小结 12
第一部分 基 础 知 识
第1章 预备知识 15
1.1 多文件C++程序 15
1.2 typedef声明 22
1.3 断言语句 22
1.4 编程风格 23
1.5 迭代器 28
1.6 逻辑设计表示法 34
1.7 继承与分层 40
1.8 最小化 41
译者序
本书作者John Lakos曾在Mentor Graphics公司IC部门工作,从事大规模C++项目的研发工作。Mentor Graphics公司是首先尝试真正的大规模C++项目的公司之一。Lakos从1987年开始就一直使用C++进行专业的大规模的软件编程,并于1990年在哥伦比亚大学开设了面向对象编程方面的研究生课程。
作者结合自己多年从事大规模C++项目的开发经验精心设计并写作了本书,书中所介绍的一系列概念、理论、原理、设计规则及编程规范可以作为每一个开发团队制定实际开发标准的基础,更是每一位C++程序员应该遵循的准则。其中特别有价值的是一些来自真实世界的编程示例,这些示例说明了物理设计和逻辑设计的一些新概念和新理论,阐明了在从事大规模和超大规模C++软件项目时应该遵循的一系列设计规则,论述了具有易测试、易维护和可重用等特性的高质量大规模C++软件产品的设计方法。
许多阅读过本书英文版的读者可能会认为本书比较难读。真正理解本书的一般性内容需要花一些时间,融会贯通则更需要下功夫。理解本书的内容不仅需要花费大量的阅读时间,还需要花费更多的时间去从事C++的开发实践。如果读者致力于将自己发展成从事大规模C++开发的专业人员,或者要在计算机方面的技术领域中长期工作下去,读者从本书中收获的将与阅读和实践所花费的时间成正比。
由于作者有着极其丰富的实践经验,因此,当他想要论述一个问题、提出一个观点时,常会想到在自己长期实践中最适合说明这个问题的示例,用几句简短的话引述有关的情况。因此,在论述中作者有时会不知不觉地将某些并不显然的东西当成是不言自明的事情提出来。而对于许多初学者而言,这些都可能成为学习中的障碍。
本书是重庆邮电大学的刘冰老师在重庆大学做访问学者期间,与重庆大学的周尚波教授共同合作完成的一部译著,并获得重庆邮电大学出版基金的资助。其中第0章、第1章、第2章、第3章、第8章、第9章、第10章由刘冰老师翻译完成,第4章、第5章、第6章及第7章由张林老师翻译完成,周尚波博导对全书进行了译校和审定,重庆大学的博士及硕士研究生谢江安、尹学辉、宋新颖、王伟、李金芝、吴操、李文琛、罗捷、杨晗、陈淑芳,重庆邮电大学的本科生陈伟、李竹君等同学也参与了各个章节的校对工作。在翻译本书的过程中,我们查阅了大量的C++资料,并参考了2003年李师贤等人的翻译版本。本书从翻译到审校直至最终成稿历时半年多,限于译校者水平所限,译文中不当之处,恳请读者批评指正。
周尚波、刘冰
shbzhou@cqu.edu.cn;liubing@cqupt.edu.cn
前言
早在1985年,Mentor Graphics公司就是最早使用C++开发实际大型项目的公司之一。那时,没有人知道该如何开发大型项目,也没有人预料到未有过使用经验的项目构建方法会出现这样的问题——成本超支、计划延迟、可执行文件庞大、性能低劣,以及构建时间昂贵得令人难以置信。
一路走来,我们收获了许多宝贵的经验教训——知识的获取是一个痛苦的过程。没有书籍可以帮助指导这种设计过程,也从未有人在如此大规模的系统上尝试使用面向对象的设计。
十年来,由于积累了大量有价值的经验,Mentor Graphics公司使用C++开发完成了数个大型软件系统,同时也为其他使用C++进行大项目开发的人开辟了一条道路,使他们不用再付出高昂的代价。
在十三年的C语言(后来转为C++语言)计算机辅助设计(Computer Aided Design,CAD)软件开发生涯中,我已经多次体会到:提前计划总会产生出更高质量、更易维护的软件产品。在Mentor Graphics公司,我一直强调要从项目的一开始就确保质量,要把确保质量作为设计过程中一个必不可少的组成部分。
1990年,我在哥伦比亚大学开始讲授研究生课程“面向对象设计与编程”。自1991年以来,作为这门课程的教师,我有机会将我们在Mentor Graphics公司从工业化软件开发过程中获得的许多经验与学生一起分享。来自数百个研究生和专业程序员的提问及反馈信息,帮助我明确了许多重要的概念。本书正是这些经验的总结。据我所知,这是第一本指导开发大型C++项目的书籍,也是第一本针对大型C++项目中出现的软件质量相关问题的书籍。我希望这些资料对于读者的工作非常有帮助,如同在我的工作中一样实用。
适用读者
本书主要是为有经验的C++软件开发人员、系统架构师和具有前瞻性的质量保证专业人员而写的。本书尤其适合那些致力于大规模软件开发(如数据库、操作系统、编译器和框架等)的人员阅读。
使用C++开发一个大规模软件系统,不仅要充分理解逻辑设计问题,与C++编程有关的大部分书籍中都包括了这些逻辑设计问题。若要进行有效的设计,还需要掌握物理设计概念,尽管这些物理设计概念与开发的技术紧密相关,但是物理设计概念的某些方面即便是专家级的软件开发人员也可能仅有很少的经验或者根本就没有经验。
当然,本书中提出的大多数建议也适用于小型项目。对于开发者来说,典型的做法是从一个小型项目开始,然后开始接触更具有挑战性的更大型项目。一个特定项目的范围经常会扩展,即使开始时是一个小型项目,后来也会变成一个大型项目。但是,在大型项目中忽略最佳实践策略所产生的直接后果比在一个较小型项目中要严重得多。
本书将高层设计概念与特定的C++编程规范结合起来,以满足下面两类需求:
(1)对面向对象设计,尤其侧重C++编程语言实际应用的书籍的需求;
(2)对描述如何使用C++编程语言开发非常大型系统的书籍的需求。
毫无疑问,这是一本进阶的书籍。本书既不适用于初学C++语法的读者,也不适合于用来学习未曾掌握的C++语法的读者。本书要教你如何充分有效地利用C++的全部功能去开发超大型系统。
总之,如果认为自己对C++已经掌握得很好了,但是想要了解更多的关于在大规模项目中如何有效地使用C++语言的内容,那么这本书是非常适合你的。
书中的例子
大部分人是通过例子来学习的。通常,我会提供更有实际意义的例子,避免采用只讲解设计的一方面,而在另外一些方面有明显错误的例子。我也尽力避免只讲述编程语言细节,而没有其他意义的例子。
除非特别指出,本书中的所有例子都表示“良好的设计。”因此,前几章介绍的例子与书中的所有推荐实践都是一致的。本书采用这种方式讲解的缺点是:大家在本书中所看到的示例代码可能与以往看到的代码有所不同,而此时可能还不能准确地知道为什么会不同。我认为,对本书提供的所有例子综合借鉴,可以弥补这个不足。
这些例子有两个地方值得注意:注释和包前缀(package prefix)。为了节省篇幅本书许多例子的注释直接省略了。所有出现的注释都是少而精的。不过遗憾的是,这里就是要求读者 “照我说的去做,而不是照我做的那样做”的地方——至少在本书中是这样的。让读者可以放心的是,在实践中,我在编写接口的时候添加了详细的注释,而不是在编写接口之后才添加注释。
第二个需要注意的是,本书前面几个例子中的包前缀使用不一致。在大型项目环境中包前缀是必需的,但是使用起来有些棘手,需要适应一段时间。在第7章正式提出来之前,我选择不使用注册的包前缀,以便能专注于介绍其他重要的基础内容。
书摘
概述
开发优秀的C++程序并非易事。随着项目变得更大,使用C++开发高可靠性和易维护的软件变得更加困难,而且会涉及许多新概念。正如木匠建造一栋房屋所获取的经验不适用于建造一栋摩天大楼一样,从开发小型C++项目那里学到的许多技术经验和实践经验也不能直接扩展运用至大型项目开发。
本书是关于如何设计超大型高质量软件系统的。本书适合经验丰富、努力构造易于维护且高度可测试的软件体系结构的C++开发者。本书不是关于编程理论方法的书籍,而是引导开发者成功开发大型C++项目的全面实用指南。本书是精通C++的程序员在开发大型多站点系统方面多年经验的总结。我们将会展示如何设计一个需要数以百计的程序员、成千上万的类和上百万行C++源代码的系统。
本章涉及使用C++开发大型项目时所遇到的某些问题,并为前几章要做的基础工作提供背景知识介绍。本章使用了许多未定义的术语,大部分术语应该能够根据上下文理解。后面的章节会更精确地定义这些术语。实际的效果将在第5章给出,在第5章我们开始应用具体的技术以减少C++系统中的耦合(即相互依赖的程度)。
0.1从C到C++
人们普遍认为在管理大型系统的复杂性方面,面向对象范型存在潜在优势。在写作本书时,C++程序员的数量每7~9个月就会成倍增加。在经验丰富的C++程序员手上,C++是人工技能和工程人才强有力的放大工具。但是,如果你认为在大型项目中,只要使用C++就会确保成功,那就完全错了。
C++不仅仅是C的扩展:C++支持一种全新的范型。面向对象范型声名狼藉,因为面向对象范型比相应的面向过程技术需要更多的设计工作和悟性。C++比C更难掌握,并且有无数情形会让程序员搬起石头砸自己的脚。通常,当已经无法修复错误并满足项目进度要求时,你才可能意识到一个错误的严重程度。即使是相当小的错误(像随意使用虚函数或者通过值传递用户自定义类型),在完全正确的C++程序中,也可能导致运行速度比你用C编写的程序慢十倍。
最初接触C++,总有这样一个过程,在这个过程中,编程效率将会逐渐陷入停滞,因为似乎有无限种可供选择的设计方案需要探究。在此期间,当传统过程式的程序员想要竭力掌握面向对象的概念时,他们会深感焦虑。
对于最有经验的专业C程序员来说,尽管C++语言的规模和复杂程度在开始时可能有些难以承受,但是有能力的C程序员用不了多久就可以写出一个小的、普通的可运行C++程序。不幸的是,使用C++创建小型项目的技术完全不能直接用于应对大型项目。也就是说,C++技术的简单应用扩展到大型项目中效果不佳。在此,缺乏经验会导致诸多后果。
0.2使用C++开发大型项目
如同C程序一样,写得很糟糕的C++程序可能会难以理解和维护。如果接口没有完全封装,则很难进行调整或者加强实现。糟糕的封装将会阻碍重用,也可能会导致可测试性方面的优势完全消失。
与流行的观点相反,从根本上说,面向对象程序最常见的形式比相对应的面向过程的程序更难测试和验证。通过虚函数改变内部行为的能力会使类不变量无效,这些类不变量对于纠正性能是必不可少的。而且,贯穿一个面向对象系统的控制流路径潜在数量可能会爆炸性地增大。
幸好,没有必要编写如此随意的、通用的(并且不可测试的)面向对象程序。我们可以将范型的使用限定在一个更易测试的子集中以获得可靠性。
当程序规模变得更大时,不同属性的效力就开始起作用。下面各节举例说明我们可能会遇到的一些问题的具体实例。
0.2.1循环依赖
作为一名软件专业人士,你可能已经遇到过这样的情况:第一次查看一个软件系统,似乎找不到一个合理的起点或者自身有意义的系统片段。不能独立理解或者使用系统的任何部分,这就是循环依赖设计的一种症状。C++对象有一种显著的相互混杂的倾向。这种紧密物理耦合的示意如图0-1所示。一个电路由诸多元件和导线构成。因此,类Circuit知道Element和Wire的定义。一个元件知道它所属的电路,而且可以分辨出是否与特定导线相连。因此类Element也知道Circuit和Wire。最后,一根导线也可以链接到一个元件或者一个电路的端子。为了可以完成电路的工作,类Wire必须同时访问Element和Circuit的定义。
图0-1循环依赖的组件
Circuit、Element和Wire这三种对象类型的定义驻留在不同的物理组件(编译单元)中,以提高模块化程度。尽管这些单个类型的实现通过它们的接口完全封装,然而,每个部件的.c文件都必须包含其他两个组件的头文件,结果导致这三个组件的依赖图是循环的。也就是说,在没有其他两个组件的情况下,没有一个组件可以单独使用或测试。
草率构建的大型系统因为循环依赖往往会紧密耦合并且强烈抵抗分解。支持这样的系统会是一场噩梦,而且对其进行有效的模块化测试通常是不可能的。