2008年9月30日星期二

名人译书要慎读

最近我在看《C++语言的设计与演化》(英文名:The design and evolution of C++ )一书。我买技术书,只要有原版的,我基本上都是买原版,宁愿看得吃力点也要买。为什么,就是怕了那些胡乱翻译的中文版,知识没学到不说,还有可能曲解原文,把我往错误的方向上领。那我自己看原文一定就能理解正确?非也,我的英文虽说还可以,但是老实说,比起那些成天译书的人总是要差些的。但是就算我自己理解错误,那也是我自己的事,怪不得别人,但我却不希望别人来误导我。

以前,我对一些有名的学者翻译的书还是比较认可的,语句通顺,用词准确规范,还会顺带纠正些原文的错误,从实际效果看的确能加快阅读和学习的速度。一般性这些人的名字也保证了译文的质量,让我比较放心。但是现在,在这种浮躁的社会气氛下,名人也开始擦烂污了。

就拿我手上的这本《C++语言的设计与演化》来说吧。译者为国内知名学者裘宗燕老师。裘老师译过很多书,在网上评价很高。但是很不巧,我就买过这一本,因此我也只能拿这本书说事。这本书语句还是很通顺的,用词也中规中矩,符合技术书籍的性质。而唯一让我气恼的是他也有名人的通病,喜欢自创术语。大家都知道,技术术语一般都是非正式的一种约定成俗的说法。但是时间长了,大家也熟悉了。一个大家都使用,都熟悉的术语就好比标准,有利于沟通,有利于教育和学习。然而,有部分人就喜欢标新立异,他的想法是什么,我不得而知,也不想过问,但是我最恨这种做法。在《C++语言的设计与演化》这本书中,一些约定成俗的术语,比如构造函数(constructor),类型转换(casting)等都被改头换面。比如构造函数变成建构函数,类型转换偏离愿意更多,变成了“强制”。老实说,我一开始还蒙了呢,当第一次看到这个术语,我在想,C++里面有叫“强制”的特性么?后来下了本原版pdf,才知道是casting。其实,在这里用强制则完全没有理解casting在C++中的意义。类型转换本身有强制转换和非强制转换之分,怎么能一棒打死全叫强制呢。其实这里翻成类型转换或者台湾术语转型都是可以的,至少是让人比较容易接受的。但总的来说,这本书其他地方翻的还行,没有明显的逻辑错误,可能就是这几个地方裘老头犯傻了一次吧。

我见过术语篡改最厉害,翻译的最过火的莫过于翻《UML精粹》第三版的徐家福老先生了。曾有人提到这位老先生的地位,似乎也是中国计算机界的泰山北斗了。不过我对这种一向不感冒,我喜欢看到实际的东西。而我看到的却是一本几乎翻成文言文的技术书,用时下流行的话说,我被雷到了。老先生文学功底自然不俗,但是用来翻译技术书籍,除了卖弄风骚,我想不出其他评价了。当然,里面的术语几乎都被重定义过了,还好老头子没有做绝,把原文单词放在那里,也幸好我比较熟悉,直接过滤中文,看英文,最后实在受不了了,下了本原本,嗯,martin fowler的英文的确不错。

另外要说的就是挂羊头,卖狗肉,也就是俗称的贴牌。我们从代加工行业熟悉了这个词,现在已经引用到翻译技术书籍上头来了。很多书,挂着名人的牌,实际都是别人翻译的。比如一些有名的教授挂名的书,实际上都是其研究生翻译的。这也算是一种潜规则吧。想想这些教授也一大把年纪了,犯得着挑灯夜战,一句一句去翻译技术书籍么。这点稿费还不及人家走个穴呢。不过有些教授还是有良心的,至少最后校审一下,有些就是黑了心,直接挂名就发书了。大家可以想象这个书的质量。我感受比较深的有几本书,barbara liskov的《程序开发原理--抽象、规格与面向对象设计》,bjarne stroustrup的《C++编程语言特别版》等。因为里面都有对原文的曲解和误解。不过这也难怪,我也是对着那几句话反复研究才搞懂作者的真正意思的。对于译者来说,那是有时间限制的,不可能像我那样逐字逐句地去斟酌。另外,这两本书,也是我看过的最难的书。但是,我觉得越是难的书,越应该买英文原版,好处么,自己去体会吧。

说了这么多,我觉得比较好的一个模式是,买本中文书,再下载个英文原版,或者买英文版,下载个中文版。目的就是对于那种不大可能错误的地方花最少的力气,用最快的速度通过。而比较有价值又比较困难的地方,则使用原版来保证质量。这也是我现在使用的模式。

2008年9月26日星期五

C++中控制对象的创建

在C++中,可以通过很多方法来定义对象的创建方式和地点。

1. 将构造函数设为私用,可以阻止直接创建。
这个方法是最常见的,恐怕我们最熟悉的就是单件模式(Singleton)。通过类的静态方法来创建对象,以达到控制对象个数的目的。
实际上,这种情况下也就直接阻止了派生。因为C++要求派生类要显示或隐式调用基类的构造函数。但是,真的没法派生了?当你要为这个类增加功能,又不想破坏现有的代码时,你会怎么做呢?
看看下面的代码:


class B{
friend D;
B(){};
}

class D{
public:
D();
D(int);
}

D d;

class DD:public D{}; // error, DD::DD() cannot access

是的,可以通过友元来获取访问权限,这样就可以在原来基类的基础上扩充功能了。而且这个派生类仍旧延续了之前的语义,无法被继承,因为DD无法访问在最上层的B::B()。

2. 利用私有的析构函数阻止派生,堆栈和全局分配。
析构函数声明为私用就可以避免堆栈和全局分配。这样做还能防止随便使用Delete,这种类的典型使用需要一个高度优化的自由存储分配系统。

析构函数声明为私用也可以用来阻止派生。这时候,构造函数最好也设计成私有,这样可以保证创建和销毁的语义相同。当然,取巧的方法也有,只要简单的重载delete操作符即可。但是这样恐怕只能通过编译,仍然无法访问基类的析构函数,因此可能会造成内存泄漏。

3.阻止复制的语义
把复制构造函数设为私用就可以防止复制构造,同理可以用在赋值操作符上面。按照Effective C++的建议,当显式提供了复制构造函数,最好也要提供赋值操作符,同时,他们两个在复制对象内容上有一致的语义。

4.用Placement new指定对象的内存地址
Placement new语义是用户自己指定一块内存,用来存放类的对象。
一般使用new来创建对象,对象的存放位置无法控制,只能由系统来确定。
而Placement new却可以控制对象的存放位置。

Class X{
//....
}

void * pv = malloc(sizeof(X) *1000);
X* pX = new(pv) X();

事实上这和一般的new区别不大。一般的new是先申请一块空间,大小为sizeof(X)+delta。(delta是cookie的大小。cookie是用来记录在自由存储区请求内存大小及其他信息的一个系统实现,隐藏在应用程序背后,我们看不到,也不需要管,在window和unix上cookie的大小略有不同。)然后再把这块空间的首地址转换成X*,接着在上面调用X的构造函数,填充这块区域,完成初始化。

Placement new只不过是自己决定了空间的大小,以及确定了起始位置。Placement new主要用于批量构造对象,比如1000个X连续排在一起。这样一方面减少了cookie数量(从1000->1),也能够使访问更迅速(在一块连续的存储上)。

但是注意使用placement new时可能会造成内存泄漏,也就是在Placement new所返回的内存中,如果有指针指向其他的自由内存的话,当调用构造函数之后,很可能把该指针覆盖掉,这样那块自由内存就“丢失”了。

2008年9月25日星期四

Track Active Item in Solution Explorer

我现在所在的项目规模很大,在solution中的源文件就有几千个。平时编辑的时候要全部展开是不可能的,特别是对于我这样的新进员工,一下子接触到这么大的Project还真有点摸不着头脑。

这几天我发现一个问题;当我在编辑某个文件的时候,我很希望看到Solution Explorer同时帮我定位到那个文件,这样我可以看到该文件在项目中的哪个项目的哪个子目录之下,这有助于我了解程序的逻辑结构。同时也因为这个项目中的文件的物理结构和逻辑结构完全对应不上,使我没法通过物理结构直接映射到逻辑结构(也就是在Solution Explorer中的树结构)。因此,Track Active Item这个功能对我而言很有必要了。然而,当默认安装好VS2005之后,这个功能是没有的。

于是我很愚蠢的花了3个多小时时间,研究了VS2005的宏编程,写了一个宏,当我选中某个文件的时候,Solution Explorer会自动定位到那个文件,必要时会自动展开。还洋洋得意的把这个宏发给同事。结果,同事告诉我,在VS2005中早已有这样的设置,我这是在重新发明轮子的傻事。

VS2005中的设置在Tools->Option里面,如下图



另外,这里也附上我写的宏,以纪念这次愚蠢的行动。


Public Sub LocateFileInSolutionExplorer()

' Get the UIHierarchy
Dim oUih As UIHierarchy = DTE.ToolWindows.SolutionExplorer

' Check if there is solution exists
If (oUih.UIHierarchyItems.Count = 0) Then
Return
End If

' Get the top level item in UIHierarchy.(solution)
Dim oUihSln As UIHierarchyItem = oUih.UIHierarchyItems.Item(1)

' Reverse finding corressponding parent until solution node.
Dim oItem As Object = DTE.ActiveDocument.ProjectItem
Dim oPath As String = oItem.Name

While Not (TypeOf oItem Is Project)
oItem = oItem.Collection.Parent
oPath = oItem.Name & "\" & oPath
End While

'Construct item path
oPath = oUihSln.Name & "\" & oPath
'Select this file
oUih.GetItem(oPath).Select(vsUISelectionType.vsUISelectionTypeSelect)
'Activate the solution window so the selected file is hilighted
DTE.Windows.Item(EnvDTE.Constants.vsWindowKindSolutionExplorer).Activate()

End Sub




这个事情给我的教训是,当遇到问题时,首先问问周围的人,然后Google一下,再去Usenet问一下,最后才自己动手。除非是想学习某样技术,否则没有必要浪费时间重新发明轮子。

2008年9月24日星期三

The Returns of Heroes -- SE3

英雄第三季悄声无息的突然出现了。我原来以为编剧已经编不下去了,也就放弃了追片。没想到在不经意间英雄回归了,而且一下子出来了两集。不过最近实在太多事情,先下了再说,等积累到3,4集再一起看。

看了看海报,几位主角都越发显得老练。啦啦队队长克莱尔显得成熟了许多,褪去了以前的青涩,充满了魅力。一直显得很初哥的Peter从海报上看起来也不太一样了,不过他的风格就是那样,能力再强还是一副懦弱的样子。最有看头的应该还是塞拉,深陷的眼窝,聪明的头脑,超强的邪恶力量,这次终于有能对抗正义的邪恶力量了。胖子警察Matt,老实说总给我一种有着很强的力量,却一直缺乏方向感的人。这种人根本没法发挥出应有的力量。

总的来说,英雄中的“英雄”们都是平民老百姓,每个人的性格都有缺陷,不过正是因为这样,才让人觉得有意思。否则弄成生来就知道自己的使命的超人或者美国上尉就俗套了。也许80年代还能这样搞搞,现在是21世纪,人们喜欢的就是多元化。

2008年9月18日星期四

与侯捷面对面

侯捷先生这两天来我们公司做C++培训,使我第一次有机会亲眼见见这位国内的大牛。

侯先生给我的第一感觉就是儒雅,平易近人,非常认真。知道侯先生已经是7,8年前的事了,侯先生对国内计算机教学最大的贡献就是引入了很多名著,当然主要在于C++和Java编程方面。我从各种侧面都了解到侯先生的为人非常令人钦佩。这次面对面聆听他的培训,更是感受颇深。


侯先生的教学态度是我遇到过的所有培训老师中最好的。9点钟开始的培训,我8:40到发现他已经在那里了。他非常喜欢和下面的人互动,鼓励我们多问问题。每天我们都会提出很多问题,有些问题他无法解答的,他会一一记下,晚上回去做功课,第二天给我们答案或者和我们更深入的讨论。侯先生不是圣人,所以他不可能什么都懂,我们有时会提出更好的或者相对来说更合适的解答,侯先生一定会欣然接受。第二天就会在他的slice里面反映出来。


侯先生的治学严谨其实在他以往的著作中可见一斑。我以前读《深入浅出MFC》的时候就相当佩服他能够将这么大的一个库剖析的这么清楚。我也看过很多源代码,但从来没有哪次能像他那样把思路理得这么清晰。这次他给我们讲了STL中的内存管理,也就是allocator。我有一次深刻的体会到他在这方面的功力。他能把一段指针满天飞的代码,不光读懂读透,还能画出非常直观,非常漂亮的示意图出来。把对象在内存中的布局,每一步的变化,像连环画一样画了出来。如果我这样说你觉得没什么,你可以试试,拿出几百行的代码,画画它们在内存中的变化,看看你能做到什么程度。侯先生不会放过任何一个小细节,有时候简单的一句话,却包含着非常深刻的意义。看代码,学代码,真正有价值的,其实就是这些。把这些搞懂,我们才能不断进步。否则,就算我们看过无数代码,还只能停留在表面。这就是他这几天教给我的东西。


侯先生的专注相当令人钦佩。侯先生自己也是一把年纪了,但是还能这么专注的研究技术,真是让我汗颜。现在搞技术的浮躁的人忒多,很多人做了一两年基本上就想转管理了,说做技术没有前途。有些人做了几年C++,看到.net流行了,就去做.net,过会儿又做做JAVA,最后年纪也大了,却一事无成。候先生这么多年来坚持不断的在这个领域内勤奋耕耘,才能有今天的成就。其实我也是经常会摇摆不定,有时候想放弃技术,但是不知道是幸运还是不幸,每次都有客观或者主观的原因把我拉回来。

天下无不散的宴席,和侯先生的接触也就是那短短的十几个小时,但是他给我展示了另外一个更有意思的世界。

2008年9月13日星期六

dev.chromium.org被封

Chromium一出来,我就一直关注着dev.chromium.org,我知道我的能力帮不上什么忙,但是我想学习一下。毕竟这是googler写出来的程序,无论怎么样,总比我这个半吊子要强的多了吧。


但是从前天开始似乎dev.chromium.org就进不去了。公司的路由是德国的,因此我能进去,发现第一个帖子就说dev.chromium.org被G××封了。G××真是越来越霸道,简直就像以前的东厂和西厂,封人没商量。事实上G××对google的产品总是青睐有加,是不是的去捏一把,推一下。就没见它对MS,Yahoo!的产品有什么动作,这背后到底有些什么呢?

2008年9月12日星期五

英国一所大学提供Jedi武士训练课程

从08年11月起,英国的Queen's University Belfast 将会提供一门非常有创意的公开课程,这门课程将会教授学生使用星球大战中的绝地(Jedi)武士的心理学来掌握交流和发展人际关系的技巧。课程的教材叫“Feel the Force: How to Train in the Jedi way”,教程中提供了在真实生活中隐藏在Jedi们的引导别人思维的把戏(Mind Tricks)之后的心理学技巧。并且保证能为学员介绍在星球大战中的很多概念,比如平衡,命运,二重性,父性,法西斯等。这门课程价格不贵,大多数学生都能承受的起。

事实上,学校的初衷不是这门课本身,而是希望通过这种有趣的方式来传达给学生们一种持续学习的理念,使他们保持终身学习,因此学院把这门课设为公开课。学生们学习的不仅仅是星球大战的电影,还有电影中涉及到政治和社会学的问题。

在这门课之前,UK的第一个Jedi church也刚刚建成。你可能要问,什么是Jedi church,但事实上我也不知道什么意思。但它说明了一点,英国人也喜欢StarWars。否则为什么别的不选,而要选一个被称为boy film的商业电影作为研究对象呢?估计卢卡斯听到这个消息,开心的鼻子都要笑掉了。不过也可以说,Star Wars中的这种心理学技巧是简单而容易学习和应用的。该教的知识都有,书本不是枯燥的定义和文字而是电影,学院在引导人们快乐而持续的学习上真是煞费苦心了。

P.S.
Jedi的引导思维的把戏可能不一定有人注意,但是打过Star Wars游戏或者看电影比较仔细的人一定会注意到。比如在Ep 4,Qui-Gon Jinn在Tatooine上为Anakin赎身和Watto(那个会飞的丑陋奴隶主)打赌的时候就用了Mind Trick。在Eq 1,A new hope 中,Obi-wan Kenobi(老年)带着luke去飞机场时候也用了Mind Trick来控制帝国士兵躲过身份盘查。这项技巧在谈判时候特别有用。但是对于意志坚定的人(生物)是没用的。

消息引自:
http://idle.slashdot.org/idle/08/09/11/1648230.shtml
http://www.telegraph.co.uk/news/newstopics/politics/education/2798657/Star-Wars-Jedi-Knights-course-offered-by-Queens-University-Belfast.html

2008年9月10日星期三

不用stylish了

我一直使用stylish很久了,几乎把google, yahoo的很多产品都该了界面。今天,突然心血来潮想回到以前简单的界面看看。没想到这一看就出事了。

我尽然觉得意见简单的界面反而有浑然天成的美,难道是我的审美除了问题?等到我把reader, gmail, calendar等全部变回原样后,我才发现,google的产品的UI设计是真正的返璞归真,简单而和谐,感觉浑然一体,非常自然。

我决定,放弃浮华,接受朴素。再见了,stylish!