2008年11月21日星期五

编程学习初体验(5. 如何自学编程)(3)

3 少量项目实践--自学和上学的区别
有句老话叫做学以致用,说的是如果不是为了用而学,是没有意义的; 同样,在用中学才能真正的掌握学到内容。编程跟着书本走,入书之后终究需要脱离书本,做到“出书”。这是自学编程和科班学习的分水岭所在。自学编程的朋友往往走到这步就难以继续前进了,一方面是从这步开始就需要自己摸索,而没有具体那本书可以带着你往前走。

之前我说到基础知识很重要,但是我并不是说如果能把那几本基础书顺背倒背了基础就扎实了。 为了真正理解和掌握书上的知识, 在读完这些书之后,入门的读者应该去做一些实际的代码,或者是程序。我在这里说的是代码和程序,而不是软件。这三者是很不同的。 在最初的时候,你可能只会写一个main函数的程序,其实这只能叫做代码(code)而已。 如果你开始能写由多个函数构成的程序了, 这个时候你才能算是知道程序是怎么回事了。在此之后,你可能会尝试写由多个源文件和头文件构成的程序,这时你可以算是开始入门了。 最后你可能会要写有多个不同功能部件组成的程序,每个部件可能是独立的一个程序模块, 放在不同的目录里面,有不同的接口。这才是程序的现实模样。 但是这和软件还是有差距的。 在这里我不想去探讨软件和程序之间的区别,因为已经有太多的定义和讨论。而且当你到了最后一步的时候,自然就明白这两者的差距了。

那么应该自己尝试写一些什么样的“程序”?从我自己的经历来说,我建议以下的几种:
1. 数据结构的基本操作,例如写一个酒店的客人住宿登记系统,当客人到来的时候可以让客人挑选不同的空闲房间。这个实际上就是一个简单的数据结构的查询,修改程序;比如你可以用链表来维护所有的房间信息, 然后把客人作为第二维的链表挂在各个房间下面。
2. 算法的优化,性能的提高。同样在上面的例子中,除了可以让客户方便的查询当前空闲的房间外,如何同时能快速的查找到已经登记了的各位顾客的信息。如何快速的修改或者取消客户的预订? 这些就要求相对复杂的对数据结构操作的技巧了。此外还有如何有效的利用系统的内存,比如程序自己维护一个用户信息数据池,当用户退订房间后,该客户的信息暂时先放入这个池中,等需要一个新的信息记录的时候,就不用再去申请内存块而是直接从这个池中获取已经回收的内存。这种内存管理机制会在今后的程序开发中被很广泛的用到。 尤其是在开发大规模的程序里面。你对这方面越是熟练, 你开发出来的程序的性能越是可靠(别人的程序处理每分钟几千个请求的时候就相应不过来了,你的程序可以轻松的支持上万个请求,你说客户会用谁的软件?)
3. 程序风格的改进:基本的分层,注释,名称使用习惯方面的考虑。这部分当你有了写一些大型程序的经验的时候就会有比较深的感受了。当程序规模比较大的时候, 程序逻辑的划分,变量的命名都会成为影响代码质量的重要非技术性因素。举个例子, 如果你把变量取名成 a,b c. 等你的程序写到几百行时候, 你肯定会记不清想用的某个变量到底叫什么名字,因而会很频繁的翻页回去看,一方面造成了你思路的中断,另外一方面特别容易让人大脑疲劳。如果你把名字取成 queueLen, queneCap, 这类的话, 虽然写的时候麻烦一点,但是很容易深入人心。此外面向对象的封装技术,以及一个好的集成开发环境 IDE都能帮助你提高效率,减缓疲劳。

以上三点中,1是对数据结构知识的巩固和加强,2是对算法分析和设计的初步尝试 3是对软件工程的重要性的了解。因此对以后的相关知识点巩固和深化有比较直观的影响。这一阶段的重要性往往在于在这个过程中所获得的个人的心得体会,而非技术上的进步。因此几乎没有书可以给你一个有形的指导,而一个有经验的“前人”如果能在这个阶段和你交流和探讨,就往往可以给你带来飞跃性的提高。

2008年11月7日星期五

编程学习初体验(5. 如何自学编程)(2)

这几天七七八八,也不知道自己在忙什么。似乎就是没心情继续到这里写东西。打了几天游戏,用java写了一个网络仿真软件用来测试p2p设计的性能,改改小bug,时间就这么过去。 希望没人在这里等我的下文,不然就惭愧死人了。

言归正传,回来继续讲我们的正题。 翻翻前面的帖子,对于数据结构和算法,我已经啰嗦了一堆他们的重要性。接下来改说哪本数据结构或者算法的书写得好把,看看网上这类的帖子文章已经论斤卖了,再写也没多少意义了。况且自己不是算法狂人,所看过的算法书也就那么基本粗浅的而已,自然不敢出来挨砖。想想能拿出来和大家分享的,依然是自己的一些看法和认识而已。

数据结构和算法

算法这两字其实到今天我还是稀里糊涂的,每次读算法书,前言或者序言第一句话肯定就有定义。反正本科看了一回,硕士的时候学算法又看了一回。至今好像也没再看过第三回。也不记得书上是怎么定义的,发展觉得就是特经典,精辟的那种,但是过眼就记不得。没事和朋友吹牛的,三句话不离本行,十句话肯定是不离算法的:大部分口水是为“算法”喷的;码的代码大多数也是在解决算法问题。 但是对于算法到底是啥,我却不愿意深究其定义,因为我知道揪出来也没意义,它能基本涵盖一个程序员所有的有用功——就好像你问人吃啥,他说吃饭, 你绝对不会去再问一句饭吃的啥了。

在这里,我有兴趣做的,倒是如何把算法和数据结构来个“实用性”分类。所谓实用性就是我不在乎分的对不对,靓不靓,只从合乎情理来分。从对算法和数据结构的逐步深入理解来分,可以分为这么三类:
(1)基本数据结构和基础算法:编程语言和数据结构,针对对编程语言的掌握
(2)通用算法:针对理论问题的探讨
(3)专用算法:金融,路由
这也对应三个不同学习和使用算法和数据结构的阶段。 虽然这分法有点老土,但是也是经过我也是仔细琢磨,觉得最合情理的分法。 首先(1)明显区别与(2)(3):前者是“就事论事”,属于掌握编程语言的内容,换句“课堂用语”来说就是为了解决编程实现域中知识技能;后两者是为了解决实际应用问题,属于“应用域”。会了(1),你就基本掌握了啥是编程了,会了(2)(3)你才算是有点“生产力”,能挣公分了。(1)是大多数学计算机的人所要关注的,而其他学科未必注重这个。(2)主要是计算机做理论方面的人在捣鼓 ,和一些职业的应用数学家(3)则是渗透到各个行业中了。 所以能掌握(3)的人是各行业里赚钱的;会(2)的人呢小康是有保障属于技术工种;。剩下的只会(1)的人,就是标榜为IT民工的各位了。这也就是为什么大家都说做IT都是打工的,只能给其他行业的人当枪使。事实也的确如此,大多数人从科班出身人,能把(1)能真正掌握做好就不多,(2)就需要去花很多的时间去看什么《算法的艺术》 《算法导论》和有相对比较好的数学底子了。(3)就往往需要在计算机之外有数学的功力和行业的背景知识了。所以说,时下流行的:少壮不努力,老大做IT,也是有一定道理的。

上面这堆废话对已经入行的朋友没有什么意义,大家就权且一笑;但是如果正准备开始学习编程,那还是应该把这些记在心里的。很多时候,决定你以后发展的并不是你学的是什么,而在于你对全局的把握。这也是我废话这么多的初衷。

言归正传, 如何学好第一步。答案很简单,也很让人失望: 学好算法和数据结构的最好办法就是把所学的背下来,默写出来。这有点类似英语学习,基本功就是背单词和句型。之所以强调要背要默的原因,第一是由于这是以后的基础;第二是以后再也不会有这样的机会让你来做这些基础功课。这点上往往是科班程序员和票友程序员之间的分水岭。科班程序员大多在入门的时候被老师逼着去做这样那样的功课, 虽然不情愿但是这些基本功对以后的确意义重大;票友程序员往往没有这样的压力, 在学习中回避这些基本功,其结果也是人浮于事,之后的内容也学不进去。 这里说说我当时的学习。我的数据结构老师很不错,上课用的是南加州大学的老教程,我喜欢把里面的例程算法都仔细看透,琢磨是否可以优化。做作业的时候是我最惨的时候。当时软盘都很少用, 程序都是自己写在作业本上交老师批改的。 女孩子们喜欢打草稿,反正他们的作业都干净要命。我是粗线条那种, 不喜欢做门面功夫,那就得力求一次性在作业上把程序从头到尾都一次写出来。这当然不可能了, 即便在计算机上编程,也不可能一次性把整个程序都写出来。所以我的本子总是涂涂改改的特别恶心。 成绩当然不高,即便程序是对的,老师也不愿意给如此恶心的作业打高分。 为了提高成绩,只能少涂改,那只能要求我自己在脑子里面进行“脑中作业”,因为上机的时间实在是不多,还得自己花钱买上机票。另外一个办法就是背住所学的算法, 背住的越多,脑中作业的脑力花费越少。于是这无形中极大强化了我对算法的掌握。后来我看其他同学做作业都要翻书抄书上的例程再改就很不屑, 因为我做作业的时候从来不打开书的。 考试的时候是开卷,我就很牛逼的连书都不带哗哗哗的写完交卷,爽!后来在学算法设计,操作系统,编译原理和计算机图形学的时候,我基本都是把书上的伪代码实现出来,写成完整的系统(现在回想当年花了3个星期实现一个pascal编译器,真是太痛苦了,后来知道有lex和yacc,真是郁闷了很久)。不过这些东西到现在对我来言都是极大的资本。

其次,我还想在这个话题下多说一句: 不要为了算法去专业算法。很多年轻人总是在我面前炫耀自己读完了《算法导论》第几卷,里面某某算法设计多难,自己都看懂了。但是我绝对不建议任何年轻的程序员去看这种书。原因有二: 第一,这种书属于(2)的范畴,需要了解,但是不需要去啃懂每个算法,好比是新华字典,对每个中国人都很重要,但是那是工具书,没人会去把整本啃完,没有意义;第二,做编程这行,变化太快,等印在纸上了,那些都已经是过时的死东西了,等你啃完前人的骨头了,你也差不多该作古了。

2008年11月4日星期二

编程学习初体验(5. 如何自学编程)(1)

注: 这个帖子原本打算把整个第五部分都一次写下来,但是在整理思路的时候发现想写和可写的东西太多,难以一次成文。思考再三还是分成多段来写,自己也不用太累,也不至于一次写出来太过匆忙而恶心到各位。

如何学习编程也是见仁见智的话题。每个人都有自己的特点, 因此不存在一条放之四海而皆准的道路。在这里我所能贡献的也仅仅是从我自己的经历得来的一点见解。希望能给刚刚入门的朋友提供一些有益参考,避免不必要的弯路,这也是我写了这么多的目的。为了能给删繁就简,我把我设想的的学习道路概括为一条step by step的路,让各位捧场的朋友有个直接明确的理解。在实际学习过程中, 并没有这样一条一路走到底的途径,而是不断反复温故而知新的过程。

Step 1. 基础学习---找本好书
入门,尤其是自学,一本好的入门书是很重要的。 不同基础的读者应该选择不同的书来学习。如果是没有任何基础的读者,应该找一本薄的,浅显的讲基本语法的书作为入门,而不该挑厚的“宝典”或“圣经”。 因为,厚的书没有几个初学者能真正吃下来,往往把人吓回去或者半途而废。如果是C语言和C++,谭浩强的那两本书还是不错的。不少高手都骂这两本书写的臭,但是从入门来看,这两本还是很合适的。 C语言还有一本是 《C programming》,也是很不错的一本入门书,而且只有100页的样子,很薄,作者是unix的设计者,书中结合了不少unix设计中的例子,很有实用性。但是我自己的感觉是这本书有点太凝练了,除非一字一字的去体会,否则初读这本书根本没法感悟出作者要表达的C语言的精髓。 对于Java语言,我觉得Sun网站上的在线教程 Java tutorial是最好的,很简单实用,其次就是《Think in Java》, 适合作为初级的进阶读物。
反面的例子就是我读过的《MFC深入简出》 《Windows programming with MFC 》和《Windows programming》,这三本书我最初读了不下10遍,但是每次都没突破过200页就放弃了。这些书在后来我的编程学习中觉得的确是经典,但是如果作为入门书籍绝对是误人子弟的。所以,对于没有任何基础的初学者而言入门最好是找本薄的,简单的书来入门,我学C++的入门书是《一周学会C++》,就60页厚。现在看来那本书里面很多对C++的说明都是不准确甚至是错误的,而且里面对于泛型和STL都没有介绍到。但是这样的书特别管用,让读者在尽可能短的实际里面能对一门语言的主要概念有一个全面的了解。这点是那些经典之作所做不到的。 另外选择这些书的一个原因是这些书往往因为其粗浅或者过时,可以很容易借到或者在旧书摊上找到,便宜实惠,物美价廉。而且这些书都没有收藏价值,等你真正上路之后没有任何作为工具书的价值,所以尽量不要花冤枉钱,就好像没有人会收藏自己当年的奶瓶一样(有变态嗜好的人除外)。

2008年11月1日星期六

编程学习初体验(4. 编程的核心)

初学编程的朋友,总觉得写程序是件单纯的事情:知道如何使用一种语言,熟悉一个开发环境,了解系统的编程接口(API)就已经能够成为一个合格的程序员了。在我刚刚接触编程学习的时候,我也是这么认为的。这种认识不是没有根据的。在我有这样的认识的时候,我已经会用basic写一些小程序,甚至照葫芦画瓢写了一些游戏动画界面了。在上个世纪末所谓的计算机的“游侠”时代,这个看法是有其合理性的;但是今天回过头来看,这些最初的认识实在是肤浅的。今天软件开发已经成为一个成熟的行业,因此如果想在这个行业中生存,核心竞争力是必须的。学会一种语言,熟悉一个开发环境,掌握API的程序员永远只能位于这个大厦的最下层,仅仅比程编程爱好者强一些。如果想摆脱这个局面,就得知道哪里才是这个行业的核心。
软件行业,就其功能而言就是一个工具行当,和会开车的司机,会开机器的工人没有什么区别。因此仅仅作为工具的操作者, 一个程序员是不值钱的,因为他只是一个更为高级的工具。一个有身价的程序员他之所以值钱,是在于他的创造力。程序员的创造力并不在于会画个界面,会用开发环境什么;而在于他对计算机这个行当的根本的掌握。 计算机是应用数学和电子工程上派生出来的一个果子。因此程序员的核心竞争力在对数学和硬件知识的掌握。因此这个世界上只有两种程序员永远不会待业,那就是算法高手和硬件高手。 但是对于软件专业出身的程序员来说, 算法是最核心的竞争力。我和很多程序员相处过,交流过。他们中的大多数都有对失业的担心,即便是已经在大公司从业了很多年的程序员: 软件技术发展日新月异,没人能永远跟住技术发展的脚步,总有会被淘汰的时候。 但是那些着眼于算法的程序员大多没有这种忧虑,年龄的增长只能让他们更加有经验,变得更吃香。我认识的一个做图像处理的朋友,写出来的程序一点可读性都没有,而且很不规范,动不动就crash了。但是老板无论换谁,都不会换他,因为他的算法性能高,能实现别人不能实现的图像检测能力。而那些帮他改程序,写注释的“职业”程序员, 尽管写出来的程序正规工整,但是工资涨不了多少,而且还得担心哪天就开路了。 相比之下, 可见一斑。
因此,学习编程的朋友们,不要去太过追求和写代码相关的能力,抱着本MFC手册当宝典了,而是应该耐心下来关注最基础的数据结构和算法,把他们搞透玩熟。这是基础中的基础,核心中的核心;没有这些,以后的会很难得到提高。而且这些基础可能在以后的十几二十年里面,你都不会再会有时间和精力去重新扎扎实实学一遍了。
此外,我还想补充一点。是不是这么说软件工程就没必要去学了? 软件工程是计算机科学中比较偏向工程方面的一个比较新的分支,对于开发而言也是至关重要。因此这个肯定是要学,而且要学好,此外在工程上,程序框架,类库的掌握,都是必须的知识。 但是掌握这些知识只能让人成为一个合格或者出色的工匠, 但是永远成为不了一个有创造力的大师。这个社会上,工匠成千上万,多你一个不多,缺你一个不少;但是大师却是寥寥无几。在计算机行业,更是如此。