前段时间,与豆瓣网友伊卡洛斯聊,他问我是否有书推荐,书没推荐几本,文章倒是推荐了一篇《刘瑜的秘密书架:从经典到经验》,他看过之后感觉很好。其实,我第一次看也有豁然开朗的感觉,索性就着刘瑜的文章,说说自己的阅读经验吧。在我看来,“读书”和“会读书”是两回事,如何才叫“会读书”,至少要保证几点,下面一一道来。

首先,读书一定要有明确的目的性。此处的“目的性”,准确来说就是真正关心的问题,循着这些问题,在阅读中思考,才可以真正有所收获。我在大学阶段的阅读就是如此,收获也确实不小。刚进大学时,我四处听了许多讲座,有两点深刻的体会,第一是之前了解的关于政治、历史、社会的许多知识是假的虚的,第二是这些假的虚的说法,竟然可以伪装成堂而皇之的道理,甚至无法识破。为了解决这两个问题,我认真读了不少思想史和历史的文本(尤其值得庆幸的是,读了很多原本,而不是后人的阐释),从此明确知道了社会只有自由才能进步,人只有自由才能真正发挥出价值,虽然后来很少“不务正业”看此类书,但这之后从未纠缠过“自由、民主是否有益”等问题;另一方面,我有幸阅读了一些严肃的论著,并认真学了一点逻辑,真正知道了论述要如何展开,也领略了逻辑的威力,而且受益至今——面对一些言论,即便不了解所在的领域,却可以知道这是不对的,是胡说八道。回想起来,如果当时我没有真正关心的问题,或许仍然会花大量的时间在图书馆,然而其实只是“没有浪费时间”而已,充其量积累了一些谈资,绝无可能有这样多的收获。

其次,读书一定要注重完善知识的结构,学会从多个角度看待同一个问题。我之前有疑惑,人脑的容量是有限的,看的东西越多,想的越多,脑子是不是越乱?但现代科学已经证明这不是一个问题:人脑的容量,其实远远大于所能吸收的信息;更重要的是,随着知识的增加,大脑中的知识结构也在不断变化,从平面到立体,到错综复杂的交联结构,同时这些知识的索引也日渐复杂高效,你可以通过更短的途径,找到想要的知识,也容易联系到更多的知识。我的朋友Jack曾说:会讲一个观点没什么了不起,面对质疑,问三问,问不倒,才真正了不起,才真正学会了。要做到这一点,就必须完善知识的结构,因为你无法保证质疑会从哪个方面来。举个例子,我国历史教育中,中国历史和世界历史是割裂的,虽然两者都还算熟悉,但问你唐宋元明清大概是公元多少年,当时世界上发生了什么事情,估计许多人就答不上来了。在这样的前提下,夸赞中国古代如何如何先进就多少显得有点心虚:哪方面先进,领先哪些人多少年?更不用说在解释游牧民族入侵时,忽略关于几个低温阶段的气象知识,而仅仅解释为“朝廷腐败”了。另一个例子是,如果你只孤立地看待中国当代史,会觉得“知识青年”是一个历史名词,但若放宽视界就会发现,在世界各国城市化进程的早期,必然要面对大量农村人口涌入城市的问题,但只有中国采取了“倒流”,让城里人去当农民的政策……类似的例子还有很多,总之,如果能跨越多种门类的知识,用多种眼光去看待同一样事物,你对许多事件的判断就更为全面、深刻了,说起话来也更有把握了。

再次,对古人的书,古人说的话,一定不能“活学活用”。我们都知道,语言不能脱离语境单独存在,任何观点和论述,都是在一定前提下展开的。脱离了语境,脱离了前提,许多观点和论断就成了永远不会出错的万灵药——于丹可以用《论语》解释任何一切,但她未必知道(知道了也未必告诉她的信徒),孔子身处怎样的年代,他的话是什么情况下对什么人说的。或许大家觉得于丹的例子太极端,但这类例子其实并不少见,比如亚里士多德说“人是政治的动物”,其实是指人不能脱离公众生活而单独存在,却被理解为“搞权谋是理所当然的”,笛卡尔说“我思故我在”其实是指“只有经过真正的思辨和质疑,我才真正成为本体论意义上的我”,却被理解为“如果我没有在想事情,我就不存在”。许多人读书,是希望找出古人的话,证明自己的正当性,但脱离语境、隔离前提来“引证”,其实是以讹传讹,放弃了求知的诚实,将自己的知识,建立在虚无的基础之上。

最后,对古老的书,要有选择性的放弃,多读现在的书。现代科学进展一日千里,不但在专门化、精细化上进展神速,更重要的是,不少领域的知识在方法论和学科范式上有了突破性的进展。许多前人通过总结个体经验,或者自己冥思苦想得出的结论,在现代的方法论和学科范式之前不值一提。这方面最明显的就是心理学,虽然这门学科是弗洛伊德开创的,但弗洛伊德五迷三道的理论,既无法证实也无法证伪,甚至在什么情况下要如何使用都难说清楚,只有在引入现代科学方法之后,可以通过实验复现之后,心理学才真正成为科学,得到了许多踏实的、普适性的结论(所以耶鲁大学的心理学公开课里说弗洛伊德的理论之于现代心理学,更像占星术之于天文学)。另一个例子是社会学,前人也许能通过冥想或内省,写出《情爱论》这样的论述,但真正幸福的情侣应当相似还是不相似,如果要相似,是要在哪些方面相似……这类问题其实不是严肃的哲学问题,而更像实证问题,可以通过大规模的数据采样,找到一般性规律,并精确分析,得到结论。相比之下,单纯“举个案”或者“举反例”的论证方法,显得太粗陋,也不能保证所举例子的典型性。

或许有人会说,读书就图开心,自己高兴就好,何必想那么多。我想说的是,同样的事情,在不同的年龄段做,效果是大不一样的;纯粹图开心而读书,不妨等到一定年纪,条件齐备,又有大把闲暇时间,再做不迟。在这之前,在宝贵的时间里学会读书,再认真读点好书,对大多数人来说,恐怕是更合适的选择。

正则表达式的书稿终于结束了(暂定名《正则导引》),关上电脑细细思考,写完这三十万字,最深刻的感受是什么?我的回答是:后悔。

从2009年初我打算写这本书,到2011年年中正式写完,一共花费了两年多时间,期间虽然经历了许多变故,有些事情也无可避免,但其实不用花费这么长时间——最初是在周筠老师的鼓励下决定动笔,当时是有想法,没规划。之后在徐定翔编辑和卢鸫翔编辑的配合下,尝试写了几章,又遇到困难停住。多亏李笑来老师说“暂时解决不了的问题,先绕过去,接着写后来的部分”,于是零零散散地继续写下去。到2010年末潘爱民老师对我说:这个状态可不行,这么随意地写,就算写出来,也不会是好书,不如不要写了。明知潘老师是在用激将法,我还是心甘情愿地上了套,为争一口气,日复一日地写,半年左右,终于完成。

回头看这段时间,却感到一丝荒谬:其实真正“笔耕不辍”也只有半年的时间,之前两年在干什么呢,这两年里,我心理总惦念这这本书,因此放弃了太多其它,然而其实并没有真正做什么事情。况且,翻看日记,真正笔耕不辍的时间,其实并不到半年::3月12日,状态不好,早点休息…3月20日,要办的事情太多,又没有规划好,书稿明天再写…4月16日,做了好几张图,做到有排斥情绪,看电影… 这类情景比比皆是。套用《少有人走的路》中的分析方式,这类因果关系其实都经不起推敲。认真分析起来,状态不好时,专注做一些事情,是可以让自己状态慢慢好起来的;要办的事情太多,没有规划好,完全是因为“没有规划”而不是“意外太多”;做图做到有排斥情绪,是因为把几张图集中在一天做,其实分几天完成并没有问题……虽然每次写日记发现自己浪费了时间,都提醒自己要从明天开始认真,但往往坚持不了几天,又因为各种理由松懈下来。我想来想去,原因就在于,我总以为“认真”是一种态度,从不认真到认真,只要端正态度就可以,然而认真其实是一种能力,如果你不具备,即便想施展,也未必施展得出来。

关于“能力”,我曾与一个朋友深入讨论过,结论是:只有当你能施展出来的时候,才真正具有这种能力,否则其实就是没有——你的思维很犀利,却没见真正解决过什么问题,其实就是思维不犀利;你的英语很好,却没有真正用英语学习过其它知识或与外国人交流过,其实英语就是不好;你理解能力很强,但不去真正学一点东西,其实就是没什么理解能力。这个道理,在书稿的写作上也是这样:我曾经信心满满地认为自己做事态度足够认真,所以有能力坚持写完这样一本书,即便有所懈怠,也可以迅速回到正轨;然而真相却是,依靠着各位师友的指点,并且在很多次想要放弃的边缘挣扎着坚持下来,才真正完成。所以,“认真”其实不是种态度,而是种能力;这种能力,自己其实还比较欠缺。

后来认真读了点心理学,才明白惰性更类似某种本能,是“野火烧不尽”的,会从生活的各个角落顽固地冒出来,滋生繁衍,这或许是种本能,只能依靠日复一日地贯彻“认真”来扫除它;惰性侵入的区域越多,“认真”的能力就越弱,就越难做到“认真”。可惜的是,这个道理,大多数人未必明白,我(或许也可以说“我们”)时常安慰自己说,某某事情不是不去做,也不是不认真去做,只是觉得没有必要罢了,实质是把能力问题错认作态度问题。在一两件事情上这样做或许无可厚非,长此以往的结果却是“认真”能力退化,惰性张扬。对我自己来说,日常生活中欠缺较真的细节,造成的恶果在需要“认真”写作时集中爆发——意志薄弱,时常找些借口自我放松;心神散漫,写一段又要看看邮件,上上twitter;缺乏规划,不能合理划分任务,照顾自己的情绪……所以才会在完稿时后悔不迭:我本可以早些完成的。

另一方面,我也体会到,在值得认真的地方认真,培养“认真”这种能力,是可以辐射到其它许多方面,让自己受益的。比如为了确认Unicode编码的某个细节(其实这仅仅是书中的一个脚注),我认真阅读了Unicode编码的长篇文档,终于弄清了这个问题。这样做看似不值得,却在其它方面带来了意想不到的好处——比如,我再也不会厌烦为弄清细节而查证长篇文档了,在这之前却会因为厌烦而抵触。这种“厌烦”,看似是态度问题,说到底还是能力问题,没有能力把认真贯彻下去(至少,依照自己现有的英语水平和理解能力,没有足够“认真”到克服厌烦心理)。

平心而论,自己和许多人一样,希望过上“有意义的生活”,可究竟什么是“有意义”呢?太过随意的生活,“意义”总是要打折扣的,真正有价值的“意义”,总是是长期努力追求的结果。而认真的能力,就是这种长期努力追求的必要因素。

Update:感谢豆瓣的朋友Clyde.L向我推荐了这篇文章,Gumption Traps and Gumptionology,我也向大家推荐。老外的文章往往更讲究方法论,也更细致,他把Gumption Trap分了三类,并给出了对应的解决办法,值得一读。

许多年前,我第一次读到《第三次浪潮》,里面有一句话非常激励人:在第三次浪潮面前,知识已经取代了资本,变为生产力提升的最重要因素。我读到这个观点,总觉得平添了无穷的力量,它比从小就耳熟能详的“知识就是力量”更加有说服力,更令人向往。

而且,我逐渐发现,知识与资本相比,其实是一种更独特,也更坦诚更健康的力量:资本的力量往往是独属于个人,或某个小团体的,固守起来,价值并不会贬低,知识却不是如此,知识的价值和增值,更多体现在交流与分享之中,“保守秘密“的做法,反而得不偿失。

举个自己经历的例子吧:上中学的时候,有一些同学对自己使用的复习资料守口如瓶,似乎这样就可以保住自己的名次和优势,我当时觉得这类做法有点奇怪,但也有朴素的味道,可以理解。

到了大学才发现天外有天,更深刻觉得这种做法真是不太好。一来因为大学里能人太多了,在中学觉得很“了不起”的东西,在大学显得非常稀松平常,往日那些“绝学”立刻显得很苍白了;二来大家都住校,基本没什么秘密可言,你看什么书,花多少精力学习,旁人不可能完全不知道。“固守自己绝技”或许能建立一些的优势,但总的来看,还是不如心态开放、愿意交流和分享的同学,尤其是,不少愿意分享的同学本身也学的很不错。

毕业以后工作了,逐渐发现自己经常在某些方面浪费了很多时间:比如非常简单的技术问题,因为不熟悉,或者没有想明白,总是“不得其门而入”,若有人点拨,往往很快就能解决了。但许多时候,人家“就是不告诉你”,甚至自己就“觉得”人家不会告诉,因而都不好意思去问。

2007年,我翻译了《精通正则表达式》,此后常常遇到各路朋友关于正则表达式的问题。平心而论,我也只是用过一点正则表达式,多一点经验而已,而且正则表达式,实在不是什么高深的技术。但是,我却发现不少朋友乃至技术高手所问的,往往多是这类看来比较简单的问题,只是没有遇到过,或者不熟悉而已,所以他们也“不得其门而入”。换位思考,我逐渐体会到,简单的问题,解决起来未必简单,其实是因为“术业有专攻”而已。没有人能做到面面俱到,即便是某个领域的行家,在不熟悉的领域,也难免被简单问题困住——我问他人的问题是如此,他人问我的问题,也是如此。

或许,也正是因为有这样的情境,“固守自己绝技”的做法,才体现出价值?我不知道。

可是再后来,见的再多一点,读的书再多一点,我却越来越否定“固守自己绝技”的做法了,因为无论从个人,还是从社会来说,其实都是得不偿失的。

从个人来说,长期来看,我们的脑细胞一直在不断减少,但智力却没有明显的下降,甚至会上升。这是因为,通过不断的学习和思考,脑细胞的突触会增加,脑的结构也会不断变化,知识体系的索引结构也在不断优化。所以,质量的提升取代了数量的下降(可以参考Richar Restark博士的Think Smart)。而固守自己绝招,不愿与人交流的人,大都满足于守住自己的一亩三分地,却忽略了不断的学习和思考。这样的生活,或许过得确实“不错”,无可厚非;但我相信,在另一个平行宇宙中,很可能有一个同样的人,却更善于学习新知识、思考新问题,他的生活,或许“更不错”。我想做的,是那个“更不错”的人。

从社会来说,一个社会要想运转正常,让成员生活幸福,必须是一个足够有效率的社会。分属熟悉不同领域的人,通过交流知识,节省了彼此的时间,这就是为社会的效率做出了贡献。也就是说,作为社会的一分子,我们所能利用的他人的知识越多,这些知识的质量越高,利用的难度越低,我们自己工作生活的效率就越高,他人为我们提供服务的效率也就越高。伟大的经济哲学家哈耶克早就发现,社会中除了存在劳动的分工,还存在知识的分工,社会发展、达致均衡的过程,就是把分散在个人之间的知识顺利协调起来的过程。

就我对中文技术资料的了解,哈耶克的观点真是伟大的洞见——网上的中文技术资料,细心整理的很少,“无责任转载”居多,即便有交流,许多也局限于小圈子的彼此欣赏。其直接后果,就是大家时常为了一个简单的问题费尽周折,也导致论坛里总是出现重复的问题……中文开发世界的整体水准不尽如人意,缺乏高质量的知识协作,肯定是原因之一。

故而,我时常为自己没有能迅速发现和利用其它知识,浪费了时间而惋惜,同时也为被正则表达式困扰的朋友而惋惜;基于此,就更加感激坦诚贡献自己的知识,指点、帮助我解决不熟悉领域问题的朋友。所以,我要把自己关于正则表达式的经验悉数总结出来,整理好,写成一本书。它或许比不上《精通正则表达式》,但终归是自己的知识总结,除去讲解了功能,还点出了自己学习时犯过的错误,更提供了常见开发问题的解决方案:正则表达式问题的分类和解决步骤、URL转发的规则、中英文混排文本的处理、正则表达式中使用Unicode的细节……

其实,这也是我长久以来的梦想:我不希望看到更多的朋友同仁,为了这类已经有现成答案的问题,再浪费时间和精力,尤其是在大家生活压力都很大的今天。我可以尽力为大家写各种表达式;但我更希望这本书能成为“木牛流马”,跨越时空的距离,为更多的人送去便利。当然,其中也有一点私心——如果这本书真的能帮到大家,它也可以分担我亲自帮各位同仁解决正则表达式问题的压力;这样,我也有更多的时间,再学点新知识,再思考点新问题罢。

陈寅恪先生曾说,要“与立说之古人,处于同一境界,而对于其持论所以不得不如是之苦心孤诣,表一种之同情”,按照我的理解,意思就是,不能忽视历史的前提:社会、意识、物质等等各方面的因素,事件的发生是深受它们影响的。但是长期以来,我们在对待历史事件时,往往只强调所谓的“超然”和“客观”,忽略甚至抹煞了这些具体的前提,所以会看到一些匪夷所思的现象,就好像黄仁宇先生所说,“历史为什么没有按照符合逻辑的方向发展呢”?

这方面最典型的例子,是公车上书与五四运动的比较。公车上书发生在1895年,中国丢失了辽东半岛和台湾岛;五四运动发生在1919年,中国丢失了胶东半岛。看起来,1895马关条约对中国的损害要远大于1919年巴黎合约,但是,同样是知识分子带头抗议,为何公车上书的反响远远不及五四运动?对这个问题有许多解释,有种传统的解释是康、梁不够进步,不过我总觉得这种解释太过简单,因为它完全忽略了时空的前提。

根据杨奎松先生的总结,1895年与1919年,虽然只相差了二十多年,社会却大不相同。在1895年,中国的信息传递方式还十分落后,电报技术并不普及,信息传播也是文言当道;另一方面,旧学当道,新学未开,知识分子与学生群体尚未形成,没有运动的主力。而1919年的形势则大不一样,第一是电报通行,报纸杂志铺天盖地;第二是已经形成了大批新式知识分子和青年学生,以爱国为己任;第三是帝国成了民国,许多城市居民感觉国家大事与自己息息相关。两厢对比,巴黎和会于中国的损害不及马关条约,却激起了更强烈的反响,也就不足为奇了。

我觉得,因为在对比这两件事情时,重要的因素并不是绝对的“进步性”,而是事件发生的具体环境,所以杨奎松先生的解释要有力得多。而且,如果我们在关于历史前提的意识上更进一步,也可以从当下的许多现象,推演、理解历史上的问题:最近几年,通货膨胀非常厉害,时常可以见到比较激进的论调。但是平心而论,现下的通胀,尚且没有夸张到极大影响大量人民生活水平的地步。但这并不妨碍我们思考,如果通胀达到几百、几千倍,到底会对自己的生活产生怎样的影响,继而对自己的心态有怎样的影响。如果了解这一点,我们就不便指责,在抗日战争结束之后的几年里许多人的选择——从许多人的回忆来看,当年的许多城市居民,对共产党和共产党的政策,并没有深刻的了解,但是国民政府货币改革失败,严重的通胀直接导致许多人的毕生积蓄化为乌有,彻底摧毁了他们对政府的信任。所以事情并不只是“宣传攻势”那么简单,即便从纯经济的角度出发,国民党政府丧失民心,也是有充分理由的。

另一方面,我们在看待一些“并不矛盾”的历史事件时,也应该培养自己的前提意识,这样才能够更深入更全面地看待整个事情。比如,董竹君女士在自传《我的一个世纪》中提到过的一件事,就很有意思:

1950年的一天,身为“锦江饭店”创始人的董竹君先生(尊称董竹君女士为“董先生”)忽然被一些职工叫道二楼大厅,一些青年员工对她说:你一直靠我们发财赚钱,剥削我们,今天要算总账了……董先生去找当时的上海市长潘汉年,潘不置可否,去找上海市工会的人,也没有回应,最后她凭自己的聪明才智,经过六个月时间,妥善解决了问题,安定了局面。又过了三个月,上海工会负责人来找董先生赔罪,承认当时她的立场是对的。对此,董先生回答说“也不怪你们,当时我还不能暴露我的政治面貌”。

事情到此为止,一般人或许只看到董先生的临危不惧,但我们若深入当时的时空,至少可以发现值得思考的疑问:第一,从各方面资料来看,董先生平时对待锦江的员工仁至义尽,为什么在1950年,员工忽然会起来要求“算账”呢,而且“剥削”的话语,不正是某些话语体系中“政治进步”、“意识觉醒”的表现吗?第二,对于这种劳资纠纷的处理,在董先生的身份没有暴露时,工会是默许支持的,但是在知道她的身份之后,态度又为之一变。也就是说,工会对于劳资纠纷的态度,似乎并不是以资方的行为为依据,而是以资方的身份为依据——不可否认,地下工作者大都会妥善对待劳工,但是,又凭什么认定非地下工作者,就不会妥善对待劳工呢?

陈寅恪先生曾说,要“与立说之古人,处于同一境界,而对于其持论所以不得不如是之苦心孤诣,表一种之同情”,按照我的理解,意思就是,不能忽视历史 的前提:社会、意识、物质等等各方面的因素,事件的发生是深受它们影响的。但是长期以来,我们在对待历史事件时,往往只强调所谓的“超然”和“客观”,忽 略甚至抹煞了这些具体的前提,所以会看到一些匪夷所思的现象,就好像黄仁宇先生所说,“历史为什么没有按照符合逻辑的方向发展呢”?

这方面 最典型的例子,是公车上书与五四运动的比较。公车上书发生在1895年,中国丢失了辽东半岛和台湾岛;五四运动发生在1919年,中国丢失了胶东半岛。看 起来,1895马关条约对中国的损害要远大于1919年巴黎合约,但是,同样是知识分子带头抗议,为何公车上书的反响远远不及五四运动?对这个问题有许多 解释,有种传统的解释是康、梁不够进步,不过我总觉得这种解释太过简单,因为它完全忽略了时空的前提。

根据杨奎松先生的总结,1895年与 1919年,虽然只相差了二十多年,社会却大不相同。在1895年,中国的信息传递方式还十分落后,电报技术并不普及,信息传播也是文言当道;另一方面, 旧学当道,新学未开,知识分子与学生群体尚未形成,没有运动的主力。而1919年的形势则大不一样,第一是电报通行,报纸杂志铺天盖地;第二是已经形成了 大批新式知识分子和青年学生,以爱国为己任;第三是帝国成了民国,许多城市居民感觉国家大事与自己息息相关。两厢对比,巴黎和会于中国的损害不及马关条 约,却激起了更强烈的反响,也就不足为奇了。

我觉得,因为在对比这两件事情时,起决定意义的并不是绝对的“进步性”,而是事件发生的具体环 境,所以杨奎松先生的解释要有力得多。而且,如果我们在关于历史前提的意识上更进一步,也可以从当下的许多现象,推演、理解历史上的问题:最近几年,通货 膨胀非常厉害,时常可以见到比较激进的论调。但是平心而论,现下的通胀,尚且没有夸张到极大影响大量人民生活水平的地步。但这并不妨碍我们思考,如果通胀 达到几百、几千倍,到底会对自己的生活产生怎样的影响,继而对自己的心态有怎样的影响。如果了解这一点,我们就不便指责,在抗日战争结束之后的几年里许多 人的选择——从许多人的回忆来看,当年的许多城市居民,对共产党和共产党的政策,并没有深刻的了解,但是国民政府货币改革失败,严重的通胀直接导致许多人 的毕生积蓄化为乌有,彻底摧毁了他们对政府的信任。所以事情并不只是“宣传攻势”那么简单,即便从纯经济的角度出发,国民党政府丧失民心,也是有充分理由 的。

另一方面,我们在看待一些“并不矛盾”的历史事件时,也应该培养自己的前提意识,这样才能够更深入更全面地看待整个事情。比如,董竹君 女士在自传《我的一个世纪》中提到过的一件事,就很有意思:

1950年的一天, 身为“锦江饭店”创始人的董竹君先生(尊称董竹君女士为“董先生”)忽然被一些职工叫道二楼大厅,一些青年员工对她说:你一直靠我们发财赚钱,剥削我们, 今天要算总账了……当然,最后董先生凭自己的聪明才智,经过六个月时间,妥善解决了问题,安定了局面,又过了三个月,上海工会负责人来找董先生赔罪,承认 当时她的立场是对的。对此,董先生回答说“也不怪你们,当时我还不能暴露我的政治面貌”。

事情到此为止,一般人或许只看到董先生的临危不 惧,但我们若深入当时的时空,至少可以发现值得思考的疑问:第一,从各方面资料来看,董先生平时对待锦江的员工仁至义尽,为什么在1950年,员工忽然会 起来要求“算账”呢,而且“剥削”的话语,不正是“政治进步”、“意识觉醒”的表现吗?第二,对于这种劳资纠纷的处理,在董先生的身份没有暴露时,工会是 默许支持的,但是在知道她的身份之后,态度又为之一变。也就是说,工会对于劳资纠纷的态度,似乎并不是以资方的行为为依据,而是以资方的身份为依据——不 可否认,地下工作者大都会妥善对待劳工,但是,又凭什么认定非地下工作者,就不会妥善对待劳工呢?

许多年前,某期《书城》上刊登过一篇文章,讨论为何我们关于历史的记忆多是宏大而抽象的,摆脱不掉文人和史官的颜色。除去官定的正史,民间的“野史”又大多数由文人骚客作主角,不见普通人的影子。作者的结论是,传统社会民智尚未发达,只有受过教育的文人有意识和能力,把自己的经历记录下来,自然而然,留下的文本有浓重的文人色彩。

如此说来,民智开化之后,此种情况应当大大改观。然而就我所见,情况并非如此。确实,晚清以降直至民国,出现了大量私人记述和回忆,所以我们可以知道,民国是一幅颜色万千的画面,教科书上所谓“万恶的旧社会”和陈丹青的“赳赳民国”,都只是其中一种而已。举个例子,“基督将军”冯玉祥的确推动了许多更加文明的生活习惯,这点可以由冯的自述《我的生活》及其它材料印证,但也有私人回忆提醒我们,冯为了推行“文明”,也一度禁止民众过春节,甚至派人检查、破坏各家的年夜饭…如此种种,抛弃是非对错,却是一种存在,惟赖多样的文本,我们才得认识全貌,而不会以简单一两个词,一两句话来概括一个人,一个时代,一个国家。然而建国之后,此风大改,虽说扫除了大量文盲,个人的记录和回忆却大大减少了(许多年前齐白石的自述到建国即止,许多年后何兆武的≪上学记≫还是如此),即便出现,也多是知识分子的诉苦篇章。可是长期以来,“知识分子”所占比例并不高,其记忆并不具备十分的代表性,而且一味的悲怆也容易引起审美疲劳,不易接受。那么,在空洞虚假的官方叙事,和哀婉反侧的知识分子话语之外,情况是怎样的?那些广大的,不甘平凡的人,他们的生活是怎么样子?他们当中的许多人,必然也有激情,也有冲动,也有智慧……这个问题必然会引起人的兴趣。

所以,姜文《阳光灿烂的日子》顺理成章地把握了相当的话语权。在其它人群大多失语的情况下,它真切地描述了青春冲动的种种表现,塑造了许多后人对那段时间的认知——许多年前,我在学校读书时,复旦大学的葛剑雄教授来讲座。到提问环节,中文系一名研究生问:文革时期,不应当是孩子们无拘无束天真烂漫的天堂年代吗?比如《阳光灿烂的日子》,说的就是这样事情嘛。葛教授的回答是:那部电影反映的,充其量是北京某些特殊群体的孩子的经历,还有大量的事实,是你没有见到,甚至也没有想到的。

“谎言重复一千遍就成了真理”,同样道理,没有其他的容易接受的声音时,片面重复一千遍,就成了全面。故而,在“文革”有关影像匮乏的情况下,部队大院孩子们无拘无束的经历,在大银幕上一再重现,就取代了其他人群的记忆,甚至模塑了后代人的认知——阶级背景、父母资历、所处城市等等背后的条件,被悉数忘却了,不用担心被抄家、不用担心批斗、也不用担心上山下乡的孩子,千真万确是无忧无虑的。简单化的结论就成了,“文革”就是孩子们的天堂年代。

之所以会出现这种情况,并不怪电影本身(我也很喜欢《阳光灿烂的日子》),原因在于其它叙述太少了,在仅有的几类回忆之间,这种记忆最对我们的味口,所以我们的希冀,也自然而然地朝向《阳光》一个方向。可是历史的颜色绝不只寥寥几种,多看一些文本就会知道,除去《阳光》,生活同样可以充满热情,只是不在大院,不在北京,而表现为其它的形态。比如熊景明女士就在回忆她父亲的文章中提到,在香港某次关于“文革”的研讨会上,有北京的学者慷慨激昂,说到周总理去世后,他们内心激荡,感到国家处在大难之中,自己有无限的使命感,熊女士大感意外,因为“同龄的云南人,完全没有对核心政治的参与感”,回顾熊女士的父亲,则更是“顺心性、听良知、追求生活”的人,“而非献身主义的时代青年”。幸好,有熊女士的回忆(《家在云之南》,熊景明 著),我们方才知道,同样身为青年,同样在大变革的年代,同样满怀期望,形式上其实有那么巨大的差异。有赖北京这位学者的回忆,更有赖熊女士的回忆(毕竟,前者更多见),我们才得以真切全面地认识那个年代,也不会简单得到“文革是孩子们的天堂”的结论。而且随着年龄的增长,我越来越觉得,首都北京、部队大院,或许很吸引人,却没有足够的代表性,只是因为别样的生活展示太少,所以吸引了足够多的关注而已。

最近我读了北岛、李陀主编的《七十年代》,更确认了自己的这种认识。这本书收集了二三十篇关于七十年代的回忆,其中占大多数的,是北岛、陈丹青等人的回忆,用不那么正经的词来形容,就是“精神贵族”。他们的经历不同于知识分子的诉苦,也不同于官方钦定的描述,他们的叙述是充满理想激情色彩的,他们熟练谈到和提及的,更多是我们耳熟能详,而又高高在上的名字,比如“大小刘麻子”之一英若诚,比如陈伯达的儿子,比如“学部”(今天中国社会科学院的前身)。他们的生活多有“往来无白丁”的沙龙和聚会,总之是让人艳羡,也占领了相当话语权的一类表述。

不过艳羡归艳羡,我更喜欢的还是另几种生活,那个时代普通人的生活,也就是范迁、蔡翔、邓刚的回忆:范迁当时是在上海印染机械厂,因为会画几笔画,被厂里宣传部门借调去画宣传画,因不满官方孔武有力的画法,时常会动脑筋“夹带私货”,尝试一些新鲜的创造,由此也卷入了黑画风波;蔡翔是上海一家铸造厂的工人,恢复高考后上了大学,他详细描述了70年代工厂里的各种景象:厂长对工人师傅毕恭毕敬,小姑娘如何把工作服穿得好看,老师傅们又如何讲起评书,“四人帮”就是奸臣,“老干部”则是朝廷的忠良……邓刚的回忆我最喜欢,除去工厂上班,他纯粹是个“山狼海贼”,就是仗着自己身体好,潜入大海捕捉海参鲍鱼等各种海产的能手。因为父亲“有问题”,他到接近30岁还没有对象,着急得上窜下跳四下打听,最后爱上了一个十九岁的漂亮女孩,并且最终娶到了这位根正苗红的共产党员——这段叙述流畅而自然,全篇没有任何关于政治的议论,言辞却带着明显的时代烙印,用大而化之的语言,描述小尔化之的平常生活:比如他说因为出身不同,自己与女孩的结合“比国共合作还要难”,但“顾不得许多,只能背水一战”,又比如他提到结婚前夜为准备婚宴下海捞海鲜,因为贪心捞得太多,无力游上岸,被巡逻的快艇发现(当时海湾是军管,防止人民偷偷爬上外国货轮),“陡然听到一阵快艇的马达声,我努力地睁开眼睛,一艘小快艇已经驶到我的面前,上面正高高地站着一个面孔阴沉的警察,那真真是政治宣传上说的“无产阶级专政的柱石铁塔般耸立”,他两眼放射着正义的光芒,正等着我自投罗网。从他脖子上挂着那个望远镜,我就明白了一切,只好落水狗一样老老实实地往小艇上爬,但哪里爬得上去,就在这时警察伸出一只有力的大手,把我一下子提上去。完全像抓到一只落水狗…”。

我之所以喜欢这类回忆,因为他们是在官方描述、知识分子苦难史和“精神贵族回忆”之外的另一种生活。虽然这类叙述不常见,但没有空洞的死板,也没有炫华的辞藻,足够真诚;更重要的是,我读过这些故事,就相信了,在城乡差异、地区差异、阶层差异巨大的中国,占人口绝大多数的普通人中,其实散落着众多不甘平庸,对生活充满热情的家伙,他们的生活,或许没有那么深重的苦难,也没有那么耀眼的文化,却保持着自己的韧性和情趣。知识分子、精神贵族,和万千个这类家伙,以及更多其他人的生活,拼合在一起,才构成了完整可信的社会和历史。

而且,这种“完整”的跨度,有时大的超乎我们的想象。在知青的回忆录里(包括在王小波的文章里),农村生活往往是愚昧而落后的,我也一直有这种印象。但是在《七十年代》中,阎连科提出:“八十年代之初,中国文坛轰然兴起的‘知青文学’,把下乡视为下狱。把一切苦难,多都直接、简单地归为某块土地和那土地上的一些愚昧。这就让我常想,知青下乡,确实是一代人和一个民族的灾难。可在知青下乡之前,包括其间,那些土地上的人们,他们的生活、生存,他们数千年的命运,那又算不算是一种灾难?” 我觉得很惭愧,这是一个很有分量的问题,但是之前我却没有想过,真实世界中的确存在着这样一面。不能容纳和驾驭这种跨度,只掌握几个简单判断,其实算不上真正的成熟。

是的,近年来我越来越认识到,真实的生活,绝难用寥寥几句话、几个词来概括,也不必对着寥寥几类描述暗自哀怜或欣喜(比如认为充满理想的生活只有一种形态,或得意或叹惋)。因为社会和历史乃是由无数个人生活,无数种颜色所构成(你以为“几种”相对“一种”就是全面吗?其实仍然少得可怜)。对那纷繁的颜色了解更多,或许越难得出一个简单的判断,认识却是更深刻、更全面了,对自己的生活也会有信心了:你可以完全淡然面对那些光鲜耀眼的生活,内心摆正的,其实是自己想要的生活,因为这样的生活,从来就存在着。

邓刚文章在线阅读:我们兄妹全是“狗崽子”

在很长的时间里,我都认为真正要做一点事情,只能来自日复一日的钻研,如“水滴石穿”那样,心无旁骛地持续做下去,才可能成功。可是,这样的生活必然又很枯燥乏味,许多人看来甚至不可理喻——那么,那些既能把事情做成做好,生活又充满趣味的人,他们到底是怎样生活的?除去运气,他们还有怎样神秘的力量?这些问题我想了很久,也实践、反思了很长时间,后来逐渐得到的一个结论:仅仅日复一日的钻研,苦行僧的做法,其实是不够的,更重要的因素,恐怕是自我管理。

“自我管理”听起来是个大词,细说起来,却并不难。古话说,没有规矩,不成方圆。那意思是,无论形态如何,总是要有一定的规则和模式。任何一个组织:学校、公司、单位、社会,总需要这样或那样,硬性或柔性的规则来约束,才能维系,才不会散架;但是个人的生活,往往在这方面有所缺乏,所谓“自我管理”,可以理解为,认识、培养、建立、维护自己生活的规则和模式,然后才能让自己的生活变成某种样子(恐怕没有人希望自己的生活是一盘散沙,毫无章法可言)。

以我的经验来说,“自我管理”主要包括以下三个方面:

一,自我认识。认识自己,需要培养“旁观”能力,建立看待自己的全新视角。我们都有感觉,自己有时会“莫名其妙”做一些事情。许多人把这类行为归结为“感性”,但这并不正确。许多“莫名其妙”的行为,其实是自己的理性未能充分发挥的结果。我自己就有很多经历:明明可以准备周全再动手的事情,却“稀里糊涂”就开工了,结果多费许多时间精力;再比如,犯困了就认为自己休息太少,而没有认真想过提高休息质量,增加体育锻炼,其实也可以保证精力。这类事情发生在人家身上,我们可能很容易看出是“不够理性”,但发生在自己身上,就往往找出各种理由。可是,自己的情况到底是怎样,自己其实是最有可能认识清楚的,所以,学会旁观自己,加深对自己的认识,生活就可以少走许多弯路。

而且,即便是“感性”的行为,也可能是有章可循,可以认识的。仍然拿我自己做例子:生活中,情绪会起伏,有时开心,有时失落。以前我总觉得,这些是无可避免的,“坦然面对”就好。但后来我尝试去思考,遇到什么样的事情,我会开心;遇到什么样的事情,我会失落。这些事情,到底值不值得我开心或失落?为什么有时候听了其他人几句话,自己的情绪就会大不一样,我能不能自己想到这些话,这样就不用再借人家的口说出来?必须承认,思考这样的问题确实有些困难,可是一旦你认识了自己情绪的规律,许多问题就迎刃而解了,想放松的时候可以更尽兴(不用背着包袱去开心),生活的负担也减少了很多(大可以“清醒”地装糊涂,忽略许多事情)。

二,自我克制。认识自己到一定程度之后,我们就摸清了自己生活的特点和边界。与自己期望的生活对比,就容易看出有多少重复,哪些地方要扩展,哪些地方要收敛。一般来说,扩展的难度并不大——是你真正想做的事情,总会有动力去做的;收敛的难度却大得多,许多东西,我们已经“习惯成自然”了,改变习惯,不是容易的事情;更重要的是,社会上,诱惑总在不断地冒出来;生活中,惰性总在不断地渗透出来。这时候,自我克制的重要性就体现出来了:诱惑也好,惰性也好,往往并不是我们真正期望的,必须把它们拒之门外。

而且,自我认识更深刻,自我克制的力量也就更强。比如说,长假的前几天,往往是工作和学习最松懈的时候,大家都“无心”,更多地在消磨时间。但是我仔细想想,自己正处在怎样的阶段,还有哪些事情要做(即便近期手头的事情做完了,也可以提早开工长期的、以后的计划),如果发现“无心”地消磨这些时间,自己其实并没有太多收获,反而可能需要将来多花更多时间来弥补,就更能克制自己——不仅仅是意志的力量,还有理智的力量。

三,自我提醒/监督。必须承认,我们都是固执的,习惯的养成,生活的改变,都不是一蹴而就的。有些问题,即便我们能认识清楚,也足够克制,仍然不能迅速解决,这时候就需要对自己的提醒和监督了。它们可以提供持续不断的反馈,在反复的刺激下,习惯才能养成,生活才可能改变。

自我提醒/监督的有效办法是要不断地反思、总结。我刚开始开车的时候,“自然不自然”地喜欢急加速、路口抢红灯,虽然能想明白这样并不好,也有足够的克制力,但还是有时候“无意识”地做这类事情。为了戒除这不好的习惯,我每次熄火下车,都要想想自己这一路有没有急加速,有没有抢红灯,如果有的话,一定要再三提醒自己,以后不能这么干。这样过了一段时间,我确实能够“自然”地、心平气和地开车了。再比如,我时常会给自己制定一些专业书的阅读计划,预计是每天都要看,但往往因为各种原因中间有空隙、间隔。为了避免这种情况,如果昨天坚持阅读了,我会在当天的日记里给自己一些积极的反馈,否则就要说明理由,提醒自己今天绝不能空缺。这样持续地提醒/监督下来,即便计划中有错漏,有变故,也不会影响整个局面(要补充的是,写日记确实是非常好的提醒/监督手段,这是我的亲身体会)。

看到这里,有人可能会说,即使做到上面这三方面,能够自我管理,生活不是同样枯燥乏味吗?答案却是否定的。前面说过,没有规矩,不成方圆。大多数人都希望自己的生活能变成理想的样子(即便做不到,也要接近),这样内心才更舒服,更满足。身为成年人,你基本不能指望依赖他人来约束和管控自己——即便有人愿意这么做,你也未必会舒服。这时候,自我管理的重要性才体现出来。

而且,自我管理也不等于苦行僧式的生活。有个笑话说:程序员为什么要在床边放两个杯子,一个有水,一个没有水?因为他不知道自己夜里是要喝水,还是不要喝水。从另一个侧面来看,它也说明一个道理:不管要不要喝水,至少要有个杯子。同样,生活可以很随意很闲适,也可以很充实很匆忙,无论它是什么样子,你至少要能如愿管理自己的生活——该放松的时候要能放得开,该收拢的时候要能收得拢。而这,正是自我管理的意义所在。

我为何爱读代码?你为何也应当爱?

原文:Why I Love Reading Other People’s Code And You Should Too by Alan Skorkin

翻译:Yurii

我恨读代码

我发现,许多程序员都讨厌读代码——拜托别掩饰了,承认吧。差不多每个人都喜欢写代码——写代码乐在其中。可是,读代码真是不容易,而且还很烦人,又无可逃避,其他人写的代码总是很垃圾(即便不说,我们心里也这么想的)。即使自己写的代码,过几个小时再看也有点垃圾,过的时间再久点,就更垃圾了。那么,还有什么理由去看别人的蹩脚代码,而是不自己写几手漂亮的?能不能暂且忽略这个问题,花上几个小时看别人的代码,再回头来看自己的是不是还那么漂亮?即便有位大师坐在你面前,如果你不能从他身上学习,你永远也成不了大师。办法之一就是找到这么一位大师,让他手把手地教会你全部知识。有这可能吗?——当然有,只是很难遇到这顶好的运气。不过你也不必奢求那么幸运,做程序员这行就很幸运,因为大师们的所有思想和技艺都凝铸在他们的代码里,供我们学习。你要做的只是阅读代码——当然,如果有人给你一点点地讲肯定更节省时间,但这基本属于痴人说梦。换句话说,要相当个好木匠,得仔细研究大量的精美家具。

我热爱读代码,我总是直观地认为读代码的收获很大,没错,它可能有点讨厌甚至烦人,但你的收益绝对大过这点麻烦。举个例子,你要当大作家,是不是只关心自己写东西就够了?你可以试试看,但是估计不会折腾不出什么名堂。公认的事实是,多数大作家都是会如饥似渴大量阅读的。想写出好的作品,必须先阅读其他大作家的作品,吸收不同的风格,了解他人的尝试,然后才可以培养自己的创造力。这样,你的知识才能逐渐积累,最终你写的东西才有几分成熟,你也才会找到“感觉”。写代码也是这样,如果你不去阅读那些伟大的代码,怎么可能把程序写的漂亮?阅读伟大的代码之于程序员,就如同阅读伟大作品之于作家(我不敢掠美,这句话是Peter Norvig(译注:Peter Norvig是著名的Lisp程序员,现任Google研发总监)说的,他可不是个简单人物,所以好好记住这句话吧)。

即使上面说的你都不信,但有个事实无可否认。要想当个称职的开发人员,能熟练阅读代码是非常重要的。如今,只要不是闹着玩的项目,都是团队协作的成果,所以总会有这样的代码:它不是你写的,但你必须跟它打交道,去修改,或者去扩展。于是,阅读代码很可能就是你身上最重要最常用的能力了,咬紧牙关练好这门本事吧——而且,要快。

要像…会读代码的那些家伙一样…阅读代码

我都说不清有多少次见过这样的事情了:程序员把一段不熟悉的代码上下拖动,几分钟之后仍然一脸迷离。不久他们就宣布,这段代码根本没法看懂,更不必浪费时间了,可以想办法绕过这个问题。我不知道他们真正要做的是什么,一点点弄明白这段代码的意思,还是睁大眼睛等着开窍?阅读代码不靠成年累月死盯着看,你要做的是弄懂它,把它变成自己的。下面说的是我用的一些技巧,但不是全部,不过我觉得这些非常有用。

看代码看到目光迷离

1. 尝试亲自构建和运行程序。通常这一步很容易做到,比如你看的是真正运行的工作代码时(而不是不知来源的古怪代码)就是如此。不过也不是每次都很容易,如果不能很容易地构建和运行,你可以在完成构建和运行的过程中,认识到代码的高层结构。而且,阅读工作代码,你会非常熟悉如何构建项目。构建通常是复杂的,但是了解构建过程,知道代码是如何变为可执行程序的,会大大加深你的理解。

2. 别死盯细节。读代码要做的第一件事,是找到对代码的结构和风格的感觉。开始应当浏览,并且努力找出各部分代码都在干什么。这样你能熟悉整套代码的高层结构,也会明白你正在看的是什么样的代码(重构良好的,还是乱成一团的)。这时候你要做的就是找到入口(可能是main函数,也可能是servlet,controller之类),看看下面的分支是怎么展开的。这一步不要花太多时间,你对全部代码更熟悉之后,随时可以退回来。

3. 确保理解所有构造(construct)。除非你非常精通这门编程语言,否则多半还有些东西是你不知道的。在概略了解代码的阶段,要记下每一个不熟悉的构造。如果这样的构造有很多,下一步就不言自明了。如果搞不懂代码行为的意义,你什么也干不了。即便你不熟悉的只是少数构造,仔细观察推敲没准也是好事。你可能会找到一些以前不知道的关于这门编程语言的知识,我就很乐意为此花上几个小时。

4. 待熟悉了大多数构造之后,就可以搞几次随机的深入探查了。做法类似第2步,快速浏览代码库,但是这次要随机抽几个函数或者类,一行行地看下去。真正的考验现在才开始,但你的收益也是从这一步开始显现。主旨是:真正深入到你所阅读的整套代码的概念体系(组件结构)当中。这又是一个速度快不起来的步骤,但是在这一步,一定要尝试深入理解若干繁杂的细节。和第2步一样,在这一步,每次你多了解了一些上下文再回头看看,你的理解就更深入一些。

5. 前几步中肯定还有你不明白的地方,现在最合适的就是跑几个测试,看看已有的测试。测试很可能会大大打消你的疑惑,加深你对所测试代码的理解。我时常不能理解,为什么有些开发人员在阅读和理解代码时,忽略严密而精巧的测试套件。当然,也有时候是因为没有测试程序。

6. 如果没有测试程序,这时候就该写上几个。这样做有很多好处,它会加深自己的理解,它可以完善整个代码库,在阅读代码的时候也在写代码,这样对已有代码和你都有好处,你也可以真正动手参与进去。即便有现成的测试程序,为了加深自己的理解,你也可以再写一些。测试人家的代码,一般要求换个角度思考,之前你感到迷惑的概念也会变得更清楚。

7. 把弄不懂的部分拿到单独的程序中来。我发现,读代码时这样做,哪怕只是为了调节阅读的节奏,也是非常有乐趣的。即使你不理解代码的底层细节,也可能会对代码的功能有些高层面的想法。那为什么不把一些功能抽到单独的程序中测试呢?如果只运行一小段程序,debug就容易多了,而且这样的过程反过来又会加深你的理解。

8. 代码很乱(dirty)很糟糕(smelly)?那么重构吧。我可不是建议你把整个代码库推倒重来,但是重构一些部分确实可以让你的理解更上层楼。一开始要做的是把你明白了的功能变为独立的函数。在你真正理解之前,重构之前的函数只是看起来没问题,而重构可以把它们变成你想要的样子。依靠重构,你可以把代码变成自己的,而不要全部重写。好的测试程序可以帮上忙,不过如果你没有,就一边测试一边重构吧,而且只改动那些你确认弄懂了的功能。即便测试看起来太少太不完善,也要相信你自己的开发水平,有时候你只管大胆尝试就好(如果确实需要,总是可以回退(revert)的)。

9. 如果上面说的都不管用,就找个同伴跟你一起读代码。能从读代码中受益的可能并不只有你一个人,所以不妨抓住其他人,一起阅读。不过别找专家,他们给你的解释都是高层面的,这样看代码时注意的那些细节就都被忽略了。如果找不到人一起阅读,你又实在看不懂,有时最好的办法就是问别人。可以问你的同事,如果你在读的代码是开源的,也可以在网上问问其他人。记住,这只是最后的办法,不要一开始就这么做。

如果时间很紧张,短时间内必须弄懂某些代码,上面的步骤中只能选一步,我会选择重构(第8步)。你可能没法明白太多东西,但你肯定可以理解真正动过的部分。无论时间是不是紧张,你要记住的是:如果你第一次接触重要的代码库,肯定不能一下子就看懂,甚至不可能很快看懂。你可能需要耐心读上几天,几周甚至几个月——坦然面对就好。即便有专家坐在你身边,也省不了太多时间(我写的关于教和学的系列文章最后一篇就会谈这个问题)。如果你读(或者写)代码的耐心足够,方法得当,你肯定能成为对项目所有方面都非常熟悉的人,也是大家对代码库有问题时出面解答问题的人。你也可以不阅读代码,选择成为那个总想找人来解释的家伙。我想要做哪样的人,我自己很清楚。

抓住阅读代码的机会,别错过

我们都喜欢新写代码,它的诱惑力在于,我们能搞定问题。起码,这次搞不定,下次可以搞定。真相是:你在实践中不断提高,永远不可能一下就彻底搞定。这就是新写代码的价值所在,你在练习,你的水平在提高,但是阅读和改动其他人写的代码也很有价值(至少不亚于自己重新写),从中你学习到的不光是有价值的技术知识,还有关于整个工作领域的知识(毕竟,代码才是文档的最终形式),这种知识通常更有价值。

每一段不遵循传统的,莫测难懂的代码,都是有价值的。你知道我说的是什么,虽然它看起来一团糟,但本意并非如此(也可能因为它是Perl代码:))。每次我看到这样的代码,我都这么想。不妨把阅读它当作猜谜游戏,想想你能学到什么。是的,这很折磨人,但必须承认,你也希望能动手就能写出这么糟糕的代码。如果你花时间阅读这样的代码,你肯定更可能写出这样的代码——这倒不是说,你一定会写这样的代码,但你肯定希望自己能够。最后要说的是,态度总是非常重要的。如果你把阅读代码看作闲杂事,那它就是闲杂事,而你肯定会逃避,但是如果你把它看成机会,事情就不一样了。

朝三暮四是个老典故:古时候宋国有个人养了一群猴子,早上喂它们三颗果子,晚上四颗,猴子就恼怒;如果改成早上四颗,晚上三颗,猴子就高兴了。小时候听了这个故事,总觉得猴子太傻:反正每天都是七颗果子,何必在乎早晚呢?长大了做许多事情也是如此,反正总量不变,朝三暮四还是朝四暮三,只有时间的差别而已,想找出什么分别都是徒劳,还不如索性从容点。而且,许多人的潜意识里似乎也这样认为的,至少争辩起来,许多人都会这样反驳,典型的句式就是“反正……,何必呢?” 可是,我又逐渐发现,有些事情似乎不是这样的。

就从生活的小事说起吧:现在物价飞涨,当过家的人都知道,有些菜简直是一天一个价,许多事情就不再是“早晚一样”了,能赶早的就得尽量赶早,否则,拿同样的钱,就买不到同样多的菜,要买同样多的菜,花的钱就不一样。换句话说,在迅速变化的形势面前,朝三暮四还是朝四暮三,就不再只有时间的差别,而是有了实实在在的不同。

而且,即便不是在迅速变化的形势下,朝三暮四和朝四暮三,也可能存在真正的分别。还是拿我自己当例子,我生活还算规律,晚上一般十二点左右睡觉,早上六点半起床,之后要锻炼、读读书、收拾收拾,八点多出门上班,时间充裕,动作从容,自己也比较满意。可是有一天,周老师跟我说,晚上早点睡觉,早上早点起床,这样可以做的事情多得多。开始我并不相信,抱着怀疑的态度尝试了几天之后,发现果然如此。可是,这是为什么呢?我仔细思考之后,终于找到了原因:我自己习惯每天要认真读点书学习点资料,大概是每天2小时左右,以前因为早上六点半起床,留给看书的时间大概是二十到三十分钟,刚刚进入状态,想清楚几个题,就得去忙别的了。提早到五点半起床之后,留出来看书思考的时间就多了很多,夸张点说,可以很从容地安排两节自习课。相应的,晚上不必看那么长时间的书,也更容易保持清醒的头脑,效率也高了不少。看来,“朝三暮四还是朝四暮三”的道理,也可以用在学习上:相比之下,“每天学习xx小时”这样的目标,还是显得太粗了,更细致更妥善的安排,完全可以收获更好的效果。

前些年我读冯仑先生写的《野蛮生长》,也见到了道理:年轻的时候,到底是多玩乐一些好,还是多积累一些好?对这个问题,他似乎并没有给出明确的答案,如果一生中用来积累的总量和玩乐的总量差不多,年轻的时候多积累一些,虽然看起来玩的少了点,但年纪大的时候收益更多一些,玩起来的后顾之忧也少一些;如果年轻的时候玩得多一些,老了就得花更多的精力补上积累的课。我想这说法确实有道理,此类问题也确实不宜从“总量一定”的角度来看:积累和玩乐之间,到底是选择朝三暮四,还是朝四暮三,它们之间,远远不只是时间的差别。

按:QQ与360的大战已经持续一段时间了,而且显然成了最近的热点。网上网下,大家都在讨论,我也有些看法。不过,各方动态和大战进程已经有很多详细的报道,这里不赘述,只说说我的想法。

公关的新形势

公关(PR,Public Relation)是现代企业不可忽略的一面,无论是推广品牌价值、营造良好形象、应对负面信息,都离不开公关。传统的公关往往更侧重也更善于与媒体打交道,因为媒体几乎“决定”了公众的情绪——至少是垄断了情绪的表达。但是,随着博客尤其是微博的兴起,越来越多的个人成为了“自媒体”(we the media),即便在传统媒体的擂台上打了胜仗,也往往无法堵住所有用户的嘴,不一样的声音仍然会发出来,传播开来。“公关”丢了“公(公众)”,只剩下“关(关窍)”,自然成了无本之木,效果也大打折扣。

在这次的大战中,QQ和360的公关策略就是两种思路的典型代表。QQ更“愿意”(姑且这么认为)使用接受专访等方式发布和传播信息,立足点也多是“对方这么做,会把我们(QQ)如何如何”的逻辑(这更适合教室,而不是广场),微博上发布的信息也以“通告”口气为主,说是“以用户为核心”,却没有体现和传达出这种理念,更多的是自顾自地论证“不以用户为核心就没有腾讯的成功,没有全球第三的互联网公司”。这样的战法,似乎更希望也更合适在媒体擂台上跟360“一对一”,由专家点评、裁判论断,与普通人的感受相差十万八千里;然而昔日台下默不作声的观众早已登上擂台,感同身受地近距离观战,他们可以影响甚至决定舆论形势。

相反,360更多通过微博、论坛进行互动,反馈迅速而精准,而且强调始终“用户(您)会受什么影响”,而不是“我们(360)会受什么损失”。在公众表达渠道日益丰富,表达意愿日益强烈的今天,两套武功的高下立现。据我观察,QQ酝酿出台每一招都很正式,义正辞言,但360都可以迅速以草根形式应对,以巧劲化解;几个回合下来,360在公关上已经确立了完全的优势。

QQ以IM为核心的弊端

QQ庞大的“帝国”,始终是以IM为核心的,其它业务也多是以IM为入口和推动力。这样的好处是,具备足够黏性的IM能为其它业务提供可靠的依托和支撑,弊端则在于,一俊遮百丑——其它业务相对羸弱甚至不够称职,平时却没有机会暴露出来,比如上面提到“不称职”的公关就是如此。

QQ的公关的不称职,不但表现在缺乏应对新媒体、新形势的能力,而且在一些基础方面都很差劲。比如在微博中说“这种“云查杀”模式的指令来自服务器后台,在远程遥控安装在2亿台电脑里的360安全软件。这甚至是连微软、谷歌等国际互联网巨头也没有的超级能力”,措辞失当,贬损变成了褒扬;又比如在新闻发布会中,其公关经理前一分钟还说“昨晚腾讯一万多名员工,彻夜不眠”,后一分钟又说“其实作为有6千多名员工的公司我们有很多的办法结束这场战斗的”,且事后既没有“公关”修改此错误(照道理说,公司员工数目是一个相对稳定的常量,也无须保密),也没有给出解释,实在让人大跌眼镜;很难想象QQ帝国的公关部是这样的素质,可能的解释是,因为IM太核心、太显眼,公关部门的羸弱被掩盖了。

IM巨大用户量给QQ带来的好处,有时也可能变成坏处。前几个月QQ先后推出了“植物精灵大战格格巫”和“葫芦娃大战蛇妖”两款游戏,上线就引起强烈负面反响,旋即下线。我听闻这两款“山寨”游戏并非公司战略,而是个别部门自作主张的结果,他们认为随便山寨一个热门游戏,傍上QQ用户这棵大树就可渔利,不料恶评如潮,公司紧急叫停。没错,QQ确实模仿过不少产品,但做的成功的模仿,都离不开周密策划与精心投入(这就是我反对把QQ的成功简单归因为纯粹“模仿”的理由)。此类“仓促退出又迅速召回”的草率举动,对小公司来说或许无甚影响,但由QQ推出,造成的印象就是QQ恣意山寨,借IM入侵他人地盘,即便迅速召回也是赔了夫人又折兵,恶劣的印象一经留下,就难以磨灭。此次大战中,其它许多力量都暗中观战、巴不得QQ落败的心理,或许也与此类印象有关。

我们应该怎么看

之所以提到这个问题,主要是因为昨天看了霍炬的这两篇文章(流氓的背后是什么金山的流氓事)后的留言。大多数留言可以这样概括:要么“支持360”,要么“支持QQ”,要么不分黑白地大骂,却根本没读懂,甚至也没看文章的内容。
这里又不得不重弹“独立思考”的老调,所谓“独立思考”,就是不要“抽象支持”360或者QQ来“保持立场”,也不要笼统地“各打五十大板”以示公平,而要根据具体事件来判断。很可能在这件事情上是360有道理,而在那件事情上是QQ有道理;也可能,在某件事情上,QQ和360都不是“完全有道理”或者”完全没道理“,而是“各有一部分道理”或者“各有一部分错误”。只有摆脱情感好恶的垄断,脱开抽象笼统的概念,细致到具体的问题,仔细听取、分析他人的看法,才算得上真正具有了“独立思考能力”。

今天我的同事老赵 @jeffz_cn 问我,有没有办法用正则表达式匹配“不包含某个字符串”的文本,正好,我在写作的《正则表达式傻瓜书》中也提到了这类问题,就把这一节放出来,给大家参考,也希望大家多提建议(尤其是配图方面)。

正则表达式的与或非

我们都知道,写正则表达式有点像搭积木,复杂的功能总可以拆分开来,由不同的元素(也就是子表达式)对应,再用合适的关系将它们组合起来,就可以完成。在这一节,我们讲解常见的与或非关系的表达。

“与”是最简单的关系,它表示若干个元素必须同时相继出现,比如匹配单词cat,其实就是要求字符c、字符a和字符t必须同时连续出现。

正则表达式表达“与”关系非常简单,直接连续写出相继出现的元素就可以,我们可以想象,在各个元素之间,存在看不见的连接操作符·,比如上面匹配单词cat的正则表达式,就是『cat』,我们可以将它想象为『c·a·t』。

“与”关系也不限于字符之间,任何子表达式都可以用它来连接,如果我们把上面单词中的a替换为字符组『[au]』,表达式就变为『c[au]t』,你可以想象为『c·[au]·t』。

“或”是正则表达式灵活性的重要体现,我们可以规定某个位置的文本的“多种可能”,比如要匹配cat或是cut,在正则表达式看来,就是“字符c,然后是a或u,然后是t”。

如果“或”的多种可能都是单个字符(一般要求ASCII字符,中文字符等多字节字符的情况,可以参考本书专门论述的章节,此处仅以ASCII字符为例),就可以用字符组来表达“或”的关系,比如上面的cat或者cut的情况,正则表达式写做『c[au]t』,其原理如下:

更复杂的情况是“或”的多种可能,并非都是单个字符,有些可能是多个字符。比如,我们可以看一个更复杂的例子,不仅要匹配cut,还要匹配c开头、t结尾的单词chart、conduct和court。也就是说,在开头的c,结尾的t之间“可能”出现的是:uharonducour。

遇到这种情况,就不应使用字符组,而应当使用多选分支『(…|…)』,将各个“可能选项”列在多选分支中。于是,正则表达式变为『c(u|har|onduc|our)t』,其原理如下:

关于多选分支,还有两点要补充:

多选分支也可用于“每个选择都是单个字符”的情况,比如『c[au]t』写成『c(a|u)t』是没错的,但字符组的效率要远高于多选分支,所以,在这种情况下,推荐使用字符组『c[au]t』;

默认的多选分支『(…|…)』使用的括号是会捕获文本的,也就是说,括号内的表达式真正匹配成功的文本会记录下来,匹配完成之后可以提取出来,具体到上面的例子,就是我们有办法在匹配完成后“提取”出u或har或onduc或our。但许多时候,我们需要的只是整个表达式的匹配,而不关心“匹配时到底选择的哪种可能情况”,在这种情况下,我们稍加修改,使用“不捕获文本的括号”,可以提高效率。不捕获文本的写法也很简单,只是在开扩号之后加上字符『?:』,也就是『(?:…|…)』,具体到上面的例子,就应该写成『c(?:u|har|onduc|our)t』。这样做虽然繁琐点,但效率有保障,阅读起来也不困难,我推荐养成这种习惯,只要用到了括号,就想想是否真的要捕获括号内表达式匹配的文本,如果不需要,就是用不捕获文本的括号。

“非”看起来简单,其实是最复杂的,以下分几种情况讨论。

首先讨论针对字符的“非”:不容许出现某个或某几个字符。这是最简单的情况,直接用排除型字符组就可以对付,仍然用上面的例子,如果要匹配的单词是c开头、t结尾,中间有一个字符,但不能是u(也就是说,整个单词不能是cut),直接用『c[^u]t』就可以了,若中间的字符不能是a或u(也就是说,整个单词不能是cat或cut),则表达式改为『c[^au]t』。

如果你认真读过关于排除型字符组的章节,肯定会知道,这个表达式能匹配的只是cot之类的单词,因为中间的排除型字符组『[^au]』必须匹配一个字符。可是,如果我们还想要匹配chart、conduct和court,怎么办?最简单的想法是去掉排除型字符组的长度限制,改成『c[^au]+t』——不幸的是,这样行不通,因为这个表达式的意思是:c和t之间,是由多于一个“除a或u之外的字符“构成的,而chart、conduct和court,都包含a或u。

我们回头仔细看看这个“非”的逻辑,我们发现,其实我们要否定的是“单个出现的a或u”,而不仅仅是“出现的a或u”,所以才出现这样的问题,要解决这个问题,就应当把意思准确表达出来,变成“在结尾的t之前,不容许只出现一个a或u”。想到这一步,我们就可以用否定顺序环视『(?!…)』来解决了,它表示“在这个位置向右,不容许出现子表达式能够匹配的文本,我们把子表达式规定为『[au]t\b』(最后的『\b』很重要,它出现在t之后,保证t是单词的结尾子母)。

有了这点限制,匹配a和t之间文本的表达式就随意很多了,我们可以用匹配单词字符的简记法『\w』表示,于是整个表达式就变成了『c(?![au]t\b)\w+t』。请注意,这里出现的并不是排除型字符组『[^au]』,而是普通的字符组『[au]』,因为否定顺序环视『(?!…)』本身已经表示了“否定”的功能。

如果我们再进一步,“整个匹配文本中都不能出现字符串cat”,要怎么办呢?许多人的思路就是借鉴处理“或”关系的思路:既然字符组对应单个字符的情况,多选分支对应多个字符的情况,那么在否定时也是这样。可惜,正则表达式并没有提供与多选分支对应的“否定”结构,那么,应该怎么办呢?

解决的办法还是得依靠否定顺序环视——“整个匹配文本中都不能出现字符串cat”,换句话说,就是“在文本中的任意位置,向右,都不能出现该字符串”。因此,我们用两个锚点『^』和『$』,分别匹配整个字符串的开头和结尾位置,再用否定顺序环视『(?!cat)』表达“不能出现字符串cat”。

即便知道了原理,也不见得能写对正则表达式,比如『^(?!cat).+$』就是不正确的,因为它只限定了在文本的开头(也就是『^』)右边不能出现cat,而我们真正要做的是,在文本的每一个位置右边,都不能出现cat,所以应该改成『^((?!cat).)+$』;但这还说不上完美,根据前面提到的关于括号捕获的知识,因为此处并不需要括号捕获的文本,所以最好使用非捕获型括号『(?:…)』,最终我们得到的表达式就是『^(?:(?!cat).)+$』。

« Previous PageNext Page »