从《DOOM启世录》到《游戏引擎架构》

谢伊的小屋,

其实也是由于最近《守望先锋》发布,在查资料的时候看到了油管上面几个当年《雷神之锤》的比赛视频,也就想起来《DOOM启世录》这本书。因为这本书初版已经有一些年头了(2004年),所以当我第一次读到这本书的时候(大约11年左右)市面上已经不是那么容易买到这本书了,也就一直在阅读一个精装的电子版。第一次阅读这个时候,一种被旋涡陷入的炫目感一直充斥在脑中,虽然不是很懂,但是也从内心深处觉得这实在是无时无刻不令人激动,读罢之时内心充斥着是当身为伟大历史潮流的一部分时候的那种“自豪感”?这种感觉实在是不好形容,或者叫做“幸运感”?或者叫做“创造感”?或者是这几种的混杂吧?这或许真的只有弄潮的人才能体会的那种感觉,那种无论做什么,都觉得是对的愉快感。从《DOOM启世录》这本书中就可以体会到这个,当然,现在看来,这本书在书写的时候故意使用了一些文学处理手法,虽然是一本传记,但是却很巧妙的安排的故事之间的结构,使得读起来真的像是一本历史书,真的看到了一个时代的兴起与发展。这对当时还非常Naive的我是非常震撼的,那个时候的我也热衷于阅读各种历史书和传记,而这本是当时读到的离我最近,但是也离我最远的传记吧。

多年之后,这本书去年的时候重新发行了一次纪念版,也就是《DOOM启世录》(纪念版)这本书。在这几年期间,我也十几次的读了这本书的电子版,当然因为个人的成长,每次读这本书的时候都会看到不太一样的东西,也非常希望能够拥有一本纸质版来阅读。虽然去年打算再版的时候就已经听说了这个消息,但是真正发行后反而忘记去入手一本。最近看完那几个《雷神之锤》的比赛视频后,也是快点去入手了一本,到了之后立刻又读了一遍,也算是感慨万千,圆了一个心愿。

有关《DOOM启世录》这本书我没有任何多余的话,大家自己入手来读一读就知道这本书有多棒了。单单作为一本传记而言,这本书就已经是上佳的作品,更何况里面描述的是最令人激动的计算机技术刚刚起步阶段的传奇故事,而豆瓣的书评区也积累了非常多很棒的书评,也推荐大家读一读。油管这本书的精神我也按照惯例摘抄一下这本书的一句原文:

在信息时代,客观障碍已不复存在,所谓障碍都是主观上的。如果你想动手开发什么全新的技术,你不需要几百万美元的资金,你只需要在冰箱里放满比萨和可乐,再有一台便宜的计算机,和为之献身的决心。————John Carmack(约翰·卡马克)

id Software早年的员工们,最左是约翰·卡马克,最逗是约翰•罗梅洛

我也就多来说一些别的事情吧,在第一次读完《DOOM启世录》这本书之后很久,我又读到了另外一本也值得大家亲自来读一读的书,那就是Paul Graham的《黑客与画家》一书,这本书同样具有很多非常棒的豆瓣书评,同样推荐大家读一读。《DOOM启世录》这本书讲的是传奇故事,《黑客与画家》这本书就是讲的这些传奇故事是如何出现的。对我来说,当我第一次读前者时,因为还缺乏对计算机科学与技术领域的了解,完全没怎么入门,只会写几个算法题的小代码而已,完全是当做一本小说来读的,崇拜着这个传奇的故事,但是在之后也算是慢慢的入门了之后,再读前者的时候,更多的看到的是两个John为了梦想而做出的努力,一个John的技术是如何的伟大而具有创造力,而另一个John的设计是如何踏上了时代的步点,而id Software又是如何做了成功的事情,又是如何做了失败的事情。而当第一次读后者的时候,已经是有点入门的时候,刚刚处于懵懵懂懂的时刻,这本书对当年的我简直是如同当头棒喝一般,一下子给我灌输了很多我从未见识过、想象过的思想,从那个时候开始,我才算是在思想上正式的入门了,搞懂了自己在干些什么,以及要如何去做这些事情,属于世界观和方法论上的指导。当然,说到非常棒的理论与思想,当真正的接触到其中的一个之后,就会慢慢的觉得很多东西都有些接触到真正棒的部分了。额...这个有点绕口,大概的意思就是说人果然还是要成长了一段时间,积累了一些见识之后,才能逐渐解锁某个体系里面更深层次的东西。再之后读了《禅与摩托车维修艺术》《深入理解计算机系统》《失控》这些书,都是属于不断重读不断有新的收获的书,也算是螺旋式上升的发展道路吧。真是有趣,经典的力量可能就在于这里吧,提供的是深刻而系统的思考理论,能够让人在实践中慢慢品味,慢慢解读,所以说半部论语治天下事实上也是能够做到的嘛。最近重读《荀子》,也深觉其中的不同味道,跟高中时候读的感觉又完全不一样了,特别是在进入大学之后,系统的了解了康德、黑格尔到马克思,以及之后发展的各种不同的西方马克思主义哲学观和中国自身的各种特色哲学理论体系之后,其实也算是慢慢的形成了一套自己的价值观(多么理所当然)。当然,说起来影响最大的就是黑格尔的肯定、否定、否定之否定的三段论,以及马克思的辩证法以及螺旋发展观吧?这也就使得我在重读这些书的时候,一方面是尝试着看到新的以前没有看到的东西,另一方面就是尝试着三段论,尝试着肯定书中的理论,肯定自己的看法,然后再想想如果需要否定这些肯定应该怎么做?我能够否定我的否定吗?在这个过程之中,也算是尝到了无穷变化的妙趣吧。

除了上面在三观方法论方面的东西之外,读技术类的书籍也具有同样的方法吧。当然,在学习技术这方面,跟着人学习比跟着书学习对我来说来的更舒服一些,我是非常佩服很多的人的,比如像是Wei WangYaoyuan、我的好朋友Shu Ding以及好朋友也同样佩服的Jiabao Guo等等,他们都是能够不断学习,不断实践的人,对我来说,他们就像是一本书一样,让我也不断的学习他们。当然,我觉得,这是在先形成自己的技术观之后再做的事情,(说着说着就开始输出技术观了,其实自己觉得合适就好)可以先读经典,特别是像上面提到的《深入理解计算机系统》(CSAPP),还有各种动物书,机械工业大套装,图灵大套装之类的东西,然后一边做一边学,考虑一下为啥要这么做?如果我不这么做呢?有啥更好的方法吗?这样有什么坑,我能cha掉吗?说起来也是有点惭愧的,虽然我开始接触信息学竞赛,开始写代码还是从蛮早就开始了,到现在也算有九年了,但是一开始写的代码实在是野路子,后来加入了模块化,能够把一个文件里面代码写的有点道理了,但是相比于身边很多优秀的代码手而言,写的代码实在是缺乏灵气。后来写长代码的时候果然又遭了很多坑,特别是在上《操作系统》课程的时候,自己动手实现Kernel,真是吃尽了苦头,拿出来的东西还非常Toy,当然这是在比较后面的事情了。于是就恶补了一波如何好好写代码的知识,在这个期间也开始系统的学习iOS开发,这个时候才大概懂点什么叫做OO,代码是如何Run的,啥叫运行时等等,然后在学习了《现代编译原理》自己尝试搭建编译器,学习体系结构自己来做CPU,也算是逐渐的搞懂了整个计算机科学与技术的体系结构和套路。于是,在前一段时间重读CSAPP的时候,读起来觉得写的真是太TM有道理了,设计的实在是太奇妙了,很多地方真是是要踩过了坑之后才知道为啥是这个样子而不是某个样子的,所以说这个过程也算是三段论样的螺旋发展吧。这个学期课余之时开始读《游戏引擎架构》,从头读到尾实在是爽快的厉害,觉得这套东西就应该这么work,各方面都非常都道理,特别是里面面向对象的部分,写的也是十分精彩,当然这本书我在阅读的时候,是当做一本《如何组织大型工程》(游戏版)来阅读的,这本书的原始内容和翻译都是非常良心的,不过因为是大部头,所以有限推荐给需要的人士吧。写到这里有点累了,之后会专门为这本书写一篇长书评的。

这篇文章是晚上失眠的时候写的,一通胡言乱语而已,其实心里面有万千言语想要写出,但是自己的笔力还不能很好的控制吧,权当随笔一篇,纯私货而已。

PS: 上面提到的那几本书我也就纯私货的推荐一下吧:

《DOOM启世录》:无论从传记小说的角度看,还是从一个计算机行业的从业人员的角度看都是非常棒的书。

《黑客与画家》:非常好的三观书,特别是里面对于“创造”部分的讨论,对我影响十分巨大,很多领域并不是零和博弈,当创造的时候是产生了更好的世界,这也就是为什么我们的世界变得越来越好的原因。

《禅与摩托车维修艺术》:一本哲学书,里面对思考方法和系统思维的讨论非常深刻。

《深入理解计算机系统》:应该多读几遍的书,每读一次有新的收获,学完数据库、操作系统、计算机体系结构、编译等等计算机课程之后,每一门课都会对这本书产生新的看法。

《失控》:KK的书,里面有很多观点是非常棒的,至少我看的时候有一种耳目一新的感觉,特别是里面对于“涌现”的表述,让我觉得非常有道理。计算机科学与技术就是一个不断涌现和抽象的过程(这个是个人观点,见文章最底下的口胡部分)。

《现代编译原理》:虎书。计算机专业同学的必修课。

《游戏引擎架构》:超级良心的书,翻译是现任腾讯互娱T4级别的工程师Milo Yip(叶劲峰),专业人士翻译,而且翻译的非常用心,原书也是写的非常详细,即使是不从事游戏相关领域,也可以用来作为了解超大型项目组织的入门读物。

以上说的可能还算有点道理,以下是纯口胡,纯个人观点而已(所以有没有道理都没关系):

计算机科学和技术的发展靠着两种模式:一个叫做“抽象”,另一个叫做“涌现”。“抽象”这里我把它解释为面向对象编程和分层结构形式的抽象,我很久以前看到过一句谚语?计算机上的设计问题都能够通过加一层封装接口来解决,如果不能就再加一层。我一直觉得分层封装实在是对计算机体系结构非常适合的一种发展模式,向上屏蔽细节,向下拓展兼容性,让整个系统天然的可以被并行的开发,而不需要考虑其他层的具体情况(除非极端情况),这是一种生产力很高的模式。而当若干具有某种同一属性的接口被抽象到一层的时候,就会“涌现”出某种新的属性,新的原始系统没有的属性。比方说把主板CPU内存弄到一块可以运行程序,当网络相关的东西都被打包起来的时候就变成AFNetworking(一个iOS上使用Objective-C实现的网络库)。而开发的时候做的事情大部分也就是这两个,设计新的接口从而实现不同的新功能和兼容性,或者把不同的接口打包涌现出新的功能或者业务逻辑。更具体的例子而言,比方说我现在需要实现一个叫做存储的功能,那么可以设计一个叫做存储的接口,然后这个接口下一个层次上实现新的接口,比如说网络存储、本地存储等不同的场景,然后在存储的接口中,根据传入的参数的不同调用不同的下层具体的接口实现。当然,存储这个接口也会被封装进其他的部分而产生作用,比如把存储接口跟几个按钮和本地加载接口放在一块,就能涌现出一个叫做“更换头像”的功能。更大的说,整个计算机软件体系结构,不就是在单独的一条条CPU指令集上的抽象和涌现吗?

所以,在写代码、写工程的时候,考虑三个问题:1.如何组织我们的代码? 2.如何组织我们的空间(缓存、内存、外存)? 3.如何组织我们的消息(逻辑如何执行?怎么跳转?叫了哪个函数?网络如何通知?通知什么)?有一句话我是非常赞同的,高级程序语言的最重要的作用是让人更够读懂,一个合理的代码组织模式(比如OO范式,MVC设计模式等)可以帮助所有人快速的搞懂要做什么。如何组织我们的空间?对于CPU而言,其实他做的事情非常简单,就是拿出PC指向的一条指令,读一下,执行一下,然后下一条。而作为整个系统的构建者,在写工程的时候,要非常清晰的考虑到现在内存中是什么样子?哪些是指针?哪些有效而哪些需要释放?如何组织消息就更加明显了,当状态发生变化的时候,自然应该通知应该通知的人,或者是等着他来询问到底处于何种状态。这也只是我很不成熟而且有点空泛的想法,本来是想写《游戏引擎架构》长书评的时候说一说,一时兴起就随口扯几句,到时候更加详细的尝试着论证一番。

睡了睡了。