如何阅读一本书

我好读书,读的很繁杂,从计算机技术到历史到国学和哲 学,系统方法论等都是我爱好读的。 但平时工作忙,尽管每天都坚持挤出一到两个小时的读书时间(牺牲睡眠时间),但读书时间与要读书的意愿上一直存在着矛盾,这意味着我需要高效率地读书。而 我想,我的阅读能力可能得益于《如何阅读一本书》,一本讲“元阅读”的书。这本书第一版出版是1940年,到今天还被很多人拿来读,可见此书称得上是经典 了。

对此,我对这本书的内容稍作总结,希望能对同样爱读书的你,同样有帮助。

主动阅读

当然,严格上来说,不存在完全被动的阅读。阅读越主动,效果很好。这个读者比另一个读者更主动一些,他在阅读世界里面的探索能就更强一些,收获更多一些,因而也更高明一些。读者对他自己,以及自己面前的书籍,要求阅读,获得的就越多。

同时,主动阅读,更多的地意味着你需要读更多超过你能力范围的书,因为只有读超过自身能力范围的书,通过阅读过程中的不断思考与磨砺,你才能真正增 进你的理解力和阅读能力,而完全在你能力范围内的书,只是让你获取更多资讯而已,而资讯的获取,在这个资讯如此发达的时代,你有太多的办法来获取。关于这 一点,Justin作为一个关注“上层建筑”的程序员,去年在读《深入理解计算机系统》一书时,有很深刻的体会。此书,对当时的我来说,完全超越我在计算 机技术上的认知能力,我花了很大的耐心,反复磨砺,寻找各种理解的方式,才将这书基本读完(暂时性的读完,还要不断重读)。但读完后,我发现我获取的不只 是对更多计算机原理知识,而是更为深刻的计算机设计和架构的思想,更关键的是,我获得了驾驭这类书籍的信心于能力,这是平常在读一本《×××计算机语言》 之类的书时获取不到的。

分层次阅读

第一层次:基础阅读

初步的阅读能力和阅读技巧,也应该是读者都基本具备的层次。达到这阶段,只要求你能辨识书中的文字即可,即摆脱了文盲状态。

第二层次:检视阅读

检视阅读,才算是真正进入了阅读的层次,但当然,只有你必须是精通了基础阅读,比如现在,让你读一本外文书,你可能就进入不了这个层次。 对于检视阅读一般分成两种:

有系统的略读与粗读
可以通过以下几个方法来略读:

  1. 先看书名,然后有序就先看序。要明白一点,书名和序,肯定作者花费心思最多的地方,通过阅读它们,你基本可以对一本书进行归类了。

  2. 研究目录页。一个好的目录,可以助你对书的基本架构有概括性的了解,就像出发前,要先看一下地图一样。但是并不是每一本书的目录都是能设计 好的。Justin曾经读过一本书叫《算法谜题》,它的目录居然是将100道算法题索引出来,而没有任何的归类于串联,后来,我也就基本断定这书,就是一 本算法集锦而已,作者的思维本身就是混乱的,只能给它打上“浪费时间”的标签了。

  3. 从目录里挑选几个看起来跟主题相关的篇章来读读。对于这一点,我最喜欢的就是读开头和结尾,因为万事开头难,作者要开始写一本书,肯定需要 深思熟虑,尽快地抛出作者自己的观点,抓住读者。而结尾呢,作者一般会作出观点的总结。如果发现作者的观点,完全在那你理解范围之类,我觉得没有很多必要 读下去了,因为要铭记,只有“主动阅读”超越自己能力和理解的书,才能让你获得成长。当然,纯粹位获取知识,除外!

  4. 读读书的封面和包装。这上面一般都有出版者的话,或者作者的其它相关书籍的介绍,在这些“面包屑”里,你或许可以发现新的”珍珠“呢。我超爱干这事,经常在这里面,发现新的值得一读的书。

粗浅的阅读

有难度的书,或者超越你能力范围的书,肯定不是易读的书。但如果要驾驭它,你需要先“粗读”,即在第一次读一本难读的书时,从头到尾先读一遍,碰到 不懂的地方也不要停下来查询或者思索。完整地读一遍之后的了解,即使你只掌握了50%甚至更少,也能帮助你在后来重读第一次略过的部分时,增进理解。就算 不重读,对一本难度很高的书了解了一半,也比什么都不了解要好——如果你在一碰上困难的地方就停住,最后可能对这本书真的一无所知了。

第三层次:分析阅读

阅读的第三个层次就是分析阅读,也是最重要的层次。分析阅读包括以下三个方面:

  • 了解书的内容
  • 明白书到底在说什么
  • 评论一本书

对于以上三个方面,作者列出了几条基本规则:

  1. 你一定要知道自己在读的哪一类书,而且越早知道越好。最好早在你开始阅读之前就先知道。 关于这一条规则,我倒是要提醒特别提醒那些喜欢给人荐书的朋友,如果你推荐一本书出去,你最好能先告知将要读这本书的人,这是一本什么类的书,这样读者才能按自己兴趣与认知,来尽快作出读或者不读的判断,或者选择相应的读法。

  2. 使用一个单一的句子,或者最多几句话来叙述整本书的内容。 对于整体内容,光是一个模糊的认知是不够的,而判断你是否确切清楚整体内容,唯一判断的办法就是,你能不能用几句话来表达清楚。如果几句话表达不出来,或者要用更多的话来表达,代表你还没有将整体的内容看清楚。

  3. 将书中重要篇章列举出来,说明它们如何按照顺序组成一个整体的架构。 于建筑设计,软件系统设计一样,可读性最高的书肯定达到了最完整的整体架构的程度。最好的书都有最睿智的架构。比如《史记》,可以轻易地将它分成12本 纪,70列传,30世家,10表,8书,而本纪是全书的提纲,所以对于读者,先肯定要能通读所有的本纪系列,而后可在列传和世家里选择一些感兴趣的来读, 而当读者对人物世系需要更多了解,就可以多去看看表。

找出作者在问的问题,或作者想要解决的问题

一本书的作者在开始写作时,都是有一个问题或一连串的问题,而这本书的内容就是一个答案,或许多答案。而技巧高超的作者,会用艺术的手段,将问题和 答案都隐藏起来,作为读者,最大的义务就是找出问题和答案。这个寻找的过程,也是读者理解力和阅读能力获得最大成长的手段之一。

第四层次:主题阅读

主题阅读是读书的最高层次,或称为最高目标。所谓主题阅读指的是,为了学习和理解某个特定的主题时,牵涉到的往往不只是一本书,而是需要去读一系列的书来研究和对比,从不同的书中相互补充观点,形成自己对这一主题的知识系统。

做到主题阅读的层次,第一要求就是必须承认某一个主题读一本书是不够的,第二个要求则是,需要知道应该读那些书,而很明显,往往第二个要求比较难以 达成。Justin本人对于这一点上经验还不是很多,毕竟不是专职搞研究的,平常对于某一主题的扩展阅读,大多数还是来自书籍本身的“面包屑”,比如前面 说过的,书籍封面和序言里提到的同一作者的其它书籍。同时,一本优秀的书里,作者为了证明自己的观点,肯定也是旁征博引的,所以,作者在书中提到的这些相 关书籍就是发掘宝藏的号地方。这在读Brooks教授(同时也是《人月神话》的作者)的《设计原本》时,我就大有体会。Brooks教授在它的书里,引用 了很多其它经典书籍,也由此看出一位优秀的作者,肯定读破万卷书的。

总结:

读书是一种习惯,一种技巧,更是一门艺术。读书不只是为了获取资讯,更是为了增进理解力,从而更好的理解世界。一个人读书,只是将文字逐字 逐句地阅读一遍往往是不够的,那顶多只能称之为消遣。一个人只是读自己理解了的书也是不够的,因为那样获取不到理解力的增长。而《如何阅读一本书》一书, 教会我们的就是,如何“读懂”一本书,并在读的过程中获得成长。​

防御性编程小例

Jan 13th, 2014

今天面试一个人时,突然想起一个话题:防御性编程 。我们先看一个小程序,这也是以前出过的一道简单面试题:写一个函数,可以将一个小写字母转换为大写字母。这道简单的题,完全写对的答案却少之又少。大部分答案是这样的:

1
2
3
4
int toupper(int c){
   c=c-32;
   return c;
}

看似简单的答案,确实不完整的,或者说正好落入了题目本身的圈套。到此, 你或许看出了问题所在。对,问题就出现在参数c的取值判断上,最明显的就是当c小于32时,c-32小于0,返回值肯定不在字符取值范围内。所以,我们加上了判断:

1
2
3
4
5
6
int toupper(int c){
  if(c>32){
    c=c-32;
  }
 return c;
}

加上了对参数c判断,这就是防御性编程的第一步了。可惜,在这道题里,这也还是错误。如果我们传入67(‘C’)来调用toupper,返回的是35(’#’),显然也是错误的。所以,我们的代码防御,应该将c的合法取值限制在一个更小的范围(小写字母集合)。

1
2
3
4
5
6
int toupper(int c){
  if(c>='a' && c<='z'){
     c=c-32;
  }
 return c;
}

至此,代码可以正确工作了。(最可惜的是,很多同学写的代码已经“进展”到下面这样了,却还没有发现c的取值范围应该限制为小写字母集合)

1
2
3
4
int toupper(int c){
  c+='A'-'a';
  return c;
}

这就是防御性编程的最基本规则:保护程序免遭非法输入数据的破坏。

或许你会比较乐观的认为,我的程序不会被非法输入来调用,当你这么想时,请参考一下墨菲定律

保护程序免遭非法输入数据的破坏,我们一般有以下几种方法:

  1. 检查所有来源于外部的数据的值: 当从文件,用户或网络等外部接口获取数据时,应该检查所有输入的值,不要有任何庆幸,以确保它们在合法的范围之类。比如,对于数值,应该确保它的可接受范 围(如非负数);对于字符串,要确保它长度合法;对于更多的安全要求的,还要进行sql注入,html/xml注入等的检查。

  2. 检查子程序所有输入参数的值: 这点与第一条类似,只是输入来源于程序内部,而不是外部。比如一个空指针,一个空对象的检查等等。

  3. 决定如何处理错误的输入值: 当你检查到程序的非法输入值后,要决定如何对这些非法值进行处理,是忽略还是抛出错误?要视情况而定,比如我们的toupper函数,忽略非法值输入是合理的。

 

原文地址:http://sharecore.net/

posted @ 2014-05-14 23:14  mrbean  阅读(303)  评论(0编辑  收藏  举报