|
% This is the file GB.tex of the CJK package
% for testing Chinese (in GB encoding).
%
% written by Werner Lemberg <wl@gnu.org>
%
% Version 4.8.0 (22-May-2008)
\documentclass[10pt]{article}
\usepackage{CJK}
\usepackage{parskip}
\begin{document}
\begin{CJK*}{UTF8}{simsun}
\CJKtilde
\title{程序员的矛盾论}
\date{}
\author{包昊军 (flonk_zj)}
\maketitle
\section{矛盾无处不在}
矛盾就是江湖。只要有人的地方,就有江湖。只要有人的地方,也就有矛盾。做
为一个程序员,很不幸,我们也是人。而不是神。只有Linus那样的人才敢公然宣
称自己是神,别人没了他不行。结果还是让很多人不舒服了。
程序员是干什么的?写程序的。程序本来没有,程序员把它写出来,程序就有了。
有和没有,是最经典的矛盾。就像0和1。
程序员写出来的程序,有的很好,有的很烂,矛盾。程序员写程序要用编程语
言,编程语言有很多种,有C,C++,选C还是C++呢?矛盾。还有
Java,Python,Perl,Bash,Sed,Awk,Lisp,Ruby,汇编。纸带打孔。程序员
都需要花时间学习,写程序也要花时间。学得太多了,会导致写程序的时间少
了,相应的写的程序也少了,于是水平可能就不会有写过很多程序的人高。
用什么操作系统呢?Windows? 还是Linux?用什么操作界面呢?图形的?命令行
的?用什么编辑器呢?Vim?Emacs?用集成开发环境?不用?
矛盾无处不在,程序员写的每一行代码,都是矛盾冲突的结果。
面对这么多矛盾,怎么办?
这个问题,是没有答案的。这是一个哲学问题,而所有的哲学问题,都没有答案。
就像生与死,作为人,每一个人都得面对。有些人选择不活了,有些人选择快乐
地活着,还有些人选择堕落,有些人选择活得不明不白的。哦错了,最后一种人
不作选择。
当一个快乐的程序员,其实很简单。
\section{学习}
程序员一生都应该不断学习。这一点是毫无疑问的。与学习相对立的,不是不学
习,而是创作。创作出东西来让别人去学习。不学习不创作的时候,大家爱干嘛
干嘛,咱们这里就不说了;创作是下一节会讲的。所以这一节主要讲讲学习。
怎么学习真的很重要。一个人的话大致有三种学习的方法:读书,读代码,读文
档。几个人的话当然就可以互相学习,但这个我这里不详细谈,留给您自己思考。
\subsection{读书}
书,好像谁都会读,因为谁都是十几年甚至二十年的书读下来的。我也一直以
为,自己对读书应该没有任何问题,no problem at all。
直到我读了那本书,我才知道,问题出大发了。
那本书的名字叫《How to read a book》。
二十多年来,我从来没有想过,自己为什么要读书;从来不知道,一本书,除了
从头读到尾之外,还有其他不同的读法。读了那本书之后,我全知道了。
读一本书,以前我一直以为是为了考试能拿高分。所以当后来我没有试考了的时
候,我突然觉得自己不会看书了。真是被应试教育给害惨了。
看书千万不要每一本都从头看到尾。二十一世纪最缺的是什么?人才!人才最缺
的又是什么呢?时间!作为一个高科技人才,我们真的不能那么奢侈。
所以如果你决定一本书你要从头读到尾的话,请确保这是你的一个理智的,明智
的,清醒的决定,而不只是你二十多年的习惯在作祟。
怎么作出理智、明智、清醒的决定呢?
首先要克服自己的那个二十多年的习惯。这不是一件容易的事。我们必须认识到
了,到现在这把年纪了,不是每本书都值得那样去读。一个娃娃拿到一本书,里
面的东西它啥啥都不懂,所以必须从头到尾的读。所以国家教育机构要做好选教
材的工作,尽量保证娃娃们读到的书不是坏书,不值得读的书。
如果作为一个成年人,还不会自己选书,不对自己读什么书怎么读负责任的话,
那就还是停留在娃娃时代,或者说的难听一点是脑残了。娃娃们有的是时间,成
年人没有。娃娃们的世界很简单,没有那么多“矛盾”,成年人很遗憾,很复杂,
充满矛盾。
\subsection{快速阅读}
读书一定要快,时间就是生命。一本书看不懂,扔掉,换一本。把所有书都看完
了怎么办?把以前扔掉的再捡起来,看看现在是不是好一点,能多看懂一点了。
这是最简单,最不动脑子的做法了。
后来,看了那本书之后,我又学会了一些新的方法。
比如,尽量理解作者,学习作者的语言。不要奇怪,作者说的难道不就是中文或
者英文吗?是的,但又不是。每个人说的语言都是不一样的,都是一种独特的,
只属于说话人一个人的语言。就像人的掌纹、瞳孔、声音有不同,语言也有特征。
红楼梦研究里一项很重要的发现是一个搞计算机的人作出来的,他用统计学原理
对前八十回和后四十回的语言进行了分析对比,结果得出来这两部分好像的确不
是曹雪芹一个人写的。
所以当你读比如一本中文书的时候,你以为那全是你的母语,结果你就放松警
惕,认为不需要费什么功夫就能读懂,结果不料的是,这其实是一门外语。你应
该把它当成一本外语书来读,尽量理解作者的语言;表达一个意思可以用不同的
词汇,他的词汇集可能跟你的有差异,你应该尽快消除这种差异,诸如此类。我
说的没有那本书好,所以推荐你尽快去读一下那本书吧。
最重要的还是你自己要战胜自己的想把书从头读到尾的“本能”,二十多年刻苦训
练出来的本能,现在你应该做一些反训练,比如,故意的胡乱、飞快地读一本书。
我想从头读到尾,可是我没钱没地位。
\subsection{融会贯通}
书读多了以后自然而然的会发现,其实很多书里面都讲得是一个道理。但是又讲
得有点不一样。这时候你需要去做一些联合阅读。就是把几本书放到一起读,有
对比的读。还是推荐你去看那本书。
有一点要注意的是,不要只看技术书。多看点杂书有很多好处。比如金庸的武侠
小说,里面有一段描写张无忌向张三丰学习太极剑的情节,大家应该都去看一下。
张三丰临阵当着敌人的面向张无忌教太极剑,一招一式教得很慢,大家都看得清
清楚楚。朋友们都很着急,这么精妙的武功,可是全被敌人也看去,还有什么
用?敌人则很开心,哇,一会这一招我就这么破解,那一招我那么破解,全部搞
定。结果教完以后,张三丰问无忌,记住了吗?无忌答道,忘记了一大半。这下
朋友们更着急了,张无忌你事到临头怎么变笨了呢,我都记住了八九成,你还忘
记了一大半,要不我给你开开小灶吧;敌人则更开心了,哇,搞半天这张无忌还
是个白痴,一会打起来绝对没问题了。结果张三丰说,好,我给你再教一遍。这
遍教得还是很慢,可是招式跟刚才好像有点说不上来,不一样了。朋友们又更着
急,敌人则又更开心。这遍教完,张无忌说,还剩三招没忘记;想了一会儿,说
全忘了。一架打下来完胜。这个故事告诉我们,把书本上教的东西全记住是没太
大用处的。应该全部忘记。全记住了意味着你学到的东西全是书本上的,全忘记
了则是说你学到的东西全是你自己的。我们应该当无忌,不要当赵括。
在搞编程的时候也是这样,比如有些人刚学完面向对象,容易哪儿哪儿都用继
承,都用面向对象,用的却还都是皮毛。这样就不对,不好。
还有一个故事,这是真事儿哦。在一个李小龙的纪录片里,李小龙教一个演员拍
武打戏。他用夺命剪刀腿把人家的脖子给绞住了,对方动*不得。李小龙教他,
你这时该怎么办呢?那人以手拍地,表示认输。李小龙笑道,你应该用牙咬我。
那人恍然大悟。就在他学会了这么厉害管用的一招开心得不得了的时候,李小龙
却警告他,“千万不要想着去咬对手,你会失去你的牙齿”。这个故事告诉我们,
千万要本着问题去找解决方案,而不要本着一个解决方案去寻找问题。如果你只
想着用牙咬能干掉对手让自己脱离困境,那离你牙齿跟你说再见为时不远了。
再回到编程技术书上来,《C++的设计与进化》作者说,C++的设计原则之一是,
要让C++能解决现实世界中的问题。以前我觉得C++好难学的,这么复杂的一门语
言,这么多语法规则,怎么记得住?读了他那句话以后,我再没有疑惑了,一个
再复杂的东西,它也是为了解决一个问题。如果你现在也碰到了同样的问题,你
就很容易理解C++里相应的部分;如果你还没有碰到问题,那你没必要太深地掌握
那一部分。更没必要不会不懂的情况下却还硬要去用相应的语言特性。
学了的东西,一定要用出来,用不上就没必要急着去学。不是所有的东西都要学
会的。学再多的东西,如果不用的话,慢慢就会忘记。
再举个例子,测试驱动开发,TDD的提倡者认为,写软件应该先写测试,再写真
正的程序。写一点测试,写一点程序,再写一点测试,再写一点程序。
有人问Don Knuth,你会这样做吗?Knuth说,我在熟悉一个系统的时候会这样
做,一旦我熟悉了之后我就不需要了。
这个故事告诉我们什么呢?留给您思考。
\subsection{读代码}
读代码是一门技术活。你必须有一个好的工具。不是光把文件打开,一行一行的
看就行的。如果某个功能支持的不够好你应该考虑换一个工具,或者甚至自己写
一个。不要对你的工具提不切实际的要求,比如,要求你的工具对任何代码,都
能找到某个函数的定义。这是不可能的。即使是很多人最爱的代码浏览器
“source insight”都不可能做到这点。能在大多数比如99\%的时候找到就应该算
可以了,剩下找不到的那百分之一有可能很重要,也有可能根本就是很隐蔽但不
重要。对这样的东西应该直接用最暴力的搜索,grep。《Linux Device Driver》
这本书的第一版前言里作者说,这本书是他花了好多小时grep内核源代码的成果。
这可以做为grep是多么有用的一个佐证。这也是对我影响最大的一句话之一。就
像打开了一扇门,哗一下,让你看见了,给你展示了,一个以前你从来不知道的
世界。其实应该说我刚读到这句话的时候不是特别明白,怎么用grep就能写出一
本书来呢,后来自己在阅读源代码的时候,想起了这句话,突然就明白了。读很
多书都会这样,第一次读没什么深刻的感觉,过一阵碰到一个问题时突然想起
来,那感觉会让你很,怎么说呢,说不上来。
最好的代码阅读工具应该是Vim或者Emacs这样的编辑器。因为你不可能只读代码
却不写、不修改。其次因为这些工具对其他工具的完美支持。用“source
insight”的话你不大可能自己去想办法解决一个代码阅读问题,你会非常依赖
它,你不想依赖都不行,因为它只提供了一个很弱的扩展功能。或者压根没有提
供?我不知道,我基本没怎么用过source insight。
有很多商业软件都是这样,它们提供第一眼看起来很好的功能,可是用久了之后
你就对它产生了依赖,无法摆脱它,也无法轻易超越它。这种软件的作者认为用
户是傻瓜,自己最聪明,自己一个人就可以把用户需要的任何东西全部实现,自
己一个人能面对用户会面对的任何问题,任何矛盾。这显然是不可能实现的。他
们不可能比所有人都聪明。当用户遇到一个他没有考虑到或者没法解决的问题
时,对不起了您哪,忍忍吧。
开放软件则不这样,他们对用户会遇到什么样的问题很少做假设,他们认为用户
是最聪明的,总能想出办法来解决问题。所以他们早就做好了这种准备。让用户
可以轻松的采用自己的解决办法,而不是设置重重障碍。
说到这里,要说到使用封闭、垄断型的软件还有一个严重的问题,那就是,即使
你能用它解决一个问题,你也只能用软件作者给你设计好了的方案。而开放软件
则不那样。它应该给你一些基本的解决方案,之后鼓励你自己去想出只属于你的
方案。Perl社区的格言就是,There Is More That One Way To Do It.
说着说着跑题了。
读代码的时候最大的问题,就是怎样提高阅读代码的速度。留给大家思考。(提
示,怎样写代码才能使代码更好阅读?)
\section{读文档}
文档啊,有很多的文档。开源软件社区里最重要的两种文档,一是man手册,另
一是info手册。
对这两种手册应该尽快熟悉,至少要知道其一般的结构。没错,文档是有结构
的,就像程序也都是一样。你要知道,写文档的人,他的目的不像写程序的人,
写程序的人最大的目标是解决问题,写文档的人,他最大的目的是想帮助看文档
的人。也就是你。你应该假设他是尽了他可能的努力来帮助你的。比如,他花了
些工夫,使他的文档具有某种结构,以方便读者,前提是你应该知道那些约定的
结构,而不是视而不见。
这个问题在那本书里面也有讲到,一本好书,它的作者绝对是花了很多时间去组
织它的结构,包括它的标题,章节,目录,索引。如果你读书只喜欢从头到尾的
读,那作者的努力就白费了。
标题,章节,目录,索引。它们的存在,就是为了鼓励你不要从头读到尾。就像
Perl格言说的那样,书也不应该只有一种读法。
有些时候,根本没有文档。有些时候找到一份文档,却发现作者根本只是在敷衍
了事。这时候没什么好办法。只要硬着头皮看。或者去联系作者,如果还能联系
得上的话。或者你应该自己去看代码,自己写一份更好的文档出来。如果这些都
不行的话,你就祈祷吧。
\section{创作}
终于说到创作、也就是编程了。说说我知道的一些基本原则吧。
\subsection{品味}
有人说过,最重要的问题,不是品味,是解决问题。把产品做出来,把项目按时
结束。我完全同意。很可惜的是,如果没有品味的话,是不可能完成那些的。
什么是品味呢?
“我是一个有品味的男人,我追求完美”。错了!那是广告词,那是骗人的!完
美,是伟大最大的敌人。追求完美的人,是有病的人,需要治疗。轻的自己治好
了,重的话得上医院。
人类都不完美,只有神是完美的。而我们是无神论者。对有神论者的人来说,更
不应该追求完美,那不是对神的亵渎了吗?有神论者应该勇敢承认自己的不完
美,让神原谅你就好了。无神论者呢?自己原谅自己吧。
追求完美,是人类的天性,我们应该克服这种本能。大多数情况下。完美并不存
在。上帝已死。追求完美,只能达到局部的完美,但那是病态的,会带来全局的
崩塌。
凡事做到八分好就很好了。这样你每件事都可以不需要很费劲。如果你事事都要
追求十分好,最后的两分会花去你额外80\%的精力。这就是老外们说的二八开原
理。边际效益。
Don Knuth说,Premature optimization is root of all evil。过早的优化是
万恶之源。什么样的人会过早的优化呢?很可能是追求完美的人。无知的人。
读书从头读到尾的人,也是追求完美的人。每个人都有追求完美的本能,一定要
克服这种本能。
写软件设想用户都是傻瓜,自己最聪明,自己是神的人,不用说,太完美了。把
用户会遇到的问题全解决掉,那得多累呢?最后还都失败告终。
品味,还包括用文本,而不是数据。文本也是数据,但那是人类可以读的数据。
使用二进制数据的人,有两类。一类是不相信文本,认为用自己设计的数据格式
能缩小存储需求。这类人犯了过早优化的毛病,也是追求完美。二类是希望用私
有二进制格式把用户锁定并垄断的人。这类人通常不得不设想用户是傻瓜,自己
都为用户解决任何问题。
看,这些道理都是相通的不是。
使用文本!使用文本!使用文本!
\subsection{海明码}
海明,贝尔实验室的,图灵奖获得者。海明码编码原则是越常用的信息编码长度
越短。
我看到Perl文档里提到了海明码,让我感悟良多。Perl语言里的关键字,my,
our, local,就是按照海明码的原则选定的。
谷歌为什么能挤掉雅虎?因为谷歌的搜索排序是越常被人引用的越排在前,符合
海明码的原则(与用户的距离越短了),而雅虎早期是人手工编辑排的。容易出
来不符合海明码的地方。最后就搞不过谷歌了。
在应该用命令行还是应该用图形界面这个问题上,也可以用海明码的原则去说明。
在图形界面上的一个很大的问题是,一个常用的命令,和一个不常用的命令,你
都得用鼠标去点,具体的步骤是:
\begin{enumerate}
\item 把手放到鼠标上
\item 移动鼠标
\item 光标对准到要点的地方
\item 点击
\end{enumerate}
这是图形界面最要命的地方。不符合海明码的原则。唯一的解决方案是提供快捷
键。但提供快捷键也完全不能从根本上解决这个问题。即使你提供对快捷键的定
制也解决不了。图形界面是很好上手没错,傻瓜都能用,所以搞垄断的软件厂商
最喜欢研究图形界面技术。但是,上手了之后呢?不支持海明码原则。没有提升
的空间。用户容易被锁死在里面,可悲的是,他们还很爱很爱图形界面。这就是
典型的斯德哥尔摩综合症。一个受害人爱上了绑架她的人。
这在一定程度上是可以弥补的,比如,同时支持命令行和图形界面的程序,以
及一些人机交互上的改进。
命令行就不一样了。很好的支持海明码原则。你知道ls命令吗?它的英文单词是
list,意思就是把文件给列一下。计算机先辈们觉得这么常用的命令打4个字受
不了,就缩短一点,变成ls了。
cd也不是让你听的光盘,是change directory,改变目录的缩写。rm是remove的
缩写。
如果你觉得先辈们选的还不够短,你喜欢缩得更短,用c来代表cd,请便。有病。
但是你绝对不能把东西缩没喽,0和1是我们说的最大的矛盾,记得呢?
同样的,如果你觉得某个复杂的,好几步的操作你经常要用到,那在命令行上简
单,你可以写一个脚本。几步就变成一步了,变短了,从违反海明码变得支持海
明码了。
品味和海明码关系是非常密切的。密切到这俩其实是一回事儿。
有品味的人知道,过早的优化是万恶之源。海明码的说法是,越常被使用的,越
需要短,也就是越需要优化。越常被使用的,你怎么知道是哪部分呢?所以就需
要先测量出来是哪部分,然后再优化。
有品味的人知道,我们应该多使用文本。在海明码那儿,你可以问问自己,作为
一个人类,你更常用文本,还是二进制数据呢?
没有品味的人做软件开发时,采用瀑布流程,逼客户把所有细节都敲定,这样他
才能把用户当做傻瓜,把自己装成神。懂海明码的人,知道什么是对客户最重要
的,越晚做出来风险就越大,他们采用迭代流程,先从value最大,risk最大的
部分入手。
从矛盾论的角度来说,也就是要抓住主要矛盾。道理,真的都是相通的。就看你
愿不愿意去思考。
有一篇文章,叫做《高效使用编辑器的七个习惯》,强烈推荐没有读的人读一
下,里面对如何用好海明码原则有一个很好的表述。
\subsection{不要闭门造车}
重复地发明轮子,没有什么好处。要理解、学习前人们遇到过的问题,这也是符
合海明码的规则的。前人们遇到过的问题,后人也会遇到,历史总是在重复。对
于这些经常重复的问题,我们应该让它们解决起来越来越快,这才是海明码的精
神。唯一的途径就是学习。
但是学习起来不要过了头,把前人的问题全研究完了再去解决自己的问题。那就
又犯了完美主义者的毛病。
所以最重要的是平衡。是思考。是自省。是哲学。
\section{后记}
我本来觉得,还有很多需要写的,可是再想想,好像已经没有什么了。说再多也
是没有用的。我本来想强调一下使用版本管理工具的重要性。可是版本管理工具
也只是海明码的一个表述。如果没有这个工具,人们只能自己手工管理版本。繁
琐而容易出错,而且是用得很频繁的。于是先辈们就想办法把这个问题优化了。
我们需要做的只是重视起来,看见问题,并使用先辈们已经提供的解决方案。
最害怕的是对问题视而不见。那样会导致我们失去很多机会。本来你可以成为解
决一个问题的第一人,结果错过,太可惜了。
如果找不着书看的话可以上电驴上下载。我和我以前的室友下载过上百个G的书。
看得快吐了都。
有空可以思考一下主要矛盾,次要矛盾,矛盾转化,软件开发,需求,变化等等。
推荐阅读毛**的《矛盾论》。《实践论》。
\end{CJK*}
\end{document}
%%% Local Variables:
%%% coding: utf-8
%%% mode: latex
%%% TeX-master: t
%%% End: |
|