一条计算机自学的路线图
from: http://t.uc.cn/YhNG
遇到很多同学,成绩还不错,但在计算机编程实践这个问题上老是不得其门。总结起来,原因很多。我这里尝试给出一些我以为可借鉴的方法和路线图。 先说在实践方面的方法问题。窃以为,工程思维中一个非常重要的能力是,自己给自己出题,然后验证。更进一步说,是能够将复杂问题分解为一些简单问题,并设计对应实验,各个击破,依次递增的能力。而设计实验,给自己出题,正是一直高中以来的教育所缺乏的东西。在应试教育中,题目都是别人出的,学生都是被动去想办法解决问题。殊不知,在实践中,遇到的问题往往是一个巨大的黑箱。如果缺乏分解黑箱,并进一步设计实验和问题去探索,就会一筹莫展。举个编程入门时的例子,有同学也很努力,照着书将代码敲了一万行。可心里非常虚,觉得自己依然无法解决实际问题,依然没有编程能力。甚至自己在很早之初时,也有类似问题。该怎么办呢?问题就是,自己不能给自己出题目,出刚刚合适的题目。并一点点递进。当你用照抄的方法熟悉了书上的算法后,就可以根据所学,立一个小程序项目,它包含了所学的东西。这样,将要做的东西既非陌生又非照抄的无主动性。在模仿的基础上一点点变动和变化的编程时最轻松,且最能烙印到心中成为自己的习惯的。
更具体说,
1 可以假想有班上同学的语文成绩需要统计(这时不要一来就统计7,8门成绩,叫简单到自己比较轻松,慢慢再增加难度),成绩先不保存到文件,只是键盘输入,统计其排名,正排,倒排,算平均数,这样,学的数据结构,排序等都能用上,而又非直接照抄书上例子。
2然后能,让输入的成绩存储到硬盘,这样又难一点点
3 将统计的成绩从一门课变成n门固定的课
4 然后,将第一步用的静态数组换成链表,动态数组,甚至为了查询的优化还换成b+树之类,但这些都是在内存中
5 将硬盘上存储的结构换成数组,链表,b+树之类
这个例子就是一个简单的展示,自己给自己出题的过程,每一步都比之前难一点点,这样难度递增,我们既能做出来,更有成就感,而有别于照抄书上例子,在新的环境中完成一些似曾相识的知识和技能,非常有利于锻炼技能本身。
总之,包含所学知识的命题,分解为多个难度和工作量递增的题目这就是我迈过实践初期困境的一种方法。也是后来学习新技术实践时采用的非常有效的方法。
要完成以上的分解,自己出题就需要一种习惯。必须逼迫自己去分解,切勿懒惰。因为习惯了从小以来的被动做题,要自己去立题了,往往不知所措。这更多是习惯,不是能力。
另外,在立题方面,我采用了三种难度不同的方法来实践,如何采用,则看心情,能力和时间。比如,我原来学习windows核心编程时。我会这样做:
1 在不想太动作的时候,看懂了,自己凭理解和记忆重写书上的例子。有记不清的看看,然后复写。这是主动性最低的一种,在时间少,兴趣不高时采用。
2 将书上例子理解后,改动下,变一下,比如增加点功能,修改显示的大小,字串的名字等等,这个比1要更调动主动性些。
3 理解了某些内容,综合起来设计一个案例覆盖知识点。比如看到内存管理那章,我发现这些技术和游戏修改器相关,就实现了一个简单的修改器。这样的难度高,综合性强,调动主动性高,又很有意思和成就。我比较喜欢这种玩法。在这当中就遇到了依次遍历字节速度慢的问题,这是立题时未想到的。后来通过分析对齐原理,解决了该问题。另外,学习跨进程通讯时,就设计了一个两个进程聊天的程序,也很好玩。
最后一个问题是心态问题,自己搞出来的必然和别人指出的不同。所以,要尽全力忍受憋闷去检查出哪怕一个逗号的错误。心态的转换,训练出细心的态度和方法,就是在这些看似枯燥无聊的煎熬中熬出来的。知识也就是在这样的熬制中融合到自己内心,变成了可以解决问题的思维模式,或者称为能力。我以前刚开始做windows程序时,头三天不断请教同寝室的好友,可后来觉得这不是个办法,毅然不再询问,全部靠自己琢磨,那时没有网络可用,只有一本简单的入门书,一周以后,各种怪问题和错误就不再犯了。所以,决心很重要。
下面开始谈谈路线图的问题:
我的经验中,也许能分成几个阶段:
1 筑基 代码量培养程序感觉。 没有程序感觉,其它免谈。这里有一个语言选择的问题。本质上,选哪个都没有关系。但为了方便切入第2阶段,建议用能嵌入汇编,有指针的语言较好。c/c++是一个不错的选择,我当年用的是delphi。这一阶段应该有1两万行代码为妥。其中,至少应该包含一个比较复杂功能的软件的编写,有3~4千行左右。比如做一个背单词的程序,做一个贪吃蛇,做一个画板之类。
2 修内功 培养系统观,特别底层观。这里有正向构建和逆向析构两种方式,可单独一个方向,也可两者结合。构建式,就是自己做一个操作系统(参考自己动手做操作系统),做一个编译器,做一个数据库(麻省理工有一个数据库实现的教材)。这并非高不可及,我带过的学生,在一年级就做出来了,甚至有的是在arm下实现的,。下面主要谈谈逆向析构式。它通过逆向,反汇编,系统机制的学习建立其坚固的系统观。并且培养其良好的工程思维模式,以及一套好用的微观级工具集(比如od,ida,peview,winhex等)。这个阶段主要从逆向入手,我不太建议从加解密入手,从攻防入道是一个有趣而更宽泛的领域。开始,不要一下就切入逆向领域。要了解系统机制,所以《windows核心编程》就是一本好书,用我前面所谈方法做一次(非读一次)。然后,拙著《老码识途》可做入门选择,其优点在于如图实验手册,非常细,且贯穿了一种“猜测,实证和构建”的工程思维训练。可谓一举两得。中间,《深入理解计算机系统》,《c++反汇编解密》,《加密与解密》也不错,可进阶学习。有了这些基础后,从病毒和溢出攻击入手能非常有趣和有深度。我刚开了门病毒课,其中有50个实验加700页ppt,可以作为实操的指导。到时候挂出来,可供参考。另外,我《信息对抗技术》课程的ppt有一章专门讲溢出攻击的实操,也可以作为案例。我比较鼓励在这一阶段,用逆向分析各种黑箱的东西,但千万不要一来就杀入破解,那里面有太多抗破解的东西,阻碍我们顺利分析,破坏了我们建立逆向分析观的进程,除非你太爱破解。这一阶段,重要的系统机制,我以为有异常处理机制(应自己实现异常处理),调试机制(要编一个调试器),进程间通讯机制,钩子机制,链接机制(可参考程序员的自我修养,老码识途等,另外,将来我会给一个教程编写链接器),程序加载机制。我会慢慢整理逆向析构的系统培养方式,到时候在发布出来。
3 套路与实战 软件模式和架构感的培养。该阶段有了大量的代码积累,能够理解重用和重复的问题,学会用设计模式的方式看待分解系统,能够构建良好架构的软件。这个阶段,可用调构学习法(老码识途第7章给出了案例)学习你感兴趣的框架,比如自己做一个hibernate,并分析hibernate改善自己的设计。这个阶段,阅读,调试,模仿优秀代码是一个关键。
4 返璞归真 系统与算法的紧密结合阶段。真正掌握经典算法,能利用好系统的特性,最大限度发挥算法的能力。只沉迷纯粹的算法不是计算机专业人士的王道,那是数学家的王道。曾听过一个故事,某游戏优化算法,一堆数学家一直没搞好,一个老程序员用了一个月搞定了。利用了计算机系统特性的算法,才是最有效的算法。比如存储,磁盘介质就需要电梯算法,就需要数据尽量放在一起,而对于固态盘,完全又是另外一回事。
最后,在多说一下,那些徘徊在门口的同学,不要将希望寄托在所谓的氛围上,寄托在高手的帮助上。要相信自己。当你确实有点无助时,可以采用一下我说的方法,也许对你有帮助。也欢迎大家讨论和交了。
更具体说,
1 可以假想有班上同学的语文成绩需要统计(这时不要一来就统计7,8门成绩,叫简单到自己比较轻松,慢慢再增加难度),成绩先不保存到文件,只是键盘输入,统计其排名,正排,倒排,算平均数,这样,学的数据结构,排序等都能用上,而又非直接照抄书上例子。
2然后能,让输入的成绩存储到硬盘,这样又难一点点
3 将统计的成绩从一门课变成n门固定的课
4 然后,将第一步用的静态数组换成链表,动态数组,甚至为了查询的优化还换成b+树之类,但这些都是在内存中
5 将硬盘上存储的结构换成数组,链表,b+树之类
这个例子就是一个简单的展示,自己给自己出题的过程,每一步都比之前难一点点,这样难度递增,我们既能做出来,更有成就感,而有别于照抄书上例子,在新的环境中完成一些似曾相识的知识和技能,非常有利于锻炼技能本身。
总之,包含所学知识的命题,分解为多个难度和工作量递增的题目这就是我迈过实践初期困境的一种方法。也是后来学习新技术实践时采用的非常有效的方法。
要完成以上的分解,自己出题就需要一种习惯。必须逼迫自己去分解,切勿懒惰。因为习惯了从小以来的被动做题,要自己去立题了,往往不知所措。这更多是习惯,不是能力。
另外,在立题方面,我采用了三种难度不同的方法来实践,如何采用,则看心情,能力和时间。比如,我原来学习windows核心编程时。我会这样做:
1 在不想太动作的时候,看懂了,自己凭理解和记忆重写书上的例子。有记不清的看看,然后复写。这是主动性最低的一种,在时间少,兴趣不高时采用。
2 将书上例子理解后,改动下,变一下,比如增加点功能,修改显示的大小,字串的名字等等,这个比1要更调动主动性些。
3 理解了某些内容,综合起来设计一个案例覆盖知识点。比如看到内存管理那章,我发现这些技术和游戏修改器相关,就实现了一个简单的修改器。这样的难度高,综合性强,调动主动性高,又很有意思和成就。我比较喜欢这种玩法。在这当中就遇到了依次遍历字节速度慢的问题,这是立题时未想到的。后来通过分析对齐原理,解决了该问题。另外,学习跨进程通讯时,就设计了一个两个进程聊天的程序,也很好玩。
最后一个问题是心态问题,自己搞出来的必然和别人指出的不同。所以,要尽全力忍受憋闷去检查出哪怕一个逗号的错误。心态的转换,训练出细心的态度和方法,就是在这些看似枯燥无聊的煎熬中熬出来的。知识也就是在这样的熬制中融合到自己内心,变成了可以解决问题的思维模式,或者称为能力。我以前刚开始做windows程序时,头三天不断请教同寝室的好友,可后来觉得这不是个办法,毅然不再询问,全部靠自己琢磨,那时没有网络可用,只有一本简单的入门书,一周以后,各种怪问题和错误就不再犯了。所以,决心很重要。
下面开始谈谈路线图的问题:
我的经验中,也许能分成几个阶段:
1 筑基 代码量培养程序感觉。 没有程序感觉,其它免谈。这里有一个语言选择的问题。本质上,选哪个都没有关系。但为了方便切入第2阶段,建议用能嵌入汇编,有指针的语言较好。c/c++是一个不错的选择,我当年用的是delphi。这一阶段应该有1两万行代码为妥。其中,至少应该包含一个比较复杂功能的软件的编写,有3~4千行左右。比如做一个背单词的程序,做一个贪吃蛇,做一个画板之类。
2 修内功 培养系统观,特别底层观。这里有正向构建和逆向析构两种方式,可单独一个方向,也可两者结合。构建式,就是自己做一个操作系统(参考自己动手做操作系统),做一个编译器,做一个数据库(麻省理工有一个数据库实现的教材)。这并非高不可及,我带过的学生,在一年级就做出来了,甚至有的是在arm下实现的,。下面主要谈谈逆向析构式。它通过逆向,反汇编,系统机制的学习建立其坚固的系统观。并且培养其良好的工程思维模式,以及一套好用的微观级工具集(比如od,ida,peview,winhex等)。这个阶段主要从逆向入手,我不太建议从加解密入手,从攻防入道是一个有趣而更宽泛的领域。开始,不要一下就切入逆向领域。要了解系统机制,所以《windows核心编程》就是一本好书,用我前面所谈方法做一次(非读一次)。然后,拙著《老码识途》可做入门选择,其优点在于如图实验手册,非常细,且贯穿了一种“猜测,实证和构建”的工程思维训练。可谓一举两得。中间,《深入理解计算机系统》,《c++反汇编解密》,《加密与解密》也不错,可进阶学习。有了这些基础后,从病毒和溢出攻击入手能非常有趣和有深度。我刚开了门病毒课,其中有50个实验加700页ppt,可以作为实操的指导。到时候挂出来,可供参考。另外,我《信息对抗技术》课程的ppt有一章专门讲溢出攻击的实操,也可以作为案例。我比较鼓励在这一阶段,用逆向分析各种黑箱的东西,但千万不要一来就杀入破解,那里面有太多抗破解的东西,阻碍我们顺利分析,破坏了我们建立逆向分析观的进程,除非你太爱破解。这一阶段,重要的系统机制,我以为有异常处理机制(应自己实现异常处理),调试机制(要编一个调试器),进程间通讯机制,钩子机制,链接机制(可参考程序员的自我修养,老码识途等,另外,将来我会给一个教程编写链接器),程序加载机制。我会慢慢整理逆向析构的系统培养方式,到时候在发布出来。
3 套路与实战 软件模式和架构感的培养。该阶段有了大量的代码积累,能够理解重用和重复的问题,学会用设计模式的方式看待分解系统,能够构建良好架构的软件。这个阶段,可用调构学习法(老码识途第7章给出了案例)学习你感兴趣的框架,比如自己做一个hibernate,并分析hibernate改善自己的设计。这个阶段,阅读,调试,模仿优秀代码是一个关键。
4 返璞归真 系统与算法的紧密结合阶段。真正掌握经典算法,能利用好系统的特性,最大限度发挥算法的能力。只沉迷纯粹的算法不是计算机专业人士的王道,那是数学家的王道。曾听过一个故事,某游戏优化算法,一堆数学家一直没搞好,一个老程序员用了一个月搞定了。利用了计算机系统特性的算法,才是最有效的算法。比如存储,磁盘介质就需要电梯算法,就需要数据尽量放在一起,而对于固态盘,完全又是另外一回事。
最后,在多说一下,那些徘徊在门口的同学,不要将希望寄托在所谓的氛围上,寄托在高手的帮助上。要相信自己。当你确实有点无助时,可以采用一下我说的方法,也许对你有帮助。也欢迎大家讨论和交了。