Programming 版 (精华区)

侯捷观点(系列书评 1/2)
【C++/OOP 大系】
《程序员》2001.01
作者简介:侯捷,台湾电脑技术作家,着译评兼擅。常着文章自娱,颇示己志。
个人网站:http://www.jjhou.com
                    http://jjhou.readme.com.tw
北京镜站:http://expert.csdn.net/jjhou


●开场白
    《程序员》杂志邀我开一个专栏。我向来期待一本为程序员打造、以程序员为主体
对象的刊物,因此这样的邀请很难推却。再加上蒋涛先生与我的私交,我於是要求自己,
尽可能拨出时间来为《程序员》写稿。专栏可以开,能不能全无间断则不敢保证。
    大陆读者对我肯定陌生,容我简介自己。我是一名资讯教育工作者,写译书籍,培
训业界人员,主持网站回应读者与学员,并於大学开课。进入教育领域之前,我分别担
任过台湾工业技术研究院机械所和电通所的副研究员和特约研究员,分别研发 CAD/CAM 
软体和 Windows 多媒体系统。有人戏称工研院为少林寺 ─ 位在山上,男多女少,高手
如云,艺成下山闯荡江湖者不计其数。
    写这篇稿子的此刻,我投入教育领域正好十年。这是一条科技人很少想过的路子,
於我也是生命中一个不经意的转弯。不过,这种迥异於软体研发也迥异於象牙塔教学的
生涯,实在是多彩多姿,与读者的互动尤其曼妙无比。
    我的钻研领域,前七年都在 Windows 编程方法和作业系统原理,近三年则放在更基
础的、与平台无关的层面。


●书籍是永远的良师益友
    过去十年中,有一件事最是奇特有趣:我於 1993 开始《无责任书评》专栏,介绍我
所能够掌握的技术范围内的一些世界名着。这样的题材与文体,吸引了很多目光,也开创
了某种先河。《无责任书评》夹杂对台湾电脑出版业的观点与评论,由於当时台湾电脑
书的良窳程度极端不均(现在也是),初阶 滥而高阶贫血(现在也是),我以程序员的
角度所给的评论显得尖锐不群。
    1998 年网际网路兴盛,我把所有电脑散文都移到网路上发表,范围扩及学习方向与
学习态度(但不涉及细节技术)。过去的书评文章也重新整理了起来。各位可从侯捷网站
上看到所有这些文章。
    书评之所以受人欢迎,一方面在它的知识性,一方面在它的辛辣味。通常我的原则是
只评好书(该说是「荐」而不是「评」了),所以辛辣味只藏在旁徵博引的明喻暗讽之中
,或偶尔忍不住的一把火。一般而言,只要有丰富的知识含量,而不是单纯地将章节照
录一遍,书评专栏就够吸引人了,辛辣味只是附带红利。诸君如想尝尝真正的川辣子,
看看国外期刊的书评,肯定叫温良恭俭让的中国人频频抚胸,大惊失色。
    好书之於学习(尤其是自修),重要性自不待言,所以书评永远受欢迎。好书是一支
钓杆,好书评则让你认识这支钓杆并告诉你到哪儿去买。单一书评固然好,如果能系列化
、系统化、根据技术的演进与层次,铺陈一条学习的红地毯,就更有价值。过去我曾经
分篇为台湾读者介绍过 C++/OOP 方面的许多好书。做为本专栏的第一篇,我决定将它们
汇总结集,让你一次看饱买足。


●阅读之前
    往下阅读之前,我想先谈一些打底的话。
    
    第一,以下介绍的全都是外来书。各位购买这些书籍或许有经济压力,但毕竟它们都
是成名已久的世界名着,我想,为读者开这扇窗绝对是很重要的。
    购买这些书籍其实很方便,只要你有信用卡,连上亚马逊网路书店(www.amazon.com
)爱怎麽买就怎麽买。我们的困难可能在於信用卡和书价。唔,加上运费真的很贵。
    
    第二,在我少不更事的时候,读了一本好书并不会回头特别记下作者姓名。这是个绝
对错误的态度。茫茫书海中该如何选书?第一次当然是到书店去乱枪打鸟,浪费一点子弹
。但是你不能老停留在少不更事的阶段,你的子弹还有你的书架空间都很宝贵,你的时
间更宝贵。牢记优秀作家的名字,是找好书的捷径。这其实也是写阅环境的一个进步表
徵:让好作家有自己的品牌。

    第三,OO(Object-Oriented,物件导向)领域,从编程到设计,可概分为 OOP(
Progrmming)、OOA(Analysis)、OOD(Design)。目前国外十分成熟的 UML(Unified 
Modeling Language)属於OO 领域里头用来将设计概念表现出来的一种 notation(符号
表现法)。本篇文章只介绍到 OOP 这个层次(唯 [Gamma95]稍属例外),这比较具体,
比较贴近大部份程序员。愈往上去愈抽象,愈接近软体工程或方法论。第四,以下介绍的
这些 C++/OOP 书籍,几乎成为我初步判断一个人在这方面水平的基准。一个具备数年经
验的 C++ 程序员,或许自己能够摸索出「总是让 base class 拥有 virtual destructor
」这样的准则,但初出茅庐的程序员,恐怕连 virtual destructor 是什麽都不甚有概念
,更别说该如何正确运用它。如果他说他看过 [Meyers98],我会比较放心他的水平。
有趣的是,我曾经在自己班上(学生从大二到研究生都有)做了一个调查。拥有这些书
籍的学生人数并不多,而且老是同样几位。这让我感觉,强者恒强弱者恒弱,悲夫。就
我和业界的广泛接触经验,我也发现,许多程序员离开学校後就不太看书了,或者因为
忙碌,或者因为安於现况。专案做了不少,技术却没有精进太多。三两下招数一再用老
,人特别容易空乏。请你打开这扇窗,你会发现巨着之所以为巨着,专家经验之所以为
专家经验,是有道理的。愈是看了这些书,你愈会发现这些书的价值,并觉醒过去的一
些愚蠢行为。

    第五,下面开出来的书单都是我熟读过的,其中甚且不少繁体中文版是我翻译的,
所以我放心推荐并接受质询。然而书海浩瀚,遗珠难免。

    第六,为求方便,以下以学术界习惯的标示法,标示书籍代名。文中即使用这些代名
。凡有中文版者,我会特别加注。

[Ellis90]: The Annotated C++ Reference Manual, by Margaret A. Ellis and Bjar
ne Stroustrup, Addison-Wesley, 1990. 447 pages.
[Gamma95]: Design Patterns: Elements of Reusable Object-Oriented Software,
by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides, Addison-Wes
ley, 1995. 395 pages
简体中文版:《设计模式》,李英军等译,机械工业出版社,2000. 254 页
[Lippman98]: C++ Primer, 3rd Editoin, by Stanley Lippman and Josee Lajoie,
Addison Wesley Longman, 1998. 1237 pages.
繁体中文版:《C++ Primer 中文版》,侯捷译, 峰 1999. 1237 页
[Lippman96]: Inside the C++ Object Model, by Stanley Lippman, Addison Wesley
 Longman, 1996. 280 pages
繁体中文版:《深度探索 C++ 物件模型》,侯捷译, 峰 1998. 320 页
[Meyers96]: More Effective C++, by Scott Meyers, Addison-Wesley, 1996. 318 p
ages
繁体中文版:《More Effective C++ 中文版》,侯捷译,培生 2000. 318 页
[Meyers98]: Effective C++, Second Edition, by Scott Meyers. Addison Wesley L
ongman, 1998. 256 pages
繁体中文版:《Effective C++ 2/e 中文版》侯捷译,培生 2000. 256 页
[Struostrup97]: The C++ Programming Language, 3rd Editoin, by Bjarne Stroust
rup, Addison Wesley Longman, 1997. 910 pages
繁体中文版:《C++ 程式语言经典本》,叶秉哲译,儒林 1999.(未录总页数)
[Sutter99]: Exceptional C++, by Herb Sutter, Addison Wesley Longman, 2000. 2
08 pages
繁体中文版:《Exceptional C++ 中文版》侯捷译,培生 2000. 248 页



●层级一:语法/语意(C++)
    学习语言,当然首先从语法开始。初学者究竟要从轻松小品出发,或一开始就接触
巨着,殊无定论,因为初学者有很多种,「初学者」一词却无法反映他们的真实状态。
我的学生群中有 13 岁的,也有 31 岁的(年纪更大的当然也有),有人连电脑基本概
念都尚未建立,有人已是经验丰富的软体工程师。不同背景、不同年龄、不同领悟力、
不同学习速度的人,需要不同层级的教材来满足他们。同一个人在不同阶段,也需要不
同层面的教材来提升其功力与视野。
    但,不论新生或老手(新生有一天会变成老手),任何一位C++ 程序员,我都强烈
建议你的书架上要有 [Lippman98] 和 [Struostrup97] 这两本书。它们是 C++ 语法/语
意层面的百科全书;所有相关问题,这两本书都是最後仲裁,说了算!它们不适合连电脑
基本概念都缺乏的人,但颇为适合已有编程经验的人。
    这两本书都已经在 C++ 领域驰逞十年。最新版本都是第三版,印映 1998 定案的 
C++ 标准规格。由於 C++ 标准规格带入一个十分庞大的标准程式库,所以这两本书也都
比其前一版有巨幅的改变。如果要拿这两本书做特性比较,我的个人观感是,[Lippman98
] 适合做为教本,教学自修叁考皆宜,[Struostrup97]比较生涩难读,学术味重,叁考性
浓厚,权威性最高(毕竟 Struostrup 创造了 C++)。
    这两本书的每一版寿命大约是五年。C++ 标准规格定案後,国际标准组织(ISO)每
五年开会覆审一次,所以第三版至少也是五年寿命。也许有人以为,做为疑问辩论的最终
裁判,还是以 C++ 规格书为准(1998/09/01 出版,编号 ISO/IEC 14882),而且网路下
载只需 18 美元,PDF 格式,索引极为方便。这当然是很好的一份工具,但是这份文件
绝不适合做为学习材料,太硬了。
    目前全世界还没有任何一个 C++ 编译器支援完整的 C++ 标准规格,互有长短,所以
晚近新增的语言特性,不见得能够在你手上的编译器演练。关於 Visual C++, Borland C
++, CYGNUS C++ 三套工具在C++ 标准规格上的表现,我个人有一些经验,整理於http:
    //www.jjhou.com/qa-cpp-primer-27.txt。为什麽迟迟未有完全支援标准规格的 C++
编译器问世呢?因为这已经不成为市场竞争重点;C++ 开发工具市场已经转到对视窗介面
的支援以及对企业的完整解决方案。
    这两本书深具工具叁考价值,因此索引格外重要。两本繁体版译本皆用心地制作了索
引(仍以英文术语来排列),此可为大陆借镜。中文电脑书带有索引,在台湾亦不常见,
两本译本皆因译者的特别用心才得如此。索引采用英文术语,导出一个问题:如果书内
文本没有保留英文术语,怎麽办?索引的制作与配套办法,是科技翻译亟需深思的一个
问题。我的作法是,把诸多科技术语保留原文不译,并努力维持中英页页对照,这麽一
来原书索引就可以完整而轻松地保留下来。保留原文术语不译,不完全是为了索引的制
作,而是因为某些字眼强译为中文,不但与业界习惯脱节,也与世界脱节。我所采行的
这种作法受到很多读者的喜爱,但是哪些原文术语要保留,哪些要中译,又是见仁见智
。大凡如果译者真正是业内人士,他的选择不会脱离业界习惯太远。


●层级二:专家经验(C++/OOP)
    能够在学习语法并开始练习编程的同时,就接触专家的经验,最是理想,但实际上很
难如此。一方面,每一条经过淬炼的编程规则,其来龙去脉可能牵涉到多方面的知识,甚
至可能涉及底层技术,这对新手的负担过重。另一方面,初学者往往只顾眼前半亩田,
眼光没太高远。不过,如果有良师带引,依样画葫芦不失为一种初期的权宜学习方式。

    无论如何,为了提升自己的 OOP 功力,专家经验是一条终南捷径,让你一次吸取高
手十数年功力。[Meyers96] 和 [Meyers98] 是我极为推荐的两本专家经验书。以下试摘
书中条款数例,诸君可掂掂自己的斤两,看看自己平时实践了多少,从各条款中又联想了
多少。

⊙以下摘自 [Meyers98]:
条款1:尽量以 const 和 inline 取代 #define
条款2:尽量以 <iostream> 取代 <stdio.h>
条款3:尽量以 new 和 delete 取代 malloc() 和 free()
条款5:使用相同型式的 new 和 delete
条款6:记得在 destructors 中以 delete 对付 pointer member
条款7:为记忆体不足的状况预做准备
条款8:撰写 operator new 和 operator delete 时,应奉行惯常行为
条款9:避免遮掩了 new 的正规型式
条款10:如果你写了 operator new,请对应写一个 operator delete
条款11:classes 内如果动态配置记忆体,请为它宣告一个 copy constructor 和一个
 assignment 运算子
条款12:在 constructor 中尽量以 initialization 动作取代 assignment 动作
条款13:initialization list 中的 members 初始化排列次序应该和其在 class 内的
宣告次序相同
条款14:总是让 base class 拥有 virtual destructor
条款15:令 operator= 传回 *this 的 reference
条款16:在 operator= 中为所有的 data members 赋值。
条款17:在 operator= 中检查是否「自己赋值给自己」
条款19:区分 member functions, non-member functions 和 friend functions 三者

条款20:避免将 data members 放在公开介面中
条款21:尽可能使用 const
条款22:尽量使用 pass-by-reference(传址),少用 pass-by-value(传值)
条款23:当你必须传回一个 object 时,不要尝试传回一个 reference
条款29:避免传回内部资料的 handles
条款30:避免写出「传回 non-const pointers 或 references 并以之指向较低存取层
级之 members」的 member functions
条款31:千万不要传回「函式内的 local 物件的 reference」,或是「函式中以 new 
获得的指标的所指物件」。
条款32:尽可能延缓变数定义式的出现
条款33:明智地运用 inlining
条款34:将档案之间的编译相依关系(compilation dependencies)降至最低
条款35:确定你的 public inheritance 模塑出 "isa" 的关系
条款36:区分「介面继承(interface inheritance)」和「实作继承(implementatio
n inheritance)」
条款37:绝对不要重新定义一个继承而来的非虚拟函式
条款38:绝对不要重新定义一个继承而来的预设叁数值
条款39:避免在继承体系中做 cast down(向下转型)动作
条款40:透过 layering(分层技术)来模塑 has-a 或 is-implemented-in-terms-of 
的关系
条款41:区分 inheritance 和 templates
条款42:明智地运用 private inheritance(私有继承)
条款43:明智地运用多重继承(multiple inheritance,MI)
条款45:知道 C++(编译器)默默为我们完成和呼叫哪些函式
条款47:使用 non-local static objects 之前,确定它已有初值
条款49:尽量让自己熟悉 C++ 标准程式库
⊙以下摘自 [Meyers96]:
条款1:仔细区别 pointers 和 references
条款2:最好使用 C++ 转型运算子
条款3:绝对不要以 polymorphically(多型)方式来处理阵列
条款4:非必要不使用 default constructor
条款5:对自定的型别转换函式保持警觉
条款6:区别 increment/decrement 运算子的前序(prefix)和後序(postfix)型式
条款7:千万不要多载化 &&, ||, 和 , 运算子
条款8:了解各种不同意义的 new 和 delete
条款9:利用 destructors 避免遗失资源
条款10:在 constructors 内阻止资源遗失(resource leaks)
条款11:禁止异常讯息(exceptions)流出 destructors 之外
条款12:了解「丢出一个 exception」与「传递一个叁数」或「呼叫一个虚拟函式」之
间的差异
条款13:以 by reference 方式捕捉 exceptions
条款15:了解异常处理(exception handling)的成本
条款17:考虑使用 lazy evaluation
条款18:分期摊还预期的计算成本
条款19:了解暂时物件的来源
条款20:协助完成「传回值最佳化(RVO)」
条款21:利用多载化技术(overload)避免隐式型别转换
条款22:考虑以运算子的复合型式(op=)取代其独身型式(op)
条款24:了解 virtual functions、multiple inheritance、virtual base classes、

runtime type identification 所需的成本
条款25:将 constructor 和 non-member functions 虚拟化
条款26:限制某个 class 所能产生的物件数量
条款27:要求(或禁止)物件产生於 heap 之中
条款28:Smart Pointers(精灵指标)
条款29:Reference counting(叁用计数)
条款30:Proxy classes(替身类别、代理人类别)
条款31:让函式根据一个以上的物件型别来决定如何虚拟化
条款33:将非尾端类别(non-leaf classes)设计为抽象类别(abstract classes)

    其中条款25~31层次甚高,用来解决C++ 软体开发过程中一再出现的问题,作者把这
类问题及其解法称为 idioms(惯用法)或 patterns(样式),与着名的23个精典 patt
erns(见 [Gamma95])相呼应。虽然这里所谈的规模格局部都比较小,但正因为如此,
作者得以完成比较具体的实现,反而比 [Gamma95] 容易阅读。
    [Meyers96] 和 [Meyers98] 这两本书成名已久,获得极大的声誉。以下的赞美可以
使你更了解这两本书的性质和价值:

◆在你开始着手第一个真正的 C++ 专案之前,你应该阅读本书;在你获得一些实务经验
之後,你应该再读一遍。-- comp.lang.c++

◆作者不只提供你撰写 C++ 码时应该遵循的明白规则,也提供了深入的解释与范例。-
- Sun Expert

◆每一位 C++ 程式员不只应该拥有这本书,而且应该确实运用这本书。书中文字极易拿
来实际运用,交叉叁考与索引的功夫做得很好。-- Computer Language

◆这本绝妙好书提供的招数,帮助我们把 C++ 运用得更好。每一位 C++ 程式员桌上都
应该有这本书。在提升 C++ 程式设计的整体品质上, Scott Meyers 这份珍贵的礼物或
许比业内任何人士的贡献都大。-- Jesse Liberty, C++ Report
[Sutter99] 是另一本专家经验谈。作者是 C++ Report 期刊主编,并主持网路上一个名
为每周之星(a Guru of the Week,GotW)的 C++ 特别节目。以他的背景和经历,接触
的疑难杂症自然是又多又猛。这本书整理了 47 个条款,由於条款名称无法表现某种具
体准则,所以我不条列於此。本书主要分为八大项:

1. 泛型程式设计与 C++ 标准程式库
2. Exception-Safety(异常发生时仍安全)的主题与相关技术
3. Class 的设计与继承
4. 编译器防火墙(Firewalls)及 Pimpl 惯用手法
5. 名称查询、命名空间、介面原则
6. 记忆体管理
7. 陷阱、易犯错误与有害作法
8. 杂项主题

Scott Meyers 为此书所写的序,点出了这本书的特质:

『从语言的特性到标准程式库内的组件,再到程式编写技术,本书在不同的主题之间跳
跃,总是使你稍稍失去平衡,总是使你必须付出全然的注意力。...我把 GotW 发音为 
"Gotcha"(意思是「这下可逮到你了」),或许很适当。当我把书中测验的(我的)答
案拿来和 Sutter 的答案比较,我掉进他(和 C++)铺设的陷阱中 ─ 虽然我实在不想
承认这点。我几乎可以看见 Herb 微笑并温柔地对我所犯的每一个错误说 "Gotcha!"。
...当你选择 C++ 做为工具,你必须小心地思考你正在做些什麽。C++ 是一个威力强大
的语言,用来协助解决吃力的问题,其重要性使你必须尽可能面对语言本身、程式库、
程式惯用手法来磨炼你的知识。』
    就我的英文程度而言,[Sutter99] 读起来不若 [Meyers96] 和 [Meyers98] 那般平
顺,原因是其中用了很多厘语、口语、典故。举个例子,Morphy law 是什麽,大家知道
吗?(莫菲定律说:会出错的,一定会出错。)Machiavelli 又代表了什麽意思?(意
大利政治家,以诈术闻名。)
    这类专家经验谈,多半薄而贵,但贵得有价值。好消息是,[Meyers96] 和 [Meyers
98] 已经集结为电子书,以光碟呈现,采用 HTML 格式,可使用任何支援 Java(以便进
行全文检索)的浏览器阅读。多少钱一片?请上亚马逊瞧瞧。


●层级三:底层机制(C++ Object Model)
    如果对於迥异传统编程方式的 C++ 特性,诸如 virtual functions、constructors
、destructors┅等特异功能一直无法心领神会,可能有必要到内部机制去深度游历一
番。不要以为钻到这麽深层的技术,会愈搞愈糊涂,愈搞愈恍忽。很多人,包括我自己,
是在游历过底层机制一遍之後,才彻底觉悟并接受了 C++。
    所谓底层机制主要是指 (1) object 的记忆体布局:data members 分布在哪里?加
了 static 又如何?member functions 分布在哪里?加了 virtual 又如何?有了继承又
如何?(2) constructors 和 destructors为什麽会自动被唤起?(3) template 模板机制
是怎麽回事?(4) this 指标是怎麽回事?(5) runtime type identification(RTTI)
是怎麽实作出来的?
    知道了这些底层机制,你便能够对自己在 C++ 程式中的每一个动作所引发的影响,
了如指掌。学习这些底层技术,不是为了自行开发一套编译器,而是为了彻底掌握 C++ 
语言;底层技术的学习,只是过程,不是目标。这种情况和《深入浅出 MFC》(侯捷着,
松岗 1997)的情况很像,数万名读者不是为了自行开发 framework 而欢喜阅读该书对 M
FC 的剖析,是为了彻底掌握自己在撰写 MFC 应用程式时的一言一行。
    底层机制方面的专论书籍非常稀少。我所仅见的两本,一是 [Ellis90],一是 [Lipp
man96]。前者被昵称为 ARM(带注解的叁考手册),是早期 C++ 编译器的实作依循准
则,但因年代过远,我宁愿更推荐後者。[Lippman96] 笔误非常多,我翻译此书的过程中
至少修正了100 个以上的笔误。
    了解事务的本质,到底有没有必要?这个问题太简单了:如果你必须走那麽一遭,才
能接受事务的表徵,那麽於你就有必要。如果你天生是个 OO 奇才,或你一开始接触的第
一个语言就是OO 语言,以至於有可能认为其中的一切都是理所当然,可以完全领受各种
特性的运用,那麽底层机制於你就不需要。
    我个人是如此地真正第一线面对大量的学习者,就我的教学经验(乃至於我个人的学
习经验),我要说,了解事务的本质,对绝大多数人都有极正面的帮助。关於这一点,我
最喜欢引用林语堂先生在《朱门》一书里头的一句话:『只用一样东西,不明白它的道
理,实在不高明。』


●层级四:设计观念的复用(C++/Patterns)
    软体工程的所有努力,无非是为了美好的复用性(reusibility)。从早期的subr-
outines, procedures, functions, 到後来的 classes, templates。在在为了相同的目
标。如今我们已经能够将「资料,以及处理资料的动作」封装得很好,甚至能够把资料
型别都抽取出来成为叁数,甚至更进一步将资料本体和处理资料的各种演算法独立开来,
各自发展而又能够藉着某种「黏胶」彼此作用(注)。
    注:这便是所谓泛型编程(generic programming)的精神。下个月我为大家介绍这
个主题。
    很好,很好。但是长久以来我们却无法将设计概念以规格化的方式传承下去。面对
资料结构(data structures),我们只要说 stack, queue, list, 不必多言,闻者马
上就知道stack 是先进後出,queue 是先进先出,list 是单向或双向串链。面对演算法
(algorithms),我们只要说 quick-sort 和 binary-search,不必多言,闻者马上就
知道其复杂度分别是 O(N log N) 和 O(log N),其行为模式如何如何。但是当我们希望
保证某个 class 在整个系统中只有一份 object 时,该如何设计?当我们希望对某个 
object 架构出一个替身(或说代理人)以控制对本尊的存取(进而达成缓式评估lazy-
-evaluation)时,该如何设计?当我们希望以某种方法走过某个聚合物件内某一范围的
所有元素,而不需曝露该物件的底层结构时,该如何设计?当我们希望以共享方式来处理
系统中的基本元素(例如庞大文档内数量相对极少的基本字符)时,该如何设计?
    如果这些一再被反覆大量运用、并且早经众人淬炼出极佳作法的设计(一整组解决
方案),能够系统化地分类整理,给定标准名称、定义、效果、实作法、甚至示例代码,
我们就不必每次都从轮子造起(还造得不比专家圆呢)。如果程序员之间只要说Singleto
n, Proxy, Iterator, Flyweight,闻者马上知道其背後代表的是某种特定设计,有着特
定的逻辑,用以解决某种特定问题,可多好。这正是将设计观念及其实作逻辑的宝贵经
验,以简洁而可复用的形式表达出来。
    [Gamma95] 一书内含精心整理的 23 个 design patterns。四位作者的主要贡献不
在於 patterns 的创建,而在於 patterns 的整理形式与发扬光大。书中所提的 patt-
erns 名称,几乎已经成为 OO 设计领域里头的标准辞汇。《程序员》去年 11 月份有
一份蒋涛先生针对 [Gamma95] 的评论,其中对於 patterns 的比喻,令人激赏:
『patterns 需要反复练习体会,才能应用自如。这有点像围棋中的定式,围棋定式是
百年来高手下法的总结,但不能简单地应用,要看场合选择合适的定式,还要按棋理变通
下法。』幸运,真幸运,[Gamma95] 也有电子书出版,以光碟呈现,采用 HTML 格式,可
使用任何支援 Java(以便进行全文检索)的浏览器阅读。
    程式设计究竟是一门工匠技艺还是一门艺术?都可以是!看你从哪个角度出发。有人
说连设计概念都可以以 patterns 规格化地传承,还谈什麽艺术?如果你是这样想,我说
三件事给你听。建筑是一门技术还是艺术?很多人都认为建筑是一门艺术。然而 patte
rns 的概念正是滥觞於建筑设计领域。目前软体界所使用的 pattern 一词源自建筑理论
大师 Christopher Alexander 的着作,他的书探讨的虽然都是建筑设计与都市规划的课
题,但其精神与本质却适用其它领域,包括软体开发。另一件事是,软体界开始流行 f
ramework 工具时,也有人认为程式主框架都被限死了,谈什麽设计与弹性?我说:只要
馒头好吃,我从不在乎是机器馒头还是纯手工精制。你的设计精力应该放在专业领域如
绘图、影像处理、统计、数学分析┅,而不是放在共通的基础框架上。如果你真的对基
础共通的事务感兴趣,你不应走应用软体开发之路,应该将设计天份用来研究更新更好
的资料结构,更新更好的演算法,更新更好的框架。


●线性学习?没的事!
    虽然我把 C++/OOP 的学习阶段分为四层,但除了第四层得万事俱备才能水到渠成,
其他三层的学习并不是那麽泾渭分明。通常你要你的C++ 坚轫锋利,你得让它历经多次
回火,在高热和骤冷之间 炼,在学术与实用之间震荡。我无法为你画出一条单行道,你
势必得走些回头路,时而品味一下曾经忽略的小花,时而啜饮一口被你遗忘的甘泉,填实
了某种缝隙之後,才能神清气爽充实盈满地再出发。


-- the end

[百宝箱] [返回首页] [上级目录] [根目录] [返回顶部] [刷新] [返回]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:211.143毫秒